diff --git a/cmd/compose/build.go b/cmd/compose/build.go index 951449214..bd3f10b00 100644 --- a/cmd/compose/build.go +++ b/cmd/compose/build.go @@ -27,6 +27,7 @@ import ( "github.com/docker/cli/cli/command" cliopts "github.com/docker/cli/opts" ui "github.com/docker/compose/v2/pkg/progress" + "github.com/docker/compose/v2/pkg/utils" buildkit "github.com/moby/buildkit/util/progress/progressui" "github.com/spf13/cobra" @@ -145,6 +146,8 @@ func runBuild(ctx context.Context, dockerCli command.Cli, backend api.Service, o return err } + services = addBuildDependencies(services, project) + if err := applyPlatforms(project, false); err != nil { return err } @@ -156,3 +159,21 @@ func runBuild(ctx context.Context, dockerCli command.Cli, backend api.Service, o return backend.Build(ctx, project, apiBuildOptions) } + +func addBuildDependencies(services []string, project *types.Project) []string { + servicesWithDependencies := utils.NewSet(services...) + for _, service := range services { + build := project.Services[service].Build + if build != nil { + for _, target := range build.AdditionalContexts { + if s, found := strings.CutPrefix(target, types.ServicePrefix); found { + servicesWithDependencies.Add(s) + } + } + } + } + if len(servicesWithDependencies) > len(services) { + return addBuildDependencies(servicesWithDependencies.Elements(), project) + } + return servicesWithDependencies.Elements() +} diff --git a/cmd/compose/build_test.go b/cmd/compose/build_test.go new file mode 100644 index 000000000..fa0a9e2c4 --- /dev/null +++ b/cmd/compose/build_test.go @@ -0,0 +1,57 @@ +/* + Copyright 2020 Docker Compose CLI authors + + 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 + + http://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 compose + +import ( + "slices" + "testing" + + "github.com/compose-spec/compose-go/v2/types" + "gotest.tools/v3/assert" +) + +func Test_addBuildDependencies(t *testing.T) { + project := &types.Project{Services: types.Services{ + "test": types.ServiceConfig{ + Build: &types.BuildConfig{ + AdditionalContexts: map[string]string{ + "foo": "service:foo", + "bar": "service:bar", + }, + }, + }, + "foo": types.ServiceConfig{ + Build: &types.BuildConfig{ + AdditionalContexts: map[string]string{ + "zot": "service:zot", + }, + }, + }, + "bar": types.ServiceConfig{ + Build: &types.BuildConfig{}, + }, + "zot": types.ServiceConfig{ + Build: &types.BuildConfig{}, + }, + }} + + services := addBuildDependencies([]string{"test"}, project) + expected := []string{"test", "foo", "bar", "zot"} + slices.Sort(services) + slices.Sort(expected) + assert.DeepEqual(t, services, expected) +}