diff --git a/cmd/compose/build.go b/cmd/compose/build.go index 58636e0dc..f31fbd28a 100644 --- a/cmd/compose/build.go +++ b/cmd/compose/build.go @@ -45,6 +45,7 @@ type buildOptions struct { builder string deps bool print bool + check bool } func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) { @@ -79,6 +80,7 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, Deps: opts.deps, Memory: int64(opts.memory), Print: opts.print, + Check: opts.check, SSHs: SSHKeys, Builder: builderName, }, nil @@ -135,6 +137,7 @@ func buildCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) flags.StringVar(&p.Progress, "progress", string(buildkit.AutoMode), fmt.Sprintf(`Set type of ui output (%s)`, strings.Join(printerModes, ", "))) flags.MarkHidden("progress") //nolint:errcheck flags.BoolVar(&opts.print, "print", false, "Print equivalent bake file") + flags.BoolVar(&opts.check, "check", false, "Check build configuration") return cmd } diff --git a/docs/reference/compose_build.md b/docs/reference/compose_build.md index 98d573e44..5589a4693 100644 --- a/docs/reference/compose_build.md +++ b/docs/reference/compose_build.md @@ -17,6 +17,7 @@ run `docker compose build` to rebuild it. |:----------------------|:--------------|:--------|:------------------------------------------------------------------------------------------------------------| | `--build-arg` | `stringArray` | | Set build-time variables for services | | `--builder` | `string` | | Set builder to use | +| `--check` | `bool` | | Check build configuration | | `--dry-run` | `bool` | | Execute command in dry run mode | | `-m`, `--memory` | `bytes` | `0` | Set memory limit for the build container. Not supported by BuildKit. | | `--no-cache` | `bool` | | Do not use cache when building the image | diff --git a/docs/reference/docker_compose_build.yaml b/docs/reference/docker_compose_build.yaml index 3f53dcf73..1197d5314 100644 --- a/docs/reference/docker_compose_build.yaml +++ b/docs/reference/docker_compose_build.yaml @@ -33,6 +33,16 @@ options: experimentalcli: false kubernetes: false swarm: false + - option: check + value_type: bool + default_value: "false" + description: Check build configuration + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false - option: compress value_type: bool default_value: "true" diff --git a/pkg/api/api.go b/pkg/api/api.go index 6745991d4..0b159b22c 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -157,6 +157,8 @@ type BuildOptions struct { Builder string // Print don't actually run builder but print equivalent build config Print bool + // Check let builder validate build configuration + Check bool } // Apply mutates project according to build options diff --git a/pkg/compose/build_bake.go b/pkg/compose/build_bake.go index 589ed5405..31864cef8 100644 --- a/pkg/compose/build_bake.go +++ b/pkg/compose/build_bake.go @@ -176,12 +176,16 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project privileged = true } - var output string + var outputs []string + var call string push := options.Push && service.Image != "" - if len(service.Build.Platforms) > 1 { - output = fmt.Sprintf("type=image,push=%t", push) - } else { - output = fmt.Sprintf("type=docker,load=true,push=%t", push) + switch { + case options.Check: + call = "lint" + case len(service.Build.Platforms) > 1: + outputs = []string{fmt.Sprintf("type=image,push=%t", push)} + default: + outputs = []string{fmt.Sprintf("type=docker,load=true,push=%t", push)} } read = append(read, build.Context) @@ -212,7 +216,9 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project ShmSize: build.ShmSize, Ulimits: toBakeUlimits(build.Ulimits), Entitlements: entitlements, - Outputs: []string{output}, + + Outputs: outputs, + Call: call, } group.Targets = append(group.Targets, serviceName) } @@ -284,7 +290,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project return nil, err } - var errMessage string + var errMessage []string scanner := bufio.NewScanner(pipe) scanner.Split(bufio.ScanLines) @@ -300,7 +306,9 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project err := decoder.Decode(&status) if err != nil { if strings.HasPrefix(line, "ERROR: ") { - errMessage = line[7:] + errMessage = append(errMessage, line[7:]) + } else { + errMessage = append(errMessage, line) } continue } @@ -310,8 +318,8 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project err = eg.Wait() if err != nil { - if errMessage != "" { - return nil, errors.New(errMessage) + if len(errMessage) > 0 { + return nil, errors.New(strings.Join(errMessage, "\n")) } return nil, fmt.Errorf("failed to execute bake: %w", err) } diff --git a/pkg/e2e/build_test.go b/pkg/e2e/build_test.go index 1b31f6fbe..6061ee106 100644 --- a/pkg/e2e/build_test.go +++ b/pkg/e2e/build_test.go @@ -300,8 +300,8 @@ func TestBuildImageDependencies(t *testing.T) { "DOCKER_BUILDKIT=1", "COMPOSE_BAKE=1", "COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml", )) - doTest(t, cli, "build") - doTest(t, cli, "build", "service") + doTest(t, cli, "--verbose", "build") + doTest(t, cli, "--verbose", "build", "service") }) }