From 6111e725f6a1038f44c13e72665e8649b57a5afc Mon Sep 17 00:00:00 2001 From: Talon Bowler Date: Wed, 4 Sep 2024 03:25:33 -0700 Subject: [PATCH] add sourceInfoMap callback when printing warnings for with command. Signed-off-by: Talon Bowler --- commands/bake.go | 13 +++++- commands/build.go | 101 ++++++++++++++++++++++++++++++---------------- 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/commands/bake.go b/commands/bake.go index bec1cadda07..d37ace1a247 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -332,10 +332,17 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba res = sp.ExporterResponse } + printArgs := &printResultArgs{ + callFunc: pf, + res: res, + contextPath: req.Inputs.ContextPath, + dockerfileName: req.Inputs.DockerfilePath, + } if callFormatJSON { jsonResults[name] = map[string]any{} buf := &bytes.Buffer{} - if code, err := printResult(buf, pf, res); err != nil { + printArgs.writer = buf + if code, err := printResult(printArgs); err != nil { jsonResults[name]["error"] = err.Error() exitCode = 1 } else if code != 0 && exitCode == 0 { @@ -355,13 +362,15 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba } else { sep = true } + fmt.Fprintf(dockerCli.Out(), "%s\n", name) if descr := tgts[name].Description; descr != "" { fmt.Fprintf(dockerCli.Out(), "%s\n", descr) } fmt.Fprintln(dockerCli.Out()) - if code, err := printResult(dockerCli.Out(), pf, res); err != nil { + printArgs.writer = dockerCli.Out() + if code, err := printResult(printArgs); err != nil { fmt.Fprintf(dockerCli.Out(), "error: %v\n", err) exitCode = 1 } else if code != 0 && exitCode == 0 { diff --git a/commands/build.go b/commands/build.go index 2d6025bdd10..6f7fcc0e148 100644 --- a/commands/build.go +++ b/commands/build.go @@ -49,6 +49,7 @@ import ( "github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/targets" "github.com/moby/buildkit/solver/errdefs" + solverpb "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/grpcerrors" "github.com/moby/buildkit/util/progress/progressui" "github.com/morikuni/aec" @@ -387,7 +388,14 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions) } } if opts.CallFunc != nil { - if exitcode, err := printResult(dockerCli.Out(), opts.CallFunc, resp.ExporterResponse); err != nil { + printArgs := &printResultArgs{ + writer: os.Stdout, + callFunc: opts.CallFunc, + res: resp.ExporterResponse, + contextPath: options.contextPath, + dockerfileName: options.dockerfileName, + } + if exitcode, err := printResult(printArgs); err != nil { return err } else if exitcode != 0 { os.Exit(exitcode) @@ -882,38 +890,66 @@ func printWarnings(w io.Writer, warnings []client.VertexWarning, mode progressui } } -func printResult(w io.Writer, f *controllerapi.CallFunc, res map[string]string) (int, error) { - switch f.Name { +type printResultArgs struct { + writer io.Writer + callFunc *controllerapi.CallFunc + res map[string]string + contextPath string + dockerfileName string +} + +func printResult(printArgs *printResultArgs) (int, error) { + switch printArgs.callFunc.Name { case "outline": - return 0, printValue(w, outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version, f.Format, res) + return 0, printValue(printArgs, outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version) case "targets": - return 0, printValue(w, targets.PrintTargets, targets.SubrequestsTargetsDefinition.Version, f.Format, res) + return 0, printValue(printArgs, targets.PrintTargets, targets.SubrequestsTargetsDefinition.Version) case "subrequests.describe": - return 0, printValue(w, subrequests.PrintDescribe, subrequests.SubrequestsDescribeDefinition.Version, f.Format, res) + return 0, printValue(printArgs, subrequests.PrintDescribe, subrequests.SubrequestsDescribeDefinition.Version) case "lint": lintResults := lint.LintResults{} - if result, ok := res["result.json"]; ok { + if result, ok := printArgs.res["result.json"]; ok { if err := json.Unmarshal([]byte(result), &lintResults); err != nil { return 0, err } } warningCount := len(lintResults.Warnings) - if f.Format != "json" && warningCount > 0 { + if printArgs.callFunc.Format != "json" && warningCount > 0 { var warningCountMsg string if warningCount == 1 { warningCountMsg = "1 warning has been found!" } else if warningCount > 1 { warningCountMsg = fmt.Sprintf("%d warnings have been found!", warningCount) } - fmt.Fprintf(w, "Check complete, %s\n", warningCountMsg) + fmt.Fprintf(printArgs.writer, "Check complete, %s\n", warningCountMsg) + } + + sourceInfoMap := func(sourceInfo *solverpb.SourceInfo) *solverpb.SourceInfo { + newSourceInfo := &solverpb.SourceInfo{} + *newSourceInfo = *sourceInfo + + contextPath := "." + if printArgs.contextPath != "" { + contextPath = printArgs.contextPath + } + + dockerfileName := printArgs.dockerfileName + if dockerfileName == "" { + dockerfileName = filepath.Join(contextPath, "Dockerfile") + } + + if strings.HasSuffix(dockerfileName, sourceInfo.Filename) { + newSourceInfo.Filename = dockerfileName + } + return newSourceInfo } lintPrintFunc := func(b []byte, w io.Writer) error { - return lintResults.PrintTo(w, nil) + return lintResults.PrintTo(w, sourceInfoMap) } - err := printValue(w, lintPrintFunc, lint.SubrequestLintDefinition.Version, f.Format, res) + err := printValue(printArgs, lintPrintFunc, lint.SubrequestLintDefinition.Version) if err != nil { return 0, err } @@ -923,32 +959,27 @@ func printResult(w io.Writer, f *controllerapi.CallFunc, res map[string]string) // Normally, we would use `errdefs.WithSource` to attach the source to the // error and let the error be printed by the handling that's already in place, // but here we want to print the error in a way that's consistent with how - // the lint warnings are printed via the `lint.PrintLintViolations` function, + // the lint warnings are printed via the `lintResults.PrintTo` function, // which differs from the default error printing. - if f.Format != "json" && len(lintResults.Warnings) > 0 { - fmt.Fprintln(w) - } - lintBuf := bytes.NewBuffer([]byte(lintResults.Error.Message + "\n")) - sourceInfo := lintResults.Sources[lintResults.Error.Location.SourceIndex] - source := errdefs.Source{ - Info: sourceInfo, - Ranges: lintResults.Error.Location.Ranges, + if printArgs.callFunc.Format != "json" && len(lintResults.Warnings) > 0 { + fmt.Fprintln(printArgs.writer) } - source.Print(lintBuf) + lintBuf := bytes.NewBuffer(nil) + lintResults.PrintErrorTo(lintBuf) return 0, errors.New(lintBuf.String()) - } else if len(lintResults.Warnings) == 0 && f.Format != "json" { - fmt.Fprintln(w, "Check complete, no warnings found.") + } else if len(lintResults.Warnings) == 0 && printArgs.callFunc.Format != "json" { + fmt.Fprintln(printArgs.writer, "Check complete, no warnings found.") } default: - if dt, ok := res["result.json"]; ok && f.Format == "json" { - fmt.Fprintln(w, dt) - } else if dt, ok := res["result.txt"]; ok { - fmt.Fprint(w, dt) + if dt, ok := printArgs.res["result.json"]; ok && printArgs.callFunc.Format == "json" { + fmt.Fprintln(printArgs.writer, dt) + } else if dt, ok := printArgs.res["result.txt"]; ok { + fmt.Fprint(printArgs.writer, dt) } else { - fmt.Fprintf(w, "%s %+v\n", f, res) + fmt.Fprintf(printArgs.writer, "%s %+v\n", printArgs.callFunc, printArgs.res) } } - if v, ok := res["result.statuscode"]; !f.IgnoreStatus && ok { + if v, ok := printArgs.res["result.statuscode"]; !printArgs.callFunc.IgnoreStatus && ok { if n, err := strconv.Atoi(v); err == nil && n != 0 { return n, nil } @@ -958,18 +989,18 @@ func printResult(w io.Writer, f *controllerapi.CallFunc, res map[string]string) type callFunc func([]byte, io.Writer) error -func printValue(w io.Writer, printer callFunc, version string, format string, res map[string]string) error { - if format == "json" { - fmt.Fprintln(w, res["result.json"]) +func printValue(printArgs *printResultArgs, printer callFunc, version string) error { + if printArgs.callFunc.Format == "json" { + fmt.Fprintln(printArgs.writer, printArgs.res["result.json"]) return nil } - if res["version"] != "" && versions.LessThan(version, res["version"]) && res["result.txt"] != "" { + if printArgs.res["version"] != "" && versions.LessThan(version, printArgs.res["version"]) && printArgs.res["result.txt"] != "" { // structure is too new and we don't know how to print it - fmt.Fprint(w, res["result.txt"]) + fmt.Fprint(printArgs.writer, printArgs.res["result.txt"]) return nil } - return printer([]byte(res["result.json"]), w) + return printer([]byte(printArgs.res["result.json"]), printArgs.writer) } type invokeConfig struct {