Skip to content

Commit 20e3005

Browse files
authored
Resolve local policies remote plugin refs (#3981)
1 parent 0d7772e commit 20e3005

File tree

2 files changed

+125
-7
lines changed

2 files changed

+125
-7
lines changed

private/buf/bufworkspace/workspace_dep_manager.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/bufbuild/buf/private/bufpkg/bufparse"
2727
"github.com/bufbuild/buf/private/bufpkg/bufplugin"
2828
"github.com/bufbuild/buf/private/bufpkg/bufpolicy"
29+
"github.com/bufbuild/buf/private/bufpkg/bufpolicy/bufpolicyconfig"
2930
"github.com/bufbuild/buf/private/pkg/storage"
3031
"github.com/bufbuild/buf/private/pkg/syserror"
3132
)
@@ -92,6 +93,16 @@ type WorkspaceDepManager interface {
9293
//
9394
// Sorted.
9495
ConfiguredRemotePolicyRefs(ctx context.Context) ([]bufparse.Ref, error)
96+
// ConfiguredLocalPolicyNameToRemotePluginRefs returns the configured remote plugins for each local policy of the Workspace.
97+
//
98+
// These come from buf.yaml files and the local buf.policy.yaml files.
99+
//
100+
// The PluginRefs for each Policy will be unique by FullName. If there are two PluginRefs
101+
// in the buf.yaml for a given Policy with the same FullName but different Refs, an error will be given
102+
// at workspace constructions.
103+
//
104+
// PluginRefs are sorted for each Policy.
105+
ConfiguredLocalPolicyNameToRemotePluginRefs(ctx context.Context) (map[string][]bufparse.Ref, error)
95106

96107
isWorkspaceDepManager()
97108
}
@@ -242,6 +253,62 @@ func (w *workspaceDepManager) ConfiguredRemotePolicyRefs(ctx context.Context) ([
242253
return policyRefs, nil
243254
}
244255

256+
func (w *workspaceDepManager) ConfiguredLocalPolicyNameToRemotePluginRefs(ctx context.Context) (map[string][]bufparse.Ref, error) {
257+
bufYAMLFile, err := bufconfig.GetBufYAMLFileForPrefix(ctx, w.bucket, w.targetSubDirPath)
258+
if err != nil {
259+
if !errors.Is(err, fs.ErrNotExist) {
260+
return nil, err
261+
}
262+
}
263+
if bufYAMLFile == nil {
264+
return nil, nil
265+
}
266+
switch fileVersion := bufYAMLFile.FileVersion(); fileVersion {
267+
case bufconfig.FileVersionV1Beta1, bufconfig.FileVersionV1:
268+
if w.isV2 {
269+
return nil, syserror.Newf("buf.yaml at %q did had version %v but expected v1beta1, v1", w.targetSubDirPath, fileVersion)
270+
}
271+
// Policys are not supported in versions less than v2.
272+
return nil, nil
273+
case bufconfig.FileVersionV2:
274+
if !w.isV2 {
275+
return nil, syserror.Newf("buf.yaml at %q did had version %v but expected v2", w.targetSubDirPath, fileVersion)
276+
}
277+
default:
278+
return nil, syserror.Newf("unknown FileVersion: %v", fileVersion)
279+
}
280+
localPolicyNameToRemotePluginRefs := make(map[string][]bufparse.Ref)
281+
for _, policyConfig := range bufYAMLFile.PolicyConfigs() {
282+
if policyConfig.Ref() != nil {
283+
continue // Only local policies refs are considered here.
284+
}
285+
localPolicyName := policyConfig.Name()
286+
bufPolicyFile, err := bufpolicyconfig.GetBufPolicyYAMLFile(ctx, w.bucket, localPolicyName)
287+
if err != nil {
288+
return nil, err
289+
}
290+
pluginRefs := xslices.Filter(
291+
xslices.Map(
292+
bufPolicyFile.PluginConfigs(),
293+
func(value bufpolicy.PluginConfig) bufparse.Ref {
294+
return value.Ref()
295+
},
296+
),
297+
func(value bufparse.Ref) bool {
298+
return value != nil
299+
},
300+
)
301+
sort.Slice(
302+
pluginRefs,
303+
func(i int, j int) bool {
304+
return pluginRefs[i].FullName().String() < pluginRefs[j].FullName().String()
305+
},
306+
)
307+
localPolicyNameToRemotePluginRefs[localPolicyName] = pluginRefs
308+
}
309+
return localPolicyNameToRemotePluginRefs, nil
310+
}
311+
245312
func (w *workspaceDepManager) BufLockFileDigestType() bufmodule.DigestType {
246313
if w.isV2 {
247314
return bufmodule.DigestTypeB5

private/buf/cmd/buf/command/policy/policyupdate/policyupdate.go

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"errors"
2020
"fmt"
21+
"maps"
2122

2223
"buf.build/go/app/appcmd"
2324
"buf.build/go/app/appext"
@@ -103,6 +104,10 @@ func run(
103104
if err != nil {
104105
return err
105106
}
107+
configuredLocalPolicyNameToRemotePluginRefs, err := workspaceDepManager.ConfiguredLocalPolicyNameToRemotePluginRefs(ctx)
108+
if err != nil {
109+
return err
110+
}
106111
policyKeyProvider, err := bufcli.NewPolicyKeyProvider(container)
107112
if err != nil {
108113
return err
@@ -115,21 +120,40 @@ func run(
115120
if err != nil {
116121
return err
117122
}
118-
configuredPolicyNameToRemotePluginKeys, err := getPolicyKeyPluginKeysForPolicyKeys(
123+
configuredRemotePolicyNameToRemotePluginKeys, err := getPolicyKeyPluginKeysForPolicyKeys(
119124
ctx,
120125
container,
121126
configuredRemotePolicyKeys,
122127
)
123128
if err != nil {
124129
return err
125130
}
131+
configuredLocalPolicyNameToRemotePluginKeys, err := getPolicyPluginKeysForPolicyNames(
132+
ctx,
133+
container,
134+
configuredLocalPolicyNameToRemotePluginRefs,
135+
)
136+
if err != nil {
137+
return err
138+
}
139+
var configuredPolicyNameToRemotePluginKeys map[string][]bufplugin.PluginKey
140+
if policyCount := len(configuredRemotePolicyNameToRemotePluginKeys) + len(configuredLocalPolicyNameToRemotePluginKeys); policyCount > 0 {
141+
configuredPolicyNameToRemotePluginKeys = make(map[string][]bufplugin.PluginKey, policyCount)
142+
maps.Copy(configuredPolicyNameToRemotePluginKeys, configuredRemotePolicyNameToRemotePluginKeys)
143+
maps.Copy(configuredPolicyNameToRemotePluginKeys, configuredLocalPolicyNameToRemotePluginKeys)
144+
}
126145

127146
// Store the existing buf.lock data.
128147
existingRemotePolicyKeys, err := workspaceDepManager.ExistingBufLockFileRemotePolicyKeys(ctx)
129148
if err != nil {
130149
return err
131150
}
132-
if configuredRemotePolicyKeys == nil && existingRemotePolicyKeys == nil {
151+
existingPolicyNameToRemotePluginKeys, err := workspaceDepManager.ExistingBufLockFilePolicyNameToRemotePluginKeys(ctx)
152+
if err != nil {
153+
return err
154+
}
155+
if len(configuredRemotePolicyKeys) == 0 && len(configuredPolicyNameToRemotePluginKeys) == 0 &&
156+
len(existingRemotePolicyKeys) == 0 && len(existingPolicyNameToRemotePluginKeys) == 0 {
133157
// No new configured remote plugins were found, and no existing buf.lock deps were found, so there
134158
// is nothing to update, we can return here.
135159
// This ensures we do not create an empty buf.lock when one did not exist in the first
@@ -146,11 +170,6 @@ func run(
146170
if err != nil {
147171
return err
148172
}
149-
existingPolicyNameToRemotePluginKeys, err := workspaceDepManager.ExistingBufLockFilePolicyNameToRemotePluginKeys(ctx)
150-
if err != nil {
151-
return err
152-
}
153-
154173
// We're about to edit the buf.lock file on disk. If we have a subsequent error,
155174
// attempt to revert the buf.lock file.
156175
//
@@ -176,6 +195,9 @@ func getPolicyKeyPluginKeysForPolicyKeys(
176195
container appext.Container,
177196
policyKeys []bufpolicy.PolicyKey,
178197
) (map[string][]bufplugin.PluginKey, error) {
198+
if len(policyKeys) == 0 {
199+
return nil, nil
200+
}
179201
policyDataProvider, err := bufcli.NewPolicyDataProvider(container)
180202
if err != nil {
181203
return nil, err
@@ -220,3 +242,32 @@ func getPolicyKeyPluginKeysForPolicyKeys(
220242
}
221243
return policyNameToRemotePluginKeys, nil
222244
}
245+
246+
func getPolicyPluginKeysForPolicyNames(
247+
ctx context.Context,
248+
container appext.Container,
249+
localPolicyNameToRemotePluginRefs map[string][]bufparse.Ref,
250+
) (map[string][]bufplugin.PluginKey, error) {
251+
if len(localPolicyNameToRemotePluginRefs) == 0 {
252+
return nil, nil
253+
}
254+
pluginKeyProvider, err := bufcli.NewPluginKeyProvider(container)
255+
if err != nil {
256+
return nil, err
257+
}
258+
policyNameToRemotePluginKeys := make(map[string][]bufplugin.PluginKey)
259+
for policyName, pluginRefs := range localPolicyNameToRemotePluginRefs {
260+
remotePluginKeys, err := pluginKeyProvider.GetPluginKeysForPluginRefs(
261+
ctx,
262+
pluginRefs,
263+
bufplugin.DigestTypeP1,
264+
)
265+
if err != nil {
266+
return nil, err
267+
}
268+
if len(remotePluginKeys) > 0 {
269+
policyNameToRemotePluginKeys[policyName] = remotePluginKeys
270+
}
271+
}
272+
return policyNameToRemotePluginKeys, nil
273+
}

0 commit comments

Comments
 (0)