diff --git a/sg/logger.go b/sg/logger.go index aec81094..2fe6b928 100644 --- a/sg/logger.go +++ b/sg/logger.go @@ -33,6 +33,12 @@ func WithLogger(ctx context.Context, logger *log.Logger) context.Context { return context.WithValue(ctx, loggerContextKey{}, logger) } +// AppendLoggerPrefix appends a prefix to the current logger. +func AppendLoggerPrefix(ctx context.Context, prefix string) context.Context { + logger := Logger(ctx) + return WithLogger(ctx, log.New(logger.Writer(), logger.Prefix()+prefix, logger.Flags())) +} + // Logger returns the log.Logger attached to ctx, or a default logger. func Logger(ctx context.Context) *log.Logger { if value := ctx.Value(loggerContextKey{}); value != nil { diff --git a/tools/sggovulncheck/tools.go b/tools/sggovulncheck/tools.go index b806ed42..367643b4 100644 --- a/tools/sggovulncheck/tools.go +++ b/tools/sggovulncheck/tools.go @@ -2,7 +2,10 @@ package sggovulncheck import ( "context" + "fmt" + "io/fs" "os/exec" + "path/filepath" "go.einride.tech/sage/sg" "go.einride.tech/sage/sgtool" @@ -10,19 +13,59 @@ import ( const ( name = "govulncheck" - version = "latest" + version = "v1.0.0" ) +// Command returns an [*exec.Cmd] for govulncheck. func Command(ctx context.Context, args ...string) *exec.Cmd { sg.Deps(ctx, PrepareCommand) return sg.Command(ctx, sg.FromBinDir(name), args...) } +// RunAll runs govulncheck on all the specified module paths, or all module paths from the current git root by default. +func RunAll(ctx context.Context, modulePaths ...string) error { + var commands []*exec.Cmd + if err := filepath.WalkDir(sg.FromGitRoot(), func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() || d.Name() != "go.mod" { + return nil + } + if len(modulePaths) > 0 { + var shouldRunInModulePath bool + for _, modulePath := range modulePaths { + if modulePath == path { + shouldRunInModulePath = true + break + } + } + if !shouldRunInModulePath { + return nil + } + } + relativePath, err := filepath.Rel(sg.FromGitRoot(), path) + if err != nil { + return err + } + cmd := Command( + sg.AppendLoggerPrefix(ctx, fmt.Sprintf(" (%s) ", relativePath)), + "-C", filepath.Dir(path), "./...", + ) + commands = append(commands, cmd) + return cmd.Start() + }); err != nil { + return err + } + for _, cmd := range commands { + if err := cmd.Wait(); err != nil { + return err + } + } + return nil +} + func PrepareCommand(ctx context.Context) error { - _, err := sgtool.GoInstall( - ctx, - "golang.org/x/vuln/cmd/govulncheck", - version, - ) + _, err := sgtool.GoInstall(ctx, "golang.org/x/vuln/cmd/govulncheck", version) return err }