Skip to content

Commit 6c6e323

Browse files
authored
Add configurable base plugin support in buf.plugin.yaml (#3513)
1 parent f93c18a commit 6c6e323

File tree

7 files changed

+719
-646
lines changed

7 files changed

+719
-646
lines changed

private/bufpkg/bufremoteplugin/bufremoteplugin.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ func PluginRegistryToProtoRegistryConfig(pluginRegistry *bufremotepluginconfig.R
133133
case pluginRegistry.Go != nil:
134134
goConfig := &registryv1alpha1.GoConfig{}
135135
goConfig.MinimumVersion = pluginRegistry.Go.MinVersion
136+
if pluginRegistry.Go.BasePlugin != nil {
137+
goConfig.BasePlugin = pluginRegistry.Go.BasePlugin.IdentityString()
138+
}
136139
if pluginRegistry.Go.Deps != nil {
137140
goConfig.RuntimeLibraries = make([]*registryv1alpha1.GoConfig_RuntimeLibrary, 0, len(pluginRegistry.Go.Deps))
138141
for _, dependency := range pluginRegistry.Go.Deps {
@@ -249,6 +252,13 @@ func ProtoRegistryConfigToPluginRegistry(config *registryv1alpha1.RegistryConfig
249252
case config.GetGoConfig() != nil:
250253
goConfig := &bufremotepluginconfig.GoRegistryConfig{}
251254
goConfig.MinVersion = config.GetGoConfig().GetMinimumVersion()
255+
if config.GetGoConfig().GetBasePlugin() != "" {
256+
basePluginIdentity, err := bufremotepluginref.PluginIdentityForString(config.GetGoConfig().GetBasePlugin())
257+
if err != nil {
258+
return nil, err
259+
}
260+
goConfig.BasePlugin = basePluginIdentity
261+
}
252262
runtimeLibraries := config.GetGoConfig().GetRuntimeLibraries()
253263
if runtimeLibraries != nil {
254264
goConfig.Deps = make([]*bufremotepluginconfig.GoRegistryDependencyConfig, 0, len(runtimeLibraries))

private/bufpkg/bufremoteplugin/bufremotepluginconfig/bufremotepluginconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ type RegistryConfig struct {
120120
type GoRegistryConfig struct {
121121
MinVersion string
122122
Deps []*GoRegistryDependencyConfig
123+
BasePlugin bufremotepluginref.PluginIdentity
123124
}
124125

125126
// GoRegistryDependencyConfig is the go registry dependency configuration.
@@ -440,6 +441,7 @@ type ExternalGoRegistryConfig struct {
440441
Module string `json:"module,omitempty" yaml:"module,omitempty"`
441442
Version string `json:"version,omitempty" yaml:"version,omitempty"`
442443
} `json:"deps,omitempty" yaml:"deps,omitempty"`
444+
BasePlugin string `json:"base_plugin,omitempty" yaml:"base_plugin,omitempty"`
443445
}
444446

445447
// ExternalNPMRegistryConfig is the external registry configuration for a JavaScript NPM plugin.

private/bufpkg/bufremoteplugin/bufremotepluginconfig/bufremotepluginconfig_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ func TestGetConfigForBucket(t *testing.T) {
4040
require.NoError(t, err)
4141
pluginDependency, err := bufremotepluginref.PluginReferenceForString("buf.build/library/go:v1.28.0", 1)
4242
require.NoError(t, err)
43+
basePluginIdentity, err := bufremotepluginref.PluginIdentityForString("buf.build/library/go")
44+
require.NoError(t, err)
4345
require.Equal(
4446
t,
4547
&Config{
@@ -54,6 +56,7 @@ func TestGetConfigForBucket(t *testing.T) {
5456
Registry: &RegistryConfig{
5557
Go: &GoRegistryConfig{
5658
MinVersion: "1.18",
59+
BasePlugin: basePluginIdentity,
5760
Deps: []*GoRegistryDependencyConfig{
5861
{
5962
Module: "google.golang.org/grpc",
@@ -82,6 +85,8 @@ func TestParsePluginConfigGoYAML(t *testing.T) {
8285
require.NoError(t, err)
8386
pluginDependency, err := bufremotepluginref.PluginReferenceForString("buf.build/library/go:v1.28.0", 1)
8487
require.NoError(t, err)
88+
basePluginIdentity, err := bufremotepluginref.PluginIdentityForString("buf.build/library/go")
89+
require.NoError(t, err)
8590
require.Equal(
8691
t,
8792
&Config{
@@ -96,6 +101,7 @@ func TestParsePluginConfigGoYAML(t *testing.T) {
96101
Registry: &RegistryConfig{
97102
Go: &GoRegistryConfig{
98103
MinVersion: "1.18",
104+
BasePlugin: basePluginIdentity,
99105
Deps: []*GoRegistryDependencyConfig{
100106
{
101107
Module: "google.golang.org/grpc",

private/bufpkg/bufremoteplugin/bufremotepluginconfig/config.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package bufremotepluginconfig
1717
import (
1818
"errors"
1919
"fmt"
20+
"slices"
2021
"strings"
2122

2223
"buf.build/go/spdx"
@@ -60,7 +61,7 @@ func newConfig(externalConfig ExternalConfig, options []ConfigOption) (*Config,
6061
dependencies = append(dependencies, reference)
6162
}
6263
}
63-
registryConfig, err := newRegistryConfig(externalConfig.Registry)
64+
registryConfig, err := newRegistryConfig(externalConfig.Registry, dependencies, opts.overrideRemote)
6465
if err != nil {
6566
return nil, err
6667
}
@@ -87,7 +88,11 @@ func newConfig(externalConfig ExternalConfig, options []ConfigOption) (*Config,
8788
}, nil
8889
}
8990

90-
func newRegistryConfig(externalRegistryConfig ExternalRegistryConfig) (*RegistryConfig, error) {
91+
func newRegistryConfig(
92+
externalRegistryConfig ExternalRegistryConfig,
93+
pluginDependencies []bufremotepluginref.PluginReference,
94+
overrideRemote string,
95+
) (*RegistryConfig, error) {
9196
var (
9297
isGoEmpty = externalRegistryConfig.Go == nil
9398
isNPMEmpty = externalRegistryConfig.NPM == nil
@@ -125,7 +130,7 @@ func newRegistryConfig(externalRegistryConfig ExternalRegistryConfig) (*Registry
125130
options := OptionsSliceToPluginOptions(externalRegistryConfig.Opts)
126131
switch {
127132
case !isGoEmpty:
128-
goRegistryConfig, err := newGoRegistryConfig(externalRegistryConfig.Go)
133+
goRegistryConfig, err := newGoRegistryConfig(externalRegistryConfig.Go, pluginDependencies, overrideRemote)
129134
if err != nil {
130135
return nil, err
131136
}
@@ -242,14 +247,18 @@ func newNPMRegistryConfig(externalNPMRegistryConfig *ExternalNPMRegistryConfig)
242247
}, nil
243248
}
244249

245-
func newGoRegistryConfig(externalGoRegistryConfig *ExternalGoRegistryConfig) (*GoRegistryConfig, error) {
250+
func newGoRegistryConfig(
251+
externalGoRegistryConfig *ExternalGoRegistryConfig,
252+
pluginDependencies []bufremotepluginref.PluginReference,
253+
overrideRemote string,
254+
) (*GoRegistryConfig, error) {
246255
if externalGoRegistryConfig == nil {
247256
return nil, nil
248257
}
249258
if externalGoRegistryConfig.MinVersion != "" && !modfile.GoVersionRE.MatchString(externalGoRegistryConfig.MinVersion) {
250259
return nil, fmt.Errorf("the go minimum version %q must be a valid semantic version in the form of <major>.<minor>", externalGoRegistryConfig.MinVersion)
251260
}
252-
var dependencies []*GoRegistryDependencyConfig
261+
var runtimeDependencies []*GoRegistryDependencyConfig
253262
for _, dep := range externalGoRegistryConfig.Deps {
254263
if dep.Module == "" {
255264
return nil, errors.New("go runtime dependency requires a non-empty module name")
@@ -260,17 +269,37 @@ func newGoRegistryConfig(externalGoRegistryConfig *ExternalGoRegistryConfig) (*G
260269
if !semver.IsValid(dep.Version) {
261270
return nil, fmt.Errorf("go runtime dependency %s:%s does not have a valid semantic version", dep.Module, dep.Version)
262271
}
263-
dependencies = append(
264-
dependencies,
272+
runtimeDependencies = append(
273+
runtimeDependencies,
265274
&GoRegistryDependencyConfig{
266275
Module: dep.Module,
267276
Version: dep.Version,
268277
},
269278
)
270279
}
280+
var basePlugin bufremotepluginref.PluginIdentity
281+
if externalGoRegistryConfig.BasePlugin != "" {
282+
var err error
283+
basePlugin, err = pluginIdentityForStringWithOverrideRemote(externalGoRegistryConfig.BasePlugin, overrideRemote)
284+
if err != nil {
285+
return nil, fmt.Errorf("failed to parse base plugin: %w", err)
286+
}
287+
// Validate the base plugin is included as one of the plugin dependencies when both are
288+
// specified. This ensures there's exactly one base type and it has a known dependency to
289+
// generate imports correctly and build a correct Go mod file.
290+
if len(pluginDependencies) > 0 {
291+
ok := slices.ContainsFunc(pluginDependencies, func(ref bufremotepluginref.PluginReference) bool {
292+
return ref.IdentityString() == basePlugin.IdentityString()
293+
})
294+
if !ok {
295+
return nil, fmt.Errorf("base plugin %q not found in plugin dependencies", externalGoRegistryConfig.BasePlugin)
296+
}
297+
}
298+
}
271299
return &GoRegistryConfig{
272300
MinVersion: externalGoRegistryConfig.MinVersion,
273-
Deps: dependencies,
301+
Deps: runtimeDependencies,
302+
BasePlugin: basePlugin,
274303
}, nil
275304
}
276305

private/bufpkg/bufremoteplugin/bufremotepluginconfig/testdata/success/go/buf.plugin.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ deps:
99
output_languages: [go]
1010
registry:
1111
go:
12+
base_plugin: buf.build/library/go
1213
min_version: 1.18
1314
deps:
1415
- module: google.golang.org/grpc

0 commit comments

Comments
 (0)