From 639ab433dd28df3bc6199856ef03fdf7939c74fe Mon Sep 17 00:00:00 2001 From: barry Date: Tue, 24 Jun 2025 22:58:25 +0800 Subject: [PATCH 1/8] fix: barry quick fix, 2025-06-24 22:58:25 --- cmd/linter/cli.go | 295 +++++++++++++++++++++++++++++++++++ cmd/linter/github_actions.go | 69 ++++++++ cmd/linter/main.go | 55 +++++++ cmd/linter/rules.go | 47 ++++++ go.mod | 24 ++- go.sum | 81 +++++++--- 6 files changed, 546 insertions(+), 25 deletions(-) create mode 100644 cmd/linter/cli.go create mode 100644 cmd/linter/github_actions.go create mode 100644 cmd/linter/main.go create mode 100644 cmd/linter/rules.go diff --git a/cmd/linter/cli.go b/cmd/linter/cli.go new file mode 100644 index 0000000..768a4ef --- /dev/null +++ b/cmd/linter/cli.go @@ -0,0 +1,295 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "strings" + "sync" + + "github.com/googleapis/api-linter/lint" + "github.com/jhump/protoreflect/desc" + "github.com/jhump/protoreflect/desc/protoparse" + "github.com/spf13/pflag" + "google.golang.org/protobuf/proto" + dpb "google.golang.org/protobuf/types/descriptorpb" + "gopkg.in/yaml.v3" +) + +type cli struct { + ConfigPath string + FormatType string + OutputPath string + ExitStatusOnLintFailure bool + VersionFlag bool + ProtoImportPaths []string + ProtoFiles []string + ProtoDescPath []string + EnabledRules []string + DisabledRules []string + ListRulesFlag bool + DebugFlag bool + IgnoreCommentDisablesFlag bool +} + +// ExitForLintFailure indicates that a problem was found during linting. +// +//lint:ignore ST1012 modifying this variable name is a breaking change. +var ExitForLintFailure = errors.New("found problems during linting") + +func newCli(args []string) *cli { + // Define flag variables. + var cfgFlag string + var fmtFlag string + var outFlag string + var setExitStatusOnLintFailure bool + var versionFlag bool + var protoImportFlag []string + var protoDescFlag []string + var ruleEnableFlag []string + var ruleDisableFlag []string + var listRulesFlag bool + var debugFlag bool + var ignoreCommentDisablesFlag bool + + // Register flag variables. + fs := pflag.NewFlagSet("api-linter", pflag.ExitOnError) + fs.StringVar(&cfgFlag, "config", "", "The linter config file.") + fs.StringVar(&fmtFlag, "output-format", "", "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.") + fs.StringVarP(&outFlag, "output-path", "o", "", "The output file path.\nIf not given, the linting results will be printed out to STDOUT.") + fs.BoolVar(&setExitStatusOnLintFailure, "set-exit-status", false, "Return exit status 1 when lint errors are found.") + fs.BoolVar(&versionFlag, "version", false, "Print version and exit.") + fs.StringArrayVarP(&protoImportFlag, "proto-path", "I", nil, "The folder for searching proto imports.\nMay be specified multiple times; directories will be searched in order.\nThe current working directory is always used.") + fs.StringArrayVar(&protoDescFlag, "descriptor-set-in", nil, "The file containing a FileDescriptorSet for searching proto imports.\nMay be specified multiple times.") + fs.StringArrayVar(&ruleEnableFlag, "enable-rule", nil, "Enable a rule with the given name.\nMay be specified multiple times.") + fs.StringArrayVar(&ruleDisableFlag, "disable-rule", nil, "Disable a rule with the given name.\nMay be specified multiple times.") + fs.BoolVar(&listRulesFlag, "list-rules", false, "Print the rules and exit. Honors the output-format flag.") + fs.BoolVar(&debugFlag, "debug", false, "Run in debug mode. Panics will print stack.") + fs.BoolVar(&ignoreCommentDisablesFlag, "ignore-comment-disables", false, "If set to true, disable comments will be ignored.\nThis is helpful when strict enforcement of AIPs are necessary and\nproto definitions should not be able to disable checks.") + + // Parse flags. + err := fs.Parse(args) + if err != nil { + panic(err) + } + + return &cli{ + ConfigPath: cfgFlag, + FormatType: fmtFlag, + OutputPath: outFlag, + ExitStatusOnLintFailure: setExitStatusOnLintFailure, + ProtoImportPaths: protoImportFlag, + ProtoDescPath: protoDescFlag, + EnabledRules: ruleEnableFlag, + DisabledRules: ruleDisableFlag, + ProtoFiles: fs.Args(), + VersionFlag: versionFlag, + ListRulesFlag: listRulesFlag, + DebugFlag: debugFlag, + IgnoreCommentDisablesFlag: ignoreCommentDisablesFlag, + } +} + +func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { + // Print version and exit if asked. + if c.VersionFlag { + return nil + } + + if c.ListRulesFlag { + return outputRules(c.FormatType) + } + + // Pre-check if there are files to lint. + if len(c.ProtoFiles) == 0 { + return fmt.Errorf("no file to lint") + } + // Read linter config and append it to the default. + if c.ConfigPath != "" { + config, err := lint.ReadConfigsFromFile(c.ConfigPath) + if err != nil { + return err + } + configs = append(configs, config...) + } + // Add configs for the enabled rules. + configs = append(configs, lint.Config{ + EnabledRules: c.EnabledRules, + }) + // Add configs for the disabled rules. + configs = append(configs, lint.Config{ + DisabledRules: c.DisabledRules, + }) + // Prepare proto import lookup. + fs, err := loadFileDescriptors(c.ProtoDescPath...) + if err != nil { + return err + } + lookupImport := func(name string) (*desc.FileDescriptor, error) { + if f, found := fs[name]; found { + return f, nil + } + return nil, fmt.Errorf("%q is not found", name) + } + var errorsWithPos []protoparse.ErrorWithPos + var lock sync.Mutex + // Parse proto files into `protoreflect` file descriptors. + p := protoparse.Parser{ + ImportPaths: append(c.ProtoImportPaths, "."), + IncludeSourceCodeInfo: true, + LookupImport: lookupImport, + ErrorReporter: func(errorWithPos protoparse.ErrorWithPos) error { + // Protoparse isn't concurrent right now but just to be safe for the future. + lock.Lock() + errorsWithPos = append(errorsWithPos, errorWithPos) + lock.Unlock() + // Continue parsing. The error returned will be protoparse.ErrInvalidSource. + return nil + }, + } + // Resolve file absolute paths to relative ones. + // Using supplied import paths first. + protoFiles := c.ProtoFiles + if len(c.ProtoImportPaths) > 0 { + protoFiles, err = protoparse.ResolveFilenames(c.ProtoImportPaths, c.ProtoFiles...) + if err != nil { + return err + } + } + // Then resolve again against ".", the local directory. + // This is necessary because ResolveFilenames won't resolve a path if it + // relative to *at least one* of the given import paths, which can result + // in duplicate file parsing and compilation errors, as seen in #1465 and + // #1471. So we resolve against local (default) and flag specified import + // paths separately. + protoFiles, err = protoparse.ResolveFilenames([]string{"."}, protoFiles...) + if err != nil { + return err + } + fd, err := p.ParseFiles(protoFiles...) + if err != nil { + if err == protoparse.ErrInvalidSource { + if len(errorsWithPos) == 0 { + return errors.New("got protoparse.ErrInvalidSource but no ErrorWithPos errors") + } + // TODO: There's multiple ways to deal with this but this prints all the errors at least + errStrings := make([]string, len(errorsWithPos)) + for i, errorWithPos := range errorsWithPos { + errStrings[i] = errorWithPos.Error() + } + return errors.New(strings.Join(errStrings, "\n")) + } + return err + } + + // Create a linter to lint the file descriptors. + l := lint.New(rules, configs, lint.Debug(c.DebugFlag), lint.IgnoreCommentDisables(c.IgnoreCommentDisablesFlag)) + results, err := l.LintProtos(fd...) + if err != nil { + return err + } + + // Determine the output for writing the results. + // Stdout is the default output. + w := os.Stdout + if c.OutputPath != "" { + var err error + w, err = os.Create(c.OutputPath) + if err != nil { + return err + } + defer w.Close() + } + + // Determine the format for printing the results. + // YAML format is the default. + marshal := getOutputFormatFunc(c.FormatType) + + // Print the results. + b, err := marshal(results) + if err != nil { + return err + } + if _, err = w.Write(b); err != nil { + return err + } + + // Return error on lint failure which subsequently + // exits with a non-zero status code + if c.ExitStatusOnLintFailure && anyProblems(results) { + return ExitForLintFailure + } + + return nil +} + +func anyProblems(results []lint.Response) bool { + for i := range results { + if len(results[i].Problems) > 0 { + return true + } + } + return false +} + +func loadFileDescriptors(filePaths ...string) (map[string]*desc.FileDescriptor, error) { + fds := []*dpb.FileDescriptorProto{} + for _, filePath := range filePaths { + fs, err := readFileDescriptorSet(filePath) + if err != nil { + return nil, err + } + fds = append(fds, fs.GetFile()...) + } + return desc.CreateFileDescriptors(fds) +} + +func readFileDescriptorSet(filePath string) (*dpb.FileDescriptorSet, error) { + in, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + fs := &dpb.FileDescriptorSet{} + if err := proto.Unmarshal(in, fs); err != nil { + return nil, err + } + return fs, nil +} + +var outputFormatFuncs = map[string]formatFunc{ + "yaml": yaml.Marshal, + "yml": yaml.Marshal, + "json": json.Marshal, + "github": func(i interface{}) ([]byte, error) { + switch v := i.(type) { + case []lint.Response: + return formatGitHubActionOutput(v), nil + default: + return json.Marshal(v) + } + }, +} + +type formatFunc func(interface{}) ([]byte, error) + +func getOutputFormatFunc(formatType string) formatFunc { + if f, found := outputFormatFuncs[strings.ToLower(formatType)]; found { + return f + } + return yaml.Marshal +} diff --git a/cmd/linter/github_actions.go b/cmd/linter/github_actions.go new file mode 100644 index 0000000..e43ed93 --- /dev/null +++ b/cmd/linter/github_actions.go @@ -0,0 +1,69 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "fmt" + "strings" + + "github.com/googleapis/api-linter/lint" +) + +// formatGitHubActionOutput returns lint errors in GitHub actions format. +func formatGitHubActionOutput(responses []lint.Response) []byte { + var buf bytes.Buffer + for _, response := range responses { + for _, problem := range response.Problems { + // lint example: + // ::error file={name},line={line},endLine={endLine},title={title}::{message} + // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message + + fmt.Fprintf(&buf, "::error file=%s", response.FilePath) + if problem.Location != nil { + // Some findings are *line level* and only have start positions but no + // starting column. Construct a switch fallthrough to emit as many of + // the location indicators are included. + switch len(problem.Location.Span) { + case 4: + fmt.Fprintf(&buf, ",endColumn=%d", problem.Location.Span[3]) + fallthrough + case 3: + fmt.Fprintf(&buf, ",endLine=%d", problem.Location.Span[2]) + fallthrough + case 2: + fmt.Fprintf(&buf, ",col=%d", problem.Location.Span[1]) + fallthrough + case 1: + fmt.Fprintf(&buf, ",line=%d", problem.Location.Span[0]) + } + } + + // GitHub uses :: as control characters (which are also used to delimit + // linter rules. In order to prevent confusion, replace the double colon + // with two Armenian full stops which are indistinguishable to my eye. + runeThatLooksLikeTwoColonsButIsActuallyTwoArmenianFullStops := "։։" + title := strings.ReplaceAll(string(problem.RuleID), "::", runeThatLooksLikeTwoColonsButIsActuallyTwoArmenianFullStops) + message := strings.ReplaceAll(problem.Message, "\n", "\\n") + uri := problem.GetRuleURI() + if uri != "" { + message += "\\n\\n" + uri + } + fmt.Fprintf(&buf, ",title=%s::%s\n", title, message) + } + } + + return buf.Bytes() +} diff --git a/cmd/linter/main.go b/cmd/linter/main.go new file mode 100644 index 0000000..9e5fe26 --- /dev/null +++ b/cmd/linter/main.go @@ -0,0 +1,55 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The command line `api-linter` checks Google APIs defined in Protobuf files. +// It follows the API Improvement Proposals defined in https://aip.dev. +package main + +import ( + "log" + "os" + + "github.com/googleapis/api-linter/lint" + "github.com/googleapis/api-linter/rules" +) + +var ( + globalRules = lint.NewRuleRegistry() + globalConfigs = defaultConfigs() +) + +func init() { + if err := rules.Add(globalRules); err != nil { + log.Fatalf("error when registering rules: %v", err) + } +} + +func main() { + if err := runCLI(os.Args[1:]); err != nil { + log.Fatalln(err) + } +} + +func runCLI(args []string) error { + c := newCli(args) + return c.lint(globalRules, globalConfigs) +} + +// Enable all rules by default. +// Once we have rules other than core, +// we will determine if we want to +// change this policy. +func defaultConfigs() lint.Configs { + return lint.Configs{} +} diff --git a/cmd/linter/rules.go b/cmd/linter/rules.go new file mode 100644 index 0000000..f887035 --- /dev/null +++ b/cmd/linter/rules.go @@ -0,0 +1,47 @@ +package main + +import ( + "os" + "sort" + + "github.com/googleapis/api-linter/lint" +) + +type ( + listedRule struct { + Name lint.RuleName + } + listedRules []listedRule + listedRulesByName []listedRule +) + +func (a listedRulesByName) Len() int { return len(a) } +func (a listedRulesByName) Less(i, j int) bool { return a[i].Name < a[j].Name } +func (a listedRulesByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +func outputRules(formatType string) error { + rules := listedRules{} + for id := range globalRules { + rules = append(rules, listedRule{ + Name: id, + }) + } + + sort.Sort(listedRulesByName(rules)) + + // Determine the format for printing the results. + // YAML format is the default. + marshal := getOutputFormatFunc(formatType) + + // Print the results. + b, err := marshal(rules) + if err != nil { + return err + } + w := os.Stdout + if _, err = w.Write(b); err != nil { + return err + } + + return nil +} diff --git a/go.mod b/go.mod index 4c790a6..2b6649a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22.6 require ( github.com/a8m/envsubst v1.3.0 - github.com/bufbuild/protocompile v0.5.1 + github.com/bufbuild/protocompile v0.14.1 github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 github.com/dave/jennifer v1.6.0 github.com/deckarep/golang-set/v2 v2.6.0 @@ -13,27 +13,34 @@ require ( github.com/fatih/structtag v1.2.0 github.com/flosch/pongo2/v5 v5.0.0 github.com/golang/protobuf v1.5.4 + github.com/googleapis/api-linter v1.69.2 github.com/hashicorp/go-version v1.6.0 github.com/huandu/go-clone v1.5.1 + github.com/jhump/protoreflect v1.17.0 github.com/lyft/protoc-gen-star/v2 v2.0.2-alpha github.com/open2b/scriggo v0.56.1 github.com/pubgo/funk v0.5.49 github.com/samber/lo v1.47.0 github.com/searKing/golang/go v1.2.115 github.com/spf13/cast v1.5.0 + github.com/spf13/pflag v1.0.6 github.com/urfave/cli/v3 v3.0.0-alpha9.0.20240717192922-127cf54fac9f github.com/yuin/goldmark v1.4.12 go.uber.org/multierr v1.11.0 golang.org/x/mod v0.17.0 - google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c - google.golang.org/grpc v1.51.0 - google.golang.org/protobuf v1.35.2 + google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47 + google.golang.org/grpc v1.69.4 + google.golang.org/protobuf v1.36.4 gopkg.in/yaml.v3 v3.0.1 gorm.io/gorm v1.24.5 ) require ( + bitbucket.org/creachadair/stringset v0.0.12 // indirect + cloud.google.com/go/longrunning v0.6.4 // indirect github.com/alecthomas/repr v0.4.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect + github.com/gertd/go-pluralize v0.2.1 // indirect github.com/goccy/go-json v0.10.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -43,10 +50,13 @@ require ( github.com/phuslu/goid v1.0.0 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/spf13/afero v1.9.2 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect ) diff --git a/go.sum b/go.sum index d6a3d53..67150e9 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +bitbucket.org/creachadair/stringset v0.0.12 h1:APD8dIoAzGv70a6p1oasPDjPwkp+ajszdgKyWUcNqo0= +bitbucket.org/creachadair/stringset v0.0.12/go.mod h1:KtNk2s0hRO1T0r78lv9Zq/S/Lp0du2zI0Fj5j5Y4LDo= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -25,6 +27,8 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/longrunning v0.6.4 h1:3tyw9rO3E2XVXzSApn1gyEEnH2K9SynNQjMlBi3uHLg= +cloud.google.com/go/longrunning v0.6.4/go.mod h1:ttZpLCe6e7EXvn9OxpBRx7kZEB0efv8yBO6YnVMfhJs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -42,8 +46,10 @@ github.com/a8m/envsubst v1.3.0 h1:GmXKmVssap0YtlU3E230W98RWtWCyIZzjtf1apWWyAg= github.com/a8m/envsubst v1.3.0/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/bufbuild/protocompile v0.5.1 h1:mixz5lJX4Hiz4FpqFREJHIXLfaLBntfaJv1h+/jS+Qg= -github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= +github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= +github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= +github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -79,9 +85,15 @@ github.com/flosch/pongo2/v5 v5.0.0 h1:ZauMp+iPZzh2aI1QM2UwRb0lXD4BoFcvBuWqefkIuq github.com/flosch/pongo2/v5 v5.0.0/go.mod h1:6ysKu++8ANFXmc3x6uA6iVaS+PKUoDfdX3yPcv8TIzY= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA= +github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -123,8 +135,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -140,6 +152,10 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/api-linter v1.69.2 h1:OqAPZMw7MiBXbJ1v32MG/8NFrj5wlF1zHd5D7jNlIUY= +github.com/googleapis/api-linter v1.69.2/go.mod h1:p09limxuj2v3iGQLIsTA12qg5K5yjS8uQ1fglPnCYl8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -153,6 +169,8 @@ github.com/huandu/go-clone v1.5.1 h1:1wlwYRlHZo4HspdOM0YQ6O7Y7bjtxTrrt+4jnDeejVo github.com/huandu/go-clone v1.5.1/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -172,6 +190,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/lyft/protoc-gen-star/v2 v2.0.2-alpha h1:4ZnxxYqVDJgZUXBZMTqDw64NKk42NbLdf7MWtvaw1kU= github.com/lyft/protoc-gen-star/v2 v2.0.2-alpha/go.mod h1:RbbSxnunjxwTAoOxdNOMFJrq51wKMMNs18aAGFCZERs= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -205,12 +225,21 @@ github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -235,6 +264,16 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -312,8 +351,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -333,6 +372,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -370,8 +411,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -379,8 +420,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -497,8 +538,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20250124145028-65684f501c47 h1:SI8Hf7K4+uVYchXqZiMfP44PZ83xomMWovbcFfm0P8Q= +google.golang.org/genproto v0.0.0-20250124145028-65684f501c47/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE= +google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47 h1:5iw9XJTD4thFidQmFVvx0wi4g5yOHk76rNRUxz1ZG5g= +google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47/go.mod h1:AfA77qWLcidQWywD0YgqfpJzf50w2VjzBml3TybHeJU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -515,8 +560,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -527,8 +572,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From a57b6e58fa266d63bd793372c2f18418939c618a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 10:34:29 +0800 Subject: [PATCH 2/8] fix: barry quick fix, 2025-06-25 10:34:29 --- .github/workflows/lint.yml | 6 +++--- .github/workflows/release.yml | 8 ++++---- go.mod | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2c4ad57..258ac67 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,12 +7,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: 1.22 + go-version-file: 'go.mod' # - name: golangci-lint # uses: golangci/golangci-lint-action@v2 # with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ffc3282..3ebd241 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,15 +9,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: 1.22 + go-version-file: 'go.mod' - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2 + uses: goreleaser/goreleaser-action@v6 with: version: latest args: release --clean diff --git a/go.mod b/go.mod index 2b6649a..ce89499 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/pubgo/protobuild -go 1.22.6 +go 1.24 require ( github.com/a8m/envsubst v1.3.0 From 9d9eab652a30ea9739e0c73d8cb4bddd881d55c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 10:40:20 +0800 Subject: [PATCH 3/8] fix: barry quick fix, 2025-06-25 10:40:20 --- .goreleaser.yaml | 2 ++ cmd/protobuild/cmd.go | 18 ++++++++++-------- go.mod | 6 +++--- go.sum | 16 ++++++++-------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index ed2a48a..841a3fc 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -9,6 +9,7 @@ builds: - windows goarch: - amd64 + - arm64 ldflags: - -X 'github.com/pubgo/protobuild/version.Version={{ .Version }}' - main: ./cmd/protoc-gen-retag/main.go @@ -21,6 +22,7 @@ builds: - windows goarch: - amd64 + - arm64 archives: - name_template: "{{ .Binary }}-{{ .Tag }}-{{ .Os }}-{{ .Arch }}" format: binary diff --git a/cmd/protobuild/cmd.go b/cmd/protobuild/cmd.go index 623105a..7c68a41 100644 --- a/cmd/protobuild/cmd.go +++ b/cmd/protobuild/cmd.go @@ -65,7 +65,7 @@ func Main() *cli.Command { Usage: "protobuf config path", Value: protoCfg, Hidden: false, - Persistent: true, + Local: true, Destination: &protoCfg, }, }, @@ -135,9 +135,11 @@ func Main() *cli.Command { }, Commands: typex.Commands{ &cli.Command{ - Name: "gen", - Usage: "编译 protobuf 文件", - Before: func(ctx context.Context, c *cli.Command) error { return parseConfig() }, + Name: "gen", + Usage: "编译 protobuf 文件", + Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { + return ctx, parseConfig() + }, Action: func(ctx context.Context, c *cli.Command) error { defer recovery.Exit() @@ -313,8 +315,8 @@ func Main() *cli.Command { &cli.Command{ Name: "vendor", Usage: "同步项目 protobuf 依赖到 .proto 目录中", - Before: func(ctx context.Context, c *cli.Command) error { - return parseConfig() + Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { + return ctx, parseConfig() }, Flags: typex.Flags{ &cli.BoolFlag{ @@ -480,8 +482,8 @@ func Main() *cli.Command { &cli.Command{ Name: "install", Usage: "install protobuf plugin", - Before: func(ctx context.Context, c *cli.Command) error { - return parseConfig() + Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { + return ctx, parseConfig() }, Flags: typex.Flags{ &cli.BoolFlag{ diff --git a/go.mod b/go.mod index ce89499..e1f66ac 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/pubgo/protobuild go 1.24 require ( - github.com/a8m/envsubst v1.3.0 + github.com/a8m/envsubst v1.4.3 github.com/bufbuild/protocompile v0.14.1 - github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 + github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a github.com/dave/jennifer v1.6.0 github.com/deckarep/golang-set/v2 v2.6.0 github.com/emicklei/proto v1.11.0 @@ -24,7 +24,7 @@ require ( github.com/searKing/golang/go v1.2.115 github.com/spf13/cast v1.5.0 github.com/spf13/pflag v1.0.6 - github.com/urfave/cli/v3 v3.0.0-alpha9.0.20240717192922-127cf54fac9f + github.com/urfave/cli/v3 v3.3.8 github.com/yuin/goldmark v1.4.12 go.uber.org/multierr v1.11.0 golang.org/x/mod v0.17.0 diff --git a/go.sum b/go.sum index 67150e9..e72bef7 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/a8m/envsubst v1.3.0 h1:GmXKmVssap0YtlU3E230W98RWtWCyIZzjtf1apWWyAg= -github.com/a8m/envsubst v1.3.0/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= +github.com/a8m/envsubst v1.4.3 h1:kDF7paGK8QACWYaQo6KtyYBozY2jhQrTuNNuUxQkhJY= +github.com/a8m/envsubst v1.4.3/go.mod h1:4jjHWQlZoaXPoLQUb7H2qT4iLkZDdmEQiOUogdUmqVU= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= @@ -58,8 +58,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ= -github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= +github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a h1:Ohw57yVY2dBTt+gsC6aZdteyxwlxfbtgkFEMTEkwgSw= +github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/dave/jennifer v1.6.0 h1:MQ/6emI2xM7wt0tJzJzyUik2Q3Tcn2eE0vtYgh4GPVI= github.com/dave/jennifer v1.6.0/go.mod h1:AxTG893FiZKqxy3FP1kL80VMshSMuz2G+EgvszgGRnk= @@ -238,16 +238,16 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/urfave/cli/v3 v3.0.0-alpha9.0.20240717192922-127cf54fac9f h1:yCJ90PBe7+45EQSF3qJXyAGW5rkE65lE8huv5pM0HY8= -github.com/urfave/cli/v3 v3.0.0-alpha9.0.20240717192922-127cf54fac9f/go.mod h1:Z1ItyMma7t6I7zHG9OpbExhHQOSkFf/96n+mAZ9MtVI= +github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E= +github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= From 37c50580fb085a48c39b7b67dbb1e2829e064861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 11:12:13 +0800 Subject: [PATCH 4/8] fix: barry quick fix, 2025-06-25 11:12:13 --- cmd/linter/cli.go | 86 ++-------------------------------------- cmd/linter/main.go | 5 +-- cmd/protobuild/config.go | 12 +++++- cmd/protobuild/linter.go | 1 + 4 files changed, 17 insertions(+), 87 deletions(-) create mode 100644 cmd/protobuild/linter.go diff --git a/cmd/linter/cli.go b/cmd/linter/cli.go index 768a4ef..761b34a 100644 --- a/cmd/linter/cli.go +++ b/cmd/linter/cli.go @@ -23,23 +23,16 @@ import ( "sync" "github.com/googleapis/api-linter/lint" - "github.com/jhump/protoreflect/desc" "github.com/jhump/protoreflect/desc/protoparse" "github.com/spf13/pflag" - "google.golang.org/protobuf/proto" - dpb "google.golang.org/protobuf/types/descriptorpb" "gopkg.in/yaml.v3" ) type cli struct { ConfigPath string FormatType string - OutputPath string - ExitStatusOnLintFailure bool - VersionFlag bool ProtoImportPaths []string ProtoFiles []string - ProtoDescPath []string EnabledRules []string DisabledRules []string ListRulesFlag bool @@ -56,11 +49,7 @@ func newCli(args []string) *cli { // Define flag variables. var cfgFlag string var fmtFlag string - var outFlag string - var setExitStatusOnLintFailure bool - var versionFlag bool var protoImportFlag []string - var protoDescFlag []string var ruleEnableFlag []string var ruleDisableFlag []string var listRulesFlag bool @@ -71,11 +60,7 @@ func newCli(args []string) *cli { fs := pflag.NewFlagSet("api-linter", pflag.ExitOnError) fs.StringVar(&cfgFlag, "config", "", "The linter config file.") fs.StringVar(&fmtFlag, "output-format", "", "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.") - fs.StringVarP(&outFlag, "output-path", "o", "", "The output file path.\nIf not given, the linting results will be printed out to STDOUT.") - fs.BoolVar(&setExitStatusOnLintFailure, "set-exit-status", false, "Return exit status 1 when lint errors are found.") - fs.BoolVar(&versionFlag, "version", false, "Print version and exit.") fs.StringArrayVarP(&protoImportFlag, "proto-path", "I", nil, "The folder for searching proto imports.\nMay be specified multiple times; directories will be searched in order.\nThe current working directory is always used.") - fs.StringArrayVar(&protoDescFlag, "descriptor-set-in", nil, "The file containing a FileDescriptorSet for searching proto imports.\nMay be specified multiple times.") fs.StringArrayVar(&ruleEnableFlag, "enable-rule", nil, "Enable a rule with the given name.\nMay be specified multiple times.") fs.StringArrayVar(&ruleDisableFlag, "disable-rule", nil, "Disable a rule with the given name.\nMay be specified multiple times.") fs.BoolVar(&listRulesFlag, "list-rules", false, "Print the rules and exit. Honors the output-format flag.") @@ -91,14 +76,10 @@ func newCli(args []string) *cli { return &cli{ ConfigPath: cfgFlag, FormatType: fmtFlag, - OutputPath: outFlag, - ExitStatusOnLintFailure: setExitStatusOnLintFailure, ProtoImportPaths: protoImportFlag, - ProtoDescPath: protoDescFlag, EnabledRules: ruleEnableFlag, DisabledRules: ruleDisableFlag, ProtoFiles: fs.Args(), - VersionFlag: versionFlag, ListRulesFlag: listRulesFlag, DebugFlag: debugFlag, IgnoreCommentDisablesFlag: ignoreCommentDisablesFlag, @@ -106,11 +87,6 @@ func newCli(args []string) *cli { } func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { - // Print version and exit if asked. - if c.VersionFlag { - return nil - } - if c.ListRulesFlag { return outputRules(c.FormatType) } @@ -135,24 +111,13 @@ func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { configs = append(configs, lint.Config{ DisabledRules: c.DisabledRules, }) - // Prepare proto import lookup. - fs, err := loadFileDescriptors(c.ProtoDescPath...) - if err != nil { - return err - } - lookupImport := func(name string) (*desc.FileDescriptor, error) { - if f, found := fs[name]; found { - return f, nil - } - return nil, fmt.Errorf("%q is not found", name) - } + var errorsWithPos []protoparse.ErrorWithPos var lock sync.Mutex // Parse proto files into `protoreflect` file descriptors. p := protoparse.Parser{ ImportPaths: append(c.ProtoImportPaths, "."), IncludeSourceCodeInfo: true, - LookupImport: lookupImport, ErrorReporter: func(errorWithPos protoparse.ErrorWithPos) error { // Protoparse isn't concurrent right now but just to be safe for the future. lock.Lock() @@ -162,6 +127,8 @@ func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { return nil }, } + + var err error // Resolve file absolute paths to relative ones. // Using supplied import paths first. protoFiles := c.ProtoFiles @@ -207,14 +174,6 @@ func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { // Determine the output for writing the results. // Stdout is the default output. w := os.Stdout - if c.OutputPath != "" { - var err error - w, err = os.Create(c.OutputPath) - if err != nil { - return err - } - defer w.Close() - } // Determine the format for printing the results. // YAML format is the default. @@ -229,48 +188,9 @@ func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { return err } - // Return error on lint failure which subsequently - // exits with a non-zero status code - if c.ExitStatusOnLintFailure && anyProblems(results) { - return ExitForLintFailure - } - return nil } -func anyProblems(results []lint.Response) bool { - for i := range results { - if len(results[i].Problems) > 0 { - return true - } - } - return false -} - -func loadFileDescriptors(filePaths ...string) (map[string]*desc.FileDescriptor, error) { - fds := []*dpb.FileDescriptorProto{} - for _, filePath := range filePaths { - fs, err := readFileDescriptorSet(filePath) - if err != nil { - return nil, err - } - fds = append(fds, fs.GetFile()...) - } - return desc.CreateFileDescriptors(fds) -} - -func readFileDescriptorSet(filePath string) (*dpb.FileDescriptorSet, error) { - in, err := os.ReadFile(filePath) - if err != nil { - return nil, err - } - fs := &dpb.FileDescriptorSet{} - if err := proto.Unmarshal(in, fs); err != nil { - return nil, err - } - return fs, nil -} - var outputFormatFuncs = map[string]formatFunc{ "yaml": yaml.Marshal, "yml": yaml.Marshal, diff --git a/cmd/linter/main.go b/cmd/linter/main.go index 9e5fe26..4d5f61c 100644 --- a/cmd/linter/main.go +++ b/cmd/linter/main.go @@ -25,8 +25,7 @@ import ( ) var ( - globalRules = lint.NewRuleRegistry() - globalConfigs = defaultConfigs() + globalRules = lint.NewRuleRegistry() ) func init() { @@ -43,7 +42,7 @@ func main() { func runCLI(args []string) error { c := newCli(args) - return c.lint(globalRules, globalConfigs) + return c.lint(globalRules, nil) } // Enable all rules by default. diff --git a/cmd/protobuild/config.go b/cmd/protobuild/config.go index c9112ac..f3a685e 100644 --- a/cmd/protobuild/config.go +++ b/cmd/protobuild/config.go @@ -1,5 +1,7 @@ package protobuild +import "github.com/googleapis/api-linter/lint" + type Config struct { Checksum string `yaml:"checksum,omitempty" hash:"-"` Vendor string `yaml:"vendor,omitempty"` @@ -15,7 +17,15 @@ type Config struct { Depends []*depend `yaml:"deps,omitempty"` Plugins []*plugin `yaml:"plugins,omitempty" hash:"-"` changed bool - Installers []string `yaml:"installers,omitempty" hash:"-"` + Installers []string `yaml:"installers,omitempty" hash:"-"` + Linters lint.Configs `yaml:"linters,omitempty" hash:"-"` +} + +type LinterConfig struct { + IncludedPaths []string `json:"included_paths" yaml:"included_paths"` + ExcludedPaths []string `json:"excluded_paths" yaml:"excluded_paths"` + EnabledRules []string `json:"enabled_rules" yaml:"enabled_rules"` + DisabledRules []string `json:"disabled_rules" yaml:"disabled_rules"` } type basePluginCfg struct { diff --git a/cmd/protobuild/linter.go b/cmd/protobuild/linter.go new file mode 100644 index 0000000..4dfea9b --- /dev/null +++ b/cmd/protobuild/linter.go @@ -0,0 +1 @@ +package protobuild From 0a1089c7e42cb1f3bb02892ca783211d9f8e67c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 11:14:59 +0800 Subject: [PATCH 5/8] fix: barry quick fix, 2025-06-25 11:14:59 --- cmd/linter/cli.go | 8 ++++---- cmd/linter/main.go | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/cmd/linter/cli.go b/cmd/linter/cli.go index 761b34a..b2e2bbc 100644 --- a/cmd/linter/cli.go +++ b/cmd/linter/cli.go @@ -28,7 +28,7 @@ import ( "gopkg.in/yaml.v3" ) -type cli struct { +type cliArgs struct { ConfigPath string FormatType string ProtoImportPaths []string @@ -45,7 +45,7 @@ type cli struct { //lint:ignore ST1012 modifying this variable name is a breaking change. var ExitForLintFailure = errors.New("found problems during linting") -func newCli(args []string) *cli { +func newCli(args []string) *cliArgs { // Define flag variables. var cfgFlag string var fmtFlag string @@ -73,7 +73,7 @@ func newCli(args []string) *cli { panic(err) } - return &cli{ + return &cliArgs{ ConfigPath: cfgFlag, FormatType: fmtFlag, ProtoImportPaths: protoImportFlag, @@ -86,7 +86,7 @@ func newCli(args []string) *cli { } } -func (c *cli) lint(rules lint.RuleRegistry, configs lint.Configs) error { +func (c *cliArgs) lint(rules lint.RuleRegistry, configs lint.Configs) error { if c.ListRulesFlag { return outputRules(c.FormatType) } diff --git a/cmd/linter/main.go b/cmd/linter/main.go index 4d5f61c..a388c72 100644 --- a/cmd/linter/main.go +++ b/cmd/linter/main.go @@ -17,13 +17,24 @@ package main import ( - "log" - "os" - + "context" "github.com/googleapis/api-linter/lint" "github.com/googleapis/api-linter/rules" + "github.com/urfave/cli/v3" + "log" + "os" ) +func NewCmd() *cli.Command { + return &cli.Command{ + Name: "lint", + Usage: "lint protobuf", + Action: func(ctx context.Context, c *cli.Command) error { + return nil + }, + } +} + var ( globalRules = lint.NewRuleRegistry() ) From a51f4f49a9170e6769adee33415e740a8728cbaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 11:30:57 +0800 Subject: [PATCH 6/8] fix: barry quick fix, 2025-06-25 11:30:57 --- cmd/linter/cli.go | 2 +- cmd/linter/main.go | 2 +- go.mod | 8 ++++---- go.sum | 15 ++++++++------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/linter/cli.go b/cmd/linter/cli.go index b2e2bbc..cb334e8 100644 --- a/cmd/linter/cli.go +++ b/cmd/linter/cli.go @@ -86,7 +86,7 @@ func newCli(args []string) *cliArgs { } } -func (c *cliArgs) lint(rules lint.RuleRegistry, configs lint.Configs) error { +func linter(c *cliArgs, rules lint.RuleRegistry, configs lint.Configs) error { if c.ListRulesFlag { return outputRules(c.FormatType) } diff --git a/cmd/linter/main.go b/cmd/linter/main.go index a388c72..d4b3a2f 100644 --- a/cmd/linter/main.go +++ b/cmd/linter/main.go @@ -53,7 +53,7 @@ func main() { func runCLI(args []string) error { c := newCli(args) - return c.lint(globalRules, nil) + return linter(c, globalRules, nil) } // Enable all rules by default. diff --git a/go.mod b/go.mod index e1f66ac..386cfdf 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/a8m/envsubst v1.4.3 github.com/bufbuild/protocompile v0.14.1 github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a - github.com/dave/jennifer v1.6.0 + github.com/dave/jennifer v1.7.0 github.com/deckarep/golang-set/v2 v2.6.0 github.com/emicklei/proto v1.11.0 github.com/emicklei/proto-contrib v0.11.0 @@ -19,7 +19,7 @@ require ( github.com/jhump/protoreflect v1.17.0 github.com/lyft/protoc-gen-star/v2 v2.0.2-alpha github.com/open2b/scriggo v0.56.1 - github.com/pubgo/funk v0.5.49 + github.com/pubgo/funk v0.5.65 github.com/samber/lo v1.47.0 github.com/searKing/golang/go v1.2.115 github.com/spf13/cast v1.5.0 @@ -41,12 +41,12 @@ require ( github.com/alecthomas/repr v0.4.0 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect github.com/gertd/go-pluralize v0.2.1 // indirect - github.com/goccy/go-json v0.10.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/k0kubun/pp/v3 v3.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/phuslu/goid v1.0.0 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/spf13/afero v1.9.2 // indirect diff --git a/go.sum b/go.sum index e72bef7..cabafb3 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a h1:Ohw57yVY2dBTt+gsC6aZdteyxwlxfbtgkFEMTEkwgSw= github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/dave/jennifer v1.6.0 h1:MQ/6emI2xM7wt0tJzJzyUik2Q3Tcn2eE0vtYgh4GPVI= -github.com/dave/jennifer v1.6.0/go.mod h1:AxTG893FiZKqxy3FP1kL80VMshSMuz2G+EgvszgGRnk= +github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE= +github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -94,8 +94,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -197,8 +197,9 @@ github.com/lyft/protoc-gen-star/v2 v2.0.2-alpha/go.mod h1:RbbSxnunjxwTAoOxdNOMFJ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/open2b/scriggo v0.56.1 h1:h3IVNM0OEvszbtdmukaJj9lPo/xSvHPclYm/RqQqUxY= github.com/open2b/scriggo v0.56.1/go.mod h1:FJS0k7CaKq2sNlrqAGMwU4dCltYqC1c+Eak3dj5w26Q= github.com/phuslu/goid v1.0.0 h1:Cgcvd/R54UO1fCtyt+iKXAi+yZQ/KWlAm6MmZNizCLM= @@ -208,8 +209,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/pubgo/funk v0.5.49 h1:ATHSsDyQ8GWUvHtvPqqzH8rqe6NTN0f9XikWKU7c44k= -github.com/pubgo/funk v0.5.49/go.mod h1:Hm4oOYENrlr8A8nuH2YQWdx5jGg1fjAjaTvN2I28ts4= +github.com/pubgo/funk v0.5.65 h1:BP9mMOSiqycV6x5V2GuJBxniU2TsLPJQJHpOHCiu7kY= +github.com/pubgo/funk v0.5.65/go.mod h1:1YPKRM0yOD4uRZNKKF4LLwmVlLmnOP1xwNVoJqATuyY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= From bd61d7c69e2d3c43b1c530028a106d86d9ed9a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 12:06:38 +0800 Subject: [PATCH 7/8] fix: barry quick fix, 2025-06-25 12:06:38 --- cmd/linter/cli.go | 148 ++++++++++++++++------------------- cmd/linter/github_actions.go | 18 +---- cmd/linter/main.go | 65 --------------- cmd/linter/rules.go | 14 +++- cmd/protobuild/cmd.go | 13 +++ cmd/protobuild/linter.go | 1 - 6 files changed, 94 insertions(+), 165 deletions(-) delete mode 100644 cmd/linter/main.go delete mode 100644 cmd/protobuild/linter.go diff --git a/cmd/linter/cli.go b/cmd/linter/cli.go index cb334e8..516627e 100644 --- a/cmd/linter/cli.go +++ b/cmd/linter/cli.go @@ -1,18 +1,4 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main +package linters import ( "encoding/json" @@ -24,15 +10,14 @@ import ( "github.com/googleapis/api-linter/lint" "github.com/jhump/protoreflect/desc/protoparse" - "github.com/spf13/pflag" + "github.com/pubgo/protobuild/internal/typex" + "github.com/urfave/cli/v3" "gopkg.in/yaml.v3" ) -type cliArgs struct { - ConfigPath string +type CliArgs struct { FormatType string ProtoImportPaths []string - ProtoFiles []string EnabledRules []string DisabledRules []string ListRulesFlag bool @@ -40,77 +25,77 @@ type cliArgs struct { IgnoreCommentDisablesFlag bool } -// ExitForLintFailure indicates that a problem was found during linting. -// -//lint:ignore ST1012 modifying this variable name is a breaking change. -var ExitForLintFailure = errors.New("found problems during linting") - -func newCli(args []string) *cliArgs { - // Define flag variables. - var cfgFlag string - var fmtFlag string - var protoImportFlag []string - var ruleEnableFlag []string - var ruleDisableFlag []string - var listRulesFlag bool - var debugFlag bool - var ignoreCommentDisablesFlag bool - - // Register flag variables. - fs := pflag.NewFlagSet("api-linter", pflag.ExitOnError) - fs.StringVar(&cfgFlag, "config", "", "The linter config file.") - fs.StringVar(&fmtFlag, "output-format", "", "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.") - fs.StringArrayVarP(&protoImportFlag, "proto-path", "I", nil, "The folder for searching proto imports.\nMay be specified multiple times; directories will be searched in order.\nThe current working directory is always used.") - fs.StringArrayVar(&ruleEnableFlag, "enable-rule", nil, "Enable a rule with the given name.\nMay be specified multiple times.") - fs.StringArrayVar(&ruleDisableFlag, "disable-rule", nil, "Disable a rule with the given name.\nMay be specified multiple times.") - fs.BoolVar(&listRulesFlag, "list-rules", false, "Print the rules and exit. Honors the output-format flag.") - fs.BoolVar(&debugFlag, "debug", false, "Run in debug mode. Panics will print stack.") - fs.BoolVar(&ignoreCommentDisablesFlag, "ignore-comment-disables", false, "If set to true, disable comments will be ignored.\nThis is helpful when strict enforcement of AIPs are necessary and\nproto definitions should not be able to disable checks.") - - // Parse flags. - err := fs.Parse(args) - if err != nil { - panic(err) - } +func NewCli() (*CliArgs, typex.Flags) { + var cliArgs CliArgs + + return &cliArgs, typex.Flags{ + &cli.BoolFlag{ + Name: "ignore-comment-disables", + Usage: "If set to true, disable comments will be ignored.\nThis is helpful when strict enforcement of AIPs are necessary and\nproto definitions should not be able to disable checks.", + Value: false, + Destination: &cliArgs.IgnoreCommentDisablesFlag, + }, + + &cli.BoolFlag{ + Name: "debug", + Usage: "Run in debug mode. Panics will print stack.", + Value: false, + Destination: &cliArgs.DebugFlag, + }, - return &cliArgs{ - ConfigPath: cfgFlag, - FormatType: fmtFlag, - ProtoImportPaths: protoImportFlag, - EnabledRules: ruleEnableFlag, - DisabledRules: ruleDisableFlag, - ProtoFiles: fs.Args(), - ListRulesFlag: listRulesFlag, - DebugFlag: debugFlag, - IgnoreCommentDisablesFlag: ignoreCommentDisablesFlag, + &cli.BoolFlag{ + Name: "list-rules", + Usage: "Print the rules and exit. Honors the output-format flag.", + Value: false, + Destination: &cliArgs.ListRulesFlag, + }, + + &cli.StringFlag{ + Name: "output-format", + Usage: "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.", + Aliases: []string{"f"}, + Value: "", + Destination: &cliArgs.FormatType, + }, + + &cli.StringSliceFlag{ + Name: "proto-path", + Usage: "The folder for searching proto imports.\\nMay be specified multiple times; directories will be searched in order.\\nThe current working directory is always used.", + Aliases: []string{"I"}, + Value: nil, + Destination: &cliArgs.ProtoImportPaths, + }, + + &cli.StringSliceFlag{ + Name: "enable-rule", + Usage: "Enable a rule with the given name.\nMay be specified multiple times.", + Value: nil, + Destination: &cliArgs.EnabledRules, + }, + + &cli.StringSliceFlag{ + Name: "disable-rule", + Usage: "Disable a rule with the given name.\nMay be specified multiple times.", + Value: nil, + Destination: &cliArgs.DisabledRules, + }, } + } -func linter(c *cliArgs, rules lint.RuleRegistry, configs lint.Configs) error { +func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { if c.ListRulesFlag { return outputRules(c.FormatType) } // Pre-check if there are files to lint. - if len(c.ProtoFiles) == 0 { + if len(protoFiles) == 0 { return fmt.Errorf("no file to lint") } - // Read linter config and append it to the default. - if c.ConfigPath != "" { - config, err := lint.ReadConfigsFromFile(c.ConfigPath) - if err != nil { - return err - } - configs = append(configs, config...) - } + // Add configs for the enabled rules. - configs = append(configs, lint.Config{ - EnabledRules: c.EnabledRules, - }) - // Add configs for the disabled rules. - configs = append(configs, lint.Config{ - DisabledRules: c.DisabledRules, - }) + configs = append(configs, lint.Config{EnabledRules: c.EnabledRules}) + configs = append(configs, lint.Config{DisabledRules: c.DisabledRules}) var errorsWithPos []protoparse.ErrorWithPos var lock sync.Mutex @@ -131,9 +116,8 @@ func linter(c *cliArgs, rules lint.RuleRegistry, configs lint.Configs) error { var err error // Resolve file absolute paths to relative ones. // Using supplied import paths first. - protoFiles := c.ProtoFiles if len(c.ProtoImportPaths) > 0 { - protoFiles, err = protoparse.ResolveFilenames(c.ProtoImportPaths, c.ProtoFiles...) + protoFiles, err = protoparse.ResolveFilenames(c.ProtoImportPaths, protoFiles...) if err != nil { return err } @@ -164,8 +148,8 @@ func linter(c *cliArgs, rules lint.RuleRegistry, configs lint.Configs) error { return err } - // Create a linter to lint the file descriptors. - l := lint.New(rules, configs, lint.Debug(c.DebugFlag), lint.IgnoreCommentDisables(c.IgnoreCommentDisablesFlag)) + // Create a Linter to lint the file descriptors. + l := lint.New(globalRules, configs, lint.Debug(c.DebugFlag), lint.IgnoreCommentDisables(c.IgnoreCommentDisablesFlag)) results, err := l.LintProtos(fd...) if err != nil { return err diff --git a/cmd/linter/github_actions.go b/cmd/linter/github_actions.go index e43ed93..72a7f4e 100644 --- a/cmd/linter/github_actions.go +++ b/cmd/linter/github_actions.go @@ -1,18 +1,4 @@ -// Copyright 2022 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main +package linters import ( "bytes" @@ -52,7 +38,7 @@ func formatGitHubActionOutput(responses []lint.Response) []byte { } // GitHub uses :: as control characters (which are also used to delimit - // linter rules. In order to prevent confusion, replace the double colon + // Linter rules. In order to prevent confusion, replace the double colon // with two Armenian full stops which are indistinguishable to my eye. runeThatLooksLikeTwoColonsButIsActuallyTwoArmenianFullStops := "։։" title := strings.ReplaceAll(string(problem.RuleID), "::", runeThatLooksLikeTwoColonsButIsActuallyTwoArmenianFullStops) diff --git a/cmd/linter/main.go b/cmd/linter/main.go deleted file mode 100644 index d4b3a2f..0000000 --- a/cmd/linter/main.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The command line `api-linter` checks Google APIs defined in Protobuf files. -// It follows the API Improvement Proposals defined in https://aip.dev. -package main - -import ( - "context" - "github.com/googleapis/api-linter/lint" - "github.com/googleapis/api-linter/rules" - "github.com/urfave/cli/v3" - "log" - "os" -) - -func NewCmd() *cli.Command { - return &cli.Command{ - Name: "lint", - Usage: "lint protobuf", - Action: func(ctx context.Context, c *cli.Command) error { - return nil - }, - } -} - -var ( - globalRules = lint.NewRuleRegistry() -) - -func init() { - if err := rules.Add(globalRules); err != nil { - log.Fatalf("error when registering rules: %v", err) - } -} - -func main() { - if err := runCLI(os.Args[1:]); err != nil { - log.Fatalln(err) - } -} - -func runCLI(args []string) error { - c := newCli(args) - return linter(c, globalRules, nil) -} - -// Enable all rules by default. -// Once we have rules other than core, -// we will determine if we want to -// change this policy. -func defaultConfigs() lint.Configs { - return lint.Configs{} -} diff --git a/cmd/linter/rules.go b/cmd/linter/rules.go index f887035..dba53c8 100644 --- a/cmd/linter/rules.go +++ b/cmd/linter/rules.go @@ -1,12 +1,24 @@ -package main +package linters import ( + "github.com/googleapis/api-linter/rules" + "log" "os" "sort" "github.com/googleapis/api-linter/lint" ) +var ( + globalRules = lint.NewRuleRegistry() +) + +func init() { + if err := rules.Add(globalRules); err != nil { + log.Fatalf("error when registering rules: %v", err) + } +} + type ( listedRule struct { Name lint.RuleName diff --git a/cmd/protobuild/cmd.go b/cmd/protobuild/cmd.go index 7c68a41..ae6ed8b 100644 --- a/cmd/protobuild/cmd.go +++ b/cmd/protobuild/cmd.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + linters "github.com/pubgo/protobuild/cmd/linter" "io" "io/fs" "log/slog" @@ -51,6 +52,7 @@ const ( func Main() *cli.Command { var force bool + cliArgs, flags := linters.NewCli() app := &cli.Command{ Name: "protobuf", Usage: "protobuf generation, configuration and management", @@ -520,6 +522,17 @@ func Main() *cli.Command { return nil }, }, + &cli.Command{ + Name: "lint", + Usage: "lint protobuf", + Flags: flags, + Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { + return ctx, parseConfig() + }, + Action: func(ctx context.Context, c *cli.Command) error { + return linters.Linter(cliArgs, globalCfg.Linters, nil) + }, + }, }, } return app diff --git a/cmd/protobuild/linter.go b/cmd/protobuild/linter.go deleted file mode 100644 index 4dfea9b..0000000 --- a/cmd/protobuild/linter.go +++ /dev/null @@ -1 +0,0 @@ -package protobuild From 834f4899d4989d665c3a511be458d0357263b488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E9=87=8C=28barry=29?= Date: Wed, 25 Jun 2025 14:09:27 +0800 Subject: [PATCH 8/8] fix: barry quick fix, 2025-06-25 14:09:27 --- cmd/{linter => linters}/github_actions.go | 3 + cmd/{linter/cli.go => linters/lint.go} | 124 ++++++++++++---------- cmd/{linter => linters}/rules.go | 0 cmd/protobuild/cmd.go | 44 +++++++- cmd/protobuild/config.go | 15 +-- 5 files changed, 116 insertions(+), 70 deletions(-) rename cmd/{linter => linters}/github_actions.go (95%) rename cmd/{linter/cli.go => linters/lint.go} (55%) rename cmd/{linter => linters}/rules.go (100%) diff --git a/cmd/linter/github_actions.go b/cmd/linters/github_actions.go similarity index 95% rename from cmd/linter/github_actions.go rename to cmd/linters/github_actions.go index 72a7f4e..c87b753 100644 --- a/cmd/linter/github_actions.go +++ b/cmd/linters/github_actions.go @@ -3,6 +3,8 @@ package linters import ( "bytes" "fmt" + "github.com/samber/lo" + "path/filepath" "strings" "github.com/googleapis/api-linter/lint" @@ -17,6 +19,7 @@ func formatGitHubActionOutput(responses []lint.Response) []byte { // ::error file={name},line={line},endLine={endLine},title={title}::{message} // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message + fmt.Println(lo.Must(filepath.Abs(response.FilePath))) fmt.Fprintf(&buf, "::error file=%s", response.FilePath) if problem.Location != nil { // Some findings are *line level* and only have start positions but no diff --git a/cmd/linter/cli.go b/cmd/linters/lint.go similarity index 55% rename from cmd/linter/cli.go rename to cmd/linters/lint.go index 516627e..8d73598 100644 --- a/cmd/linter/cli.go +++ b/cmd/linters/lint.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/samber/lo" "os" "strings" "sync" @@ -16,25 +17,25 @@ import ( ) type CliArgs struct { - FormatType string - ProtoImportPaths []string - EnabledRules []string - DisabledRules []string - ListRulesFlag bool - DebugFlag bool - IgnoreCommentDisablesFlag bool + //FormatType string + //ProtoImportPaths []string + EnabledRules []string + DisabledRules []string + ListRulesFlag bool + DebugFlag bool + //IgnoreCommentDisablesFlag bool } func NewCli() (*CliArgs, typex.Flags) { var cliArgs CliArgs return &cliArgs, typex.Flags{ - &cli.BoolFlag{ - Name: "ignore-comment-disables", - Usage: "If set to true, disable comments will be ignored.\nThis is helpful when strict enforcement of AIPs are necessary and\nproto definitions should not be able to disable checks.", - Value: false, - Destination: &cliArgs.IgnoreCommentDisablesFlag, - }, + //&cli.BoolFlag{ + // Name: "ignore-comment-disables", + // Usage: "If set to true, disable comments will be ignored.\nThis is helpful when strict enforcement of AIPs are necessary and\nproto definitions should not be able to disable checks.", + // Value: false, + // Destination: &cliArgs.IgnoreCommentDisablesFlag, + //}, &cli.BoolFlag{ Name: "debug", @@ -50,42 +51,48 @@ func NewCli() (*CliArgs, typex.Flags) { Destination: &cliArgs.ListRulesFlag, }, - &cli.StringFlag{ - Name: "output-format", - Usage: "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.", - Aliases: []string{"f"}, - Value: "", - Destination: &cliArgs.FormatType, - }, - - &cli.StringSliceFlag{ - Name: "proto-path", - Usage: "The folder for searching proto imports.\\nMay be specified multiple times; directories will be searched in order.\\nThe current working directory is always used.", - Aliases: []string{"I"}, - Value: nil, - Destination: &cliArgs.ProtoImportPaths, - }, - - &cli.StringSliceFlag{ - Name: "enable-rule", - Usage: "Enable a rule with the given name.\nMay be specified multiple times.", - Value: nil, - Destination: &cliArgs.EnabledRules, - }, - - &cli.StringSliceFlag{ - Name: "disable-rule", - Usage: "Disable a rule with the given name.\nMay be specified multiple times.", - Value: nil, - Destination: &cliArgs.DisabledRules, - }, + //&cli.StringFlag{ + // Name: "output-format", + // Usage: "The format of the linting results.\nSupported formats include \"yaml\", \"json\",\"github\" and \"summary\" table.\nYAML is the default.", + // Aliases: []string{"f"}, + // Value: "", + // Destination: &cliArgs.FormatType, + //}, + + //&cli.StringSliceFlag{ + // Name: "proto-path", + // Usage: "The folder for searching proto imports.\\nMay be specified multiple times; directories will be searched in order.\\nThe current working directory is always used.", + // Aliases: []string{"I"}, + // Value: nil, + // Destination: &cliArgs.ProtoImportPaths, + //}, + + //&cli.StringSliceFlag{ + // Name: "enable-rule", + // Usage: "Enable a rule with the given name.\nMay be specified multiple times.", + // Value: nil, + // Destination: &cliArgs.EnabledRules, + //}, + // + //&cli.StringSliceFlag{ + // Name: "disable-rule", + // Usage: "Disable a rule with the given name.\nMay be specified multiple times.", + // Value: nil, + // Destination: &cliArgs.DisabledRules, + //}, } } -func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { +type LinterConfig struct { + Rules lint.Config `yaml:"rules,omitempty" hash:"-"` + FormatType string `yaml:"format_type"` + IgnoreCommentDisablesFlag bool `yaml:"ignore_comment_disables_flag"` +} + +func Linter(c *CliArgs, config LinterConfig, protoImportPaths []string, protoFiles []string) error { if c.ListRulesFlag { - return outputRules(c.FormatType) + return outputRules(config.FormatType) } // Pre-check if there are files to lint. @@ -93,15 +100,17 @@ func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { return fmt.Errorf("no file to lint") } + rules := lint.Configs{config.Rules} + // Add configs for the enabled rules. - configs = append(configs, lint.Config{EnabledRules: c.EnabledRules}) - configs = append(configs, lint.Config{DisabledRules: c.DisabledRules}) + rules = append(rules, lint.Config{EnabledRules: c.EnabledRules}) + rules = append(rules, lint.Config{DisabledRules: c.DisabledRules}) var errorsWithPos []protoparse.ErrorWithPos var lock sync.Mutex // Parse proto files into `protoreflect` file descriptors. p := protoparse.Parser{ - ImportPaths: append(c.ProtoImportPaths, "."), + ImportPaths: append(protoImportPaths, "."), IncludeSourceCodeInfo: true, ErrorReporter: func(errorWithPos protoparse.ErrorWithPos) error { // Protoparse isn't concurrent right now but just to be safe for the future. @@ -116,8 +125,8 @@ func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { var err error // Resolve file absolute paths to relative ones. // Using supplied import paths first. - if len(c.ProtoImportPaths) > 0 { - protoFiles, err = protoparse.ResolveFilenames(c.ProtoImportPaths, protoFiles...) + if len(protoImportPaths) > 0 { + protoFiles, err = protoparse.ResolveFilenames(protoImportPaths, protoFiles...) if err != nil { return err } @@ -132,6 +141,7 @@ func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { if err != nil { return err } + fd, err := p.ParseFiles(protoFiles...) if err != nil { if err == protoparse.ErrInvalidSource { @@ -149,27 +159,27 @@ func Linter(c *CliArgs, configs lint.Configs, protoFiles []string) error { } // Create a Linter to lint the file descriptors. - l := lint.New(globalRules, configs, lint.Debug(c.DebugFlag), lint.IgnoreCommentDisables(c.IgnoreCommentDisablesFlag)) + l := lint.New(globalRules, rules, lint.Debug(c.DebugFlag), lint.IgnoreCommentDisables(config.IgnoreCommentDisablesFlag)) results, err := l.LintProtos(fd...) if err != nil { return err } - // Determine the output for writing the results. - // Stdout is the default output. - w := os.Stdout - // Determine the format for printing the results. // YAML format is the default. - marshal := getOutputFormatFunc(c.FormatType) + marshal := getOutputFormatFunc(config.FormatType) // Print the results. b, err := marshal(results) if err != nil { return err } - if _, err = w.Write(b); err != nil { - return err + + fmt.Println(string(b)) + + filterResults := lo.Filter(results, func(item lint.Response, index int) bool { return len(item.Problems) > 0 }) + if len(filterResults) > 0 { + os.Exit(1) } return nil diff --git a/cmd/linter/rules.go b/cmd/linters/rules.go similarity index 100% rename from cmd/linter/rules.go rename to cmd/linters/rules.go diff --git a/cmd/protobuild/cmd.go b/cmd/protobuild/cmd.go index ae6ed8b..d2767b4 100644 --- a/cmd/protobuild/cmd.go +++ b/cmd/protobuild/cmd.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - linters "github.com/pubgo/protobuild/cmd/linter" "io" "io/fs" "log/slog" @@ -20,6 +19,7 @@ import ( "github.com/pubgo/funk/pathutil" "github.com/pubgo/funk/recovery" "github.com/pubgo/funk/strutil" + linters "github.com/pubgo/protobuild/cmd/linters" "github.com/pubgo/protobuild/internal/modutil" "github.com/pubgo/protobuild/internal/shutil" "github.com/pubgo/protobuild/internal/typex" @@ -524,13 +524,51 @@ func Main() *cli.Command { }, &cli.Command{ Name: "lint", - Usage: "lint protobuf", + Usage: "lint protobuf https://linter.aip.dev/rules/", Flags: flags, Before: func(ctx context.Context, command *cli.Command) (context.Context, error) { return ctx, parseConfig() }, Action: func(ctx context.Context, c *cli.Command) error { - return linters.Linter(cliArgs, globalCfg.Linters, nil) + var protoPaths []string + for i := range globalCfg.Root { + if pathutil.IsNotExist(globalCfg.Root[i]) { + log.Printf("file %s not found", globalCfg.Root[i]) + continue + } + + assert.Must(filepath.WalkDir(globalCfg.Root[i], func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + protoPaths = append(protoPaths, path) + } + + return nil + })) + } + + protoPaths = lo.Uniq(protoPaths) + for _, path := range protoPaths { + // check contains proto file in dir + protoFiles := lo.Map(assert.Must1(os.ReadDir(path)), func(item os.DirEntry, index int) string { + return filepath.Join(path, item.Name()) + }) + protoFiles = lo.Filter(protoFiles, func(item string, index int) bool { return strings.HasSuffix(item, ".proto") }) + if len(protoFiles) == 0 { + continue + } + + includes := lo.Uniq(append(globalCfg.Includes, globalCfg.Vendor)) + err := linters.Linter(cliArgs, globalCfg.Linter, includes, protoFiles) + if err != nil { + return err + } + } + + return nil }, }, }, diff --git a/cmd/protobuild/config.go b/cmd/protobuild/config.go index f3a685e..e5be479 100644 --- a/cmd/protobuild/config.go +++ b/cmd/protobuild/config.go @@ -1,6 +1,8 @@ package protobuild -import "github.com/googleapis/api-linter/lint" +import ( + "github.com/pubgo/protobuild/cmd/linters" +) type Config struct { Checksum string `yaml:"checksum,omitempty" hash:"-"` @@ -17,15 +19,8 @@ type Config struct { Depends []*depend `yaml:"deps,omitempty"` Plugins []*plugin `yaml:"plugins,omitempty" hash:"-"` changed bool - Installers []string `yaml:"installers,omitempty" hash:"-"` - Linters lint.Configs `yaml:"linters,omitempty" hash:"-"` -} - -type LinterConfig struct { - IncludedPaths []string `json:"included_paths" yaml:"included_paths"` - ExcludedPaths []string `json:"excluded_paths" yaml:"excluded_paths"` - EnabledRules []string `json:"enabled_rules" yaml:"enabled_rules"` - DisabledRules []string `json:"disabled_rules" yaml:"disabled_rules"` + Installers []string `yaml:"installers,omitempty" hash:"-"` + Linter linters.LinterConfig `yaml:"linter,omitempty" hash:"-"` } type basePluginCfg struct {