Skip to content

Commit d56ef4e

Browse files
committed
Add policy configuration
1 parent 38e0790 commit d56ef4e

File tree

12 files changed

+606
-5
lines changed

12 files changed

+606
-5
lines changed

private/buf/bufmigrate/migrator.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ func (m *migrator) buildBufYAMLAndBufLockFiles(
382382
bufYAML, err := bufconfig.NewBufYAMLFile(
383383
bufconfig.FileVersionV2,
384384
migrateBuilder.moduleConfigs,
385-
// TODO: If we ever need to migrate from a v2 to v3, we will need to handle PluginConfigs
385+
// TODO: If we ever need to migrate from a v2 to v3, we will need to handle PluginConfigs and PolicyConfigs
386+
nil,
386387
nil,
387388
resolvedDeclaredRefs,
388389
)
@@ -431,7 +432,8 @@ func (m *migrator) buildBufYAMLAndBufLockFiles(
431432
bufYAML, err := bufconfig.NewBufYAMLFile(
432433
bufconfig.FileVersionV2,
433434
migrateBuilder.moduleConfigs,
434-
// TODO: If we ever need to migrate from a v2 to v3, we will need to handle PluginConfigs
435+
// TODO: If we ever need to migrate from a v2 to v3, we will need to handle PluginConfigs and PolicyConfigs
436+
nil,
435437
nil,
436438
resolvedDepModuleRefs,
437439
)

private/buf/cmd/buf/command/config/configinit/configinit.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ func run(
175175
},
176176
nil,
177177
nil,
178+
nil,
178179
bufconfig.BufYAMLFileWithIncludeDocsLink(),
179180
)
180181
if err != nil {

private/buf/cmd/buf/command/config/configlsmodules/configlsmodules.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ func getExternalModules(
143143
},
144144
nil,
145145
nil,
146+
nil,
146147
)
147148
if err != nil {
148149
return nil, err

private/buf/cmd/buf/command/config/internal/internal.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ func lsRun(
178178
},
179179
nil,
180180
nil,
181+
nil,
181182
)
182183
if err != nil {
183184
return err

private/buf/cmd/buf/command/mod/internal/internal.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ func lsRun(
164164
},
165165
nil,
166166
nil,
167+
nil,
167168
)
168169
if err != nil {
169170
return err
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
// Copyright 2020-2025 Buf Technologies, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package bufconfig
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"io"
21+
"slices"
22+
23+
"github.com/bufbuild/buf/private/pkg/encoding"
24+
"github.com/bufbuild/buf/private/pkg/storage"
25+
"github.com/bufbuild/buf/private/pkg/syserror"
26+
)
27+
28+
const (
29+
defaultBufPolicyYAMLFileName = "buf.policy.yaml"
30+
defaultBufPolicyYAMLFileVersion = FileVersionV2
31+
)
32+
33+
var (
34+
bufPolicyYAMLFileNames = []string{defaultBufPolicyYAMLFileName}
35+
bufPolicyYAMLFileNameToSupportedFileVersions = map[string]map[FileVersion]struct{}{
36+
defaultBufPolicyYAMLFileName: {
37+
FileVersionV2: struct{}{},
38+
},
39+
}
40+
)
41+
42+
// BufPolicyYAMLFile represents a buf.policy.yaml file.
43+
type BufPolicyYAMLFile interface {
44+
File
45+
46+
// Name returns the name for the File.
47+
Name() string
48+
// LintConfig returns the LintConfig for the File.
49+
LintConfig() LintConfig
50+
// BreakingConfig returns the BreakingConfig for the File.
51+
BreakingConfig() BreakingConfig
52+
// PluginConfigs returns the PluginConfigs for the File.
53+
PluginConfigs() []PluginConfig
54+
55+
isBufPolicyYAMLFile()
56+
}
57+
58+
// NewBufPolicyYAMLFile returns a new validated BufPolicyYAMLFile.
59+
func NewBufPolicyYAMLFile(
60+
fileVersion FileVersion,
61+
name string,
62+
lintConfig LintConfig,
63+
breakingConfig BreakingConfig,
64+
pluginConfigs []PluginConfig,
65+
) (BufPolicyYAMLFile, error) {
66+
return newBufPolicyYAMLFile(
67+
fileVersion,
68+
nil,
69+
name,
70+
lintConfig,
71+
breakingConfig,
72+
pluginConfigs,
73+
)
74+
}
75+
76+
// GetBufPolicyYAMLFileForPrefix gets the buf.gen.yaml file at the given bucket prefix.
77+
//
78+
// The buf.gen.yaml file will be attempted to be read at prefix/buf.gen.yaml.
79+
func GetBufPolicyYAMLFileForPrefix(
80+
ctx context.Context,
81+
bucket storage.ReadBucket,
82+
prefix string,
83+
) (BufPolicyYAMLFile, error) {
84+
return getFileForPrefix(ctx, bucket, prefix, bufPolicyYAMLFileNames, bufPolicyYAMLFileNameToSupportedFileVersions, readBufPolicyYAMLFile)
85+
}
86+
87+
// GetBufPolicyYAMLFileVersionForPrefix gets the buf.gen.yaml file version at the given bucket prefix.
88+
//
89+
// The buf.gen.yaml file will be attempted to be read at prefix/buf.gen.yaml.
90+
func GetBufPolicyYAMLFileVersionForPrefix(
91+
ctx context.Context,
92+
bucket storage.ReadBucket,
93+
prefix string,
94+
) (FileVersion, error) {
95+
return getFileVersionForPrefix(ctx, bucket, prefix, bufPolicyYAMLFileNames, bufPolicyYAMLFileNameToSupportedFileVersions, true, FileVersionV2, defaultBufPolicyYAMLFileVersion)
96+
}
97+
98+
// PutBufPolicyYAMLFileForPrefix puts the buf.gen.yaml file at the given bucket prefix.
99+
//
100+
// The buf.gen.yaml file will be attempted to be written to prefix/buf.gen.yaml.
101+
// The buf.gen.yaml file will be written atomically.
102+
func PutBufPolicyYAMLFileForPrefix(
103+
ctx context.Context,
104+
bucket storage.WriteBucket,
105+
prefix string,
106+
bufYAMLFile BufPolicyYAMLFile,
107+
) error {
108+
return putFileForPrefix(ctx, bucket, prefix, bufYAMLFile, defaultBufPolicyYAMLFileName, bufPolicyYAMLFileNameToSupportedFileVersions, writeBufPolicyYAMLFile)
109+
}
110+
111+
// ReadBufPolicyYAMLFile reads the BufPolicyYAMLFile from the io.Reader.
112+
func ReadBufPolicyYAMLFile(reader io.Reader, fileName string) (BufPolicyYAMLFile, error) {
113+
return readFile(reader, fileName, readBufPolicyYAMLFile)
114+
}
115+
116+
// WriteBufPolicyYAMLFile writes the BufPolicyYAMLFile to the io.Writer.
117+
func WriteBufPolicyYAMLFile(writer io.Writer, bufPolicyYAMLFile BufPolicyYAMLFile) error {
118+
return writeFile(writer, bufPolicyYAMLFile, writeBufPolicyYAMLFile)
119+
}
120+
121+
// *** PRIVATE ***
122+
123+
type bufPolicyYAMLFile struct {
124+
fileVersion FileVersion
125+
objectData ObjectData
126+
name string
127+
lintConfig LintConfig
128+
breakingConfig BreakingConfig
129+
pluginConfigs []PluginConfig
130+
}
131+
132+
func newBufPolicyYAMLFile(
133+
fileVersion FileVersion,
134+
objectData ObjectData,
135+
name string,
136+
lintConfig LintConfig,
137+
breakingConfig BreakingConfig,
138+
pluginConfigs []PluginConfig,
139+
) (*bufPolicyYAMLFile, error) {
140+
return &bufPolicyYAMLFile{
141+
fileVersion: fileVersion,
142+
objectData: objectData,
143+
name: name,
144+
lintConfig: lintConfig,
145+
breakingConfig: breakingConfig,
146+
pluginConfigs: pluginConfigs,
147+
}, nil
148+
}
149+
150+
func (p *bufPolicyYAMLFile) FileVersion() FileVersion {
151+
return p.fileVersion
152+
}
153+
154+
func (*bufPolicyYAMLFile) FileType() FileType {
155+
return FileTypeBufYAML
156+
}
157+
158+
func (p *bufPolicyYAMLFile) ObjectData() ObjectData {
159+
return p.objectData
160+
}
161+
162+
func (p *bufPolicyYAMLFile) Name() string {
163+
return p.name
164+
}
165+
166+
func (p *bufPolicyYAMLFile) LintConfig() LintConfig {
167+
return p.lintConfig
168+
}
169+
170+
func (p *bufPolicyYAMLFile) BreakingConfig() BreakingConfig {
171+
return p.breakingConfig
172+
}
173+
174+
func (p *bufPolicyYAMLFile) PluginConfigs() []PluginConfig {
175+
return slices.Clone(p.pluginConfigs)
176+
}
177+
func (*bufPolicyYAMLFile) isBufPolicyYAMLFile() {}
178+
func (*bufPolicyYAMLFile) isFile() {}
179+
func (*bufPolicyYAMLFile) isFileInfo() {}
180+
181+
// externalBufPolicyYAMLFileV2 represents the v2 buf.policy.yaml file.
182+
type externalBufPolicyYAMLFileV2 struct {
183+
Version string `json:"version,omitempty" yaml:"version,omitempty"`
184+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
185+
Lint externalBufYAMLFileLintV2 `json:"lint,omitempty" yaml:"lint,omitempty"`
186+
Breaking externalBufYAMLFileBreakingV1Beta1V1V2 `json:"breaking,omitempty" yaml:"breaking,omitempty"`
187+
Plugins []externalBufYAMLFilePluginV2 `json:"plugins,omitempty" yaml:"plugins,omitempty"`
188+
}
189+
190+
func readBufPolicyYAMLFile(
191+
data []byte,
192+
objectData ObjectData,
193+
allowJSON bool,
194+
) (BufPolicyYAMLFile, error) {
195+
fileVersion, err := getFileVersionForData(data, allowJSON, true, bufPolicyYAMLFileNameToSupportedFileVersions, FileVersionV2, defaultBufPolicyYAMLFileVersion)
196+
if err != nil {
197+
return nil, err
198+
}
199+
if fileVersion != FileVersionV2 {
200+
fmt.Println("objectData", objectData)
201+
return nil, newUnsupportedFileVersionError(objectData.Name(), fileVersion)
202+
}
203+
var externalBufPolicyYAMLFile externalBufPolicyYAMLFileV2
204+
if err := getUnmarshalStrict(allowJSON)(data, &externalBufPolicyYAMLFile); err != nil {
205+
return nil, fmt.Errorf("invalid as version %v: %w", fileVersion, err)
206+
}
207+
208+
var lintConfig LintConfig
209+
if !externalBufPolicyYAMLFile.Lint.isEmpty() {
210+
lintConfig, err = getLintConfigForExternalLintV2(
211+
fileVersion,
212+
externalBufPolicyYAMLFile.Lint,
213+
".", // Top-level directory always has the root ".".
214+
false, // Not module-specific configuration.
215+
)
216+
if err != nil {
217+
return nil, err
218+
}
219+
}
220+
var breakingConfig BreakingConfig
221+
if !externalBufPolicyYAMLFile.Breaking.isEmpty() {
222+
breakingConfig, err = getBreakingConfigForExternalBreaking(
223+
fileVersion,
224+
externalBufPolicyYAMLFile.Breaking,
225+
".", // Top-level directory always has the root ".".
226+
false, // Not module-specific configuration.
227+
)
228+
if err != nil {
229+
return nil, err
230+
}
231+
}
232+
var pluginConfigs []PluginConfig
233+
for _, externalPluginConfig := range externalBufPolicyYAMLFile.Plugins {
234+
pluginConfig, err := newPluginConfigForExternalV2(externalPluginConfig)
235+
if err != nil {
236+
return nil, err
237+
}
238+
pluginConfigs = append(pluginConfigs, pluginConfig)
239+
}
240+
return newBufPolicyYAMLFile(
241+
fileVersion,
242+
objectData,
243+
externalBufPolicyYAMLFile.Name,
244+
lintConfig,
245+
breakingConfig,
246+
pluginConfigs,
247+
)
248+
}
249+
250+
func writeBufPolicyYAMLFile(writer io.Writer, bufPolicyYAMLFile BufPolicyYAMLFile) error {
251+
fileVersion := bufPolicyYAMLFile.FileVersion()
252+
if fileVersion != FileVersionV2 {
253+
// This is effectively a system error.
254+
return syserror.Wrap(newUnsupportedFileVersionError("", fileVersion))
255+
}
256+
var externalLint externalBufYAMLFileLintV2
257+
if lintConfig := bufPolicyYAMLFile.LintConfig(); lintConfig != nil {
258+
externalLint = getExternalLintV2ForLintConfig(lintConfig, ".")
259+
}
260+
var externalBreaking externalBufYAMLFileBreakingV1Beta1V1V2
261+
if breakingConfig := bufPolicyYAMLFile.BreakingConfig(); breakingConfig != nil {
262+
externalBreaking = getExternalBreakingForBreakingConfig(breakingConfig, ".")
263+
}
264+
var externalPlugins []externalBufYAMLFilePluginV2
265+
for _, pluginConfig := range bufPolicyYAMLFile.PluginConfigs() {
266+
externalPlugin, err := newExternalV2ForPluginConfig(pluginConfig)
267+
if err != nil {
268+
return syserror.Wrap(err)
269+
}
270+
externalPlugins = append(externalPlugins, externalPlugin)
271+
}
272+
externalBufPolicyYAMLFile := externalBufPolicyYAMLFileV2{
273+
Version: fileVersion.String(),
274+
Name: bufPolicyYAMLFile.Name(),
275+
Lint: externalLint,
276+
Breaking: externalBreaking,
277+
Plugins: externalPlugins,
278+
}
279+
data, err := encoding.MarshalYAML(&externalBufPolicyYAMLFile)
280+
if err != nil {
281+
return err
282+
}
283+
_, err = writer.Write(data)
284+
return err
285+
}

0 commit comments

Comments
 (0)