Browse Source

select services implicitly declared by a service:xx build dependency

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 7 months ago
parent
commit
fc8c56b407
4 changed files with 41 additions and 31 deletions
  1. 1 22
      cmd/compose/build.go
  2. 28 1
      pkg/compose/build.go
  3. 0 0
      pkg/compose/build_test.go
  4. 12 8
      pkg/e2e/build_test.go

+ 1 - 22
cmd/compose/build.go

@@ -27,7 +27,6 @@ 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"
 
@@ -141,13 +140,11 @@ func buildCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
 }
 
 func runBuild(ctx context.Context, dockerCli command.Cli, backend api.Service, opts buildOptions, services []string) error {
-	project, _, err := opts.ToProject(ctx, dockerCli, services, cli.WithResolvedPaths(true), cli.WithoutEnvironmentResolution)
+	project, _, err := opts.ToProject(ctx, dockerCli, nil, cli.WithResolvedPaths(true), cli.WithoutEnvironmentResolution)
 	if err != nil {
 		return err
 	}
 
-	services = addBuildDependencies(services, project)
-
 	if err := applyPlatforms(project, false); err != nil {
 		return err
 	}
@@ -159,21 +156,3 @@ 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()
-}

+ 28 - 1
pkg/compose/build.go

@@ -85,7 +85,16 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
 		policy = types.IncludeDependencies
 	}
 
-	err := project.ForEachService(options.Services, func(serviceName string, service *types.ServiceConfig) error {
+	if len(options.Services) > 0 {
+		// As user requested some services to be built, also include those used as additional_contexts
+		options.Services = addBuildDependencies(options.Services, project)
+	}
+	project, err := project.WithSelectedServices(options.Services)
+	if err != nil {
+		return nil, err
+	}
+
+	err = project.ForEachService(options.Services, func(serviceName string, service *types.ServiceConfig) error {
 		if service.Build == nil {
 			return nil
 		}
@@ -613,3 +622,21 @@ func parsePlatforms(service types.ServiceConfig) ([]specs.Platform, error) {
 
 	return ret, nil
 }
+
+func addBuildDependencies(services []string, project *types.Project) []string {
+	servicesWithDependencies := utils.NewSet(services...)
+	for _, service := range services {
+		b := project.Services[service].Build
+		if b != nil {
+			for _, target := range b.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()
+}

+ 0 - 0
cmd/compose/build_test.go → pkg/compose/build_test.go


+ 12 - 8
pkg/e2e/build_test.go

@@ -117,14 +117,14 @@ func TestLocalComposeBuild(t *testing.T) {
 		})
 
 		t.Run(env+" rebuild when up --build", func(t *testing.T) {
-			res := c.RunDockerComposeCmd(t, "--workdir", "fixtures/build-test", "up", "-d", "--build")
+			res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "up", "-d", "--build")
 
 			res.Assert(t, icmd.Expected{Out: "COPY static /usr/share/nginx/html"})
 			res.Assert(t, icmd.Expected{Out: "COPY static2 /usr/share/nginx/html"})
 		})
 
 		t.Run(env+" build --push ignored for unnamed images", func(t *testing.T) {
-			res := c.RunDockerComposeCmd(t, "--workdir", "fixtures/build-test", "build", "--push", "nginx")
+			res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test", "build", "--push", "nginx")
 			assert.Assert(t, !strings.Contains(res.Stdout(), "failed to push"), res.Stdout())
 		})
 
@@ -232,7 +232,7 @@ func TestBuildTags(t *testing.T) {
 }
 
 func TestBuildImageDependencies(t *testing.T) {
-	doTest := func(t *testing.T, cli *CLI) {
+	doTest := func(t *testing.T, cli *CLI, args ...string) {
 		resetState := func() {
 			cli.RunDockerComposeCmd(t, "down", "--rmi=all", "-t=0")
 			res := cli.RunDockerOrExitError(t, "image", "rm", "build-dependencies-service")
@@ -250,7 +250,7 @@ func TestBuildImageDependencies(t *testing.T) {
 			Err:      "No such image: build-dependencies-service",
 		})
 
-		res = cli.RunDockerComposeCmd(t, "build")
+		res = cli.RunDockerComposeCmd(t, args...)
 		t.Log(res.Combined())
 
 		res = cli.RunDockerCmd(t,
@@ -273,7 +273,8 @@ func TestBuildImageDependencies(t *testing.T) {
 			"DOCKER_BUILDKIT=0",
 			"COMPOSE_FILE=./fixtures/build-dependencies/classic.yaml",
 		))
-		doTest(t, cli)
+		doTest(t, cli, "build")
+		doTest(t, cli, "build", "--with-dependencies", "service")
 	})
 
 	t.Run("BuildKit by dependency order", func(t *testing.T) {
@@ -281,7 +282,8 @@ func TestBuildImageDependencies(t *testing.T) {
 			"DOCKER_BUILDKIT=1",
 			"COMPOSE_FILE=./fixtures/build-dependencies/classic.yaml",
 		))
-		doTest(t, cli)
+		doTest(t, cli, "build")
+		doTest(t, cli, "build", "--with-dependencies", "service")
 	})
 
 	t.Run("BuildKit by additional contexts", func(t *testing.T) {
@@ -289,7 +291,8 @@ func TestBuildImageDependencies(t *testing.T) {
 			"DOCKER_BUILDKIT=1",
 			"COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml",
 		))
-		doTest(t, cli)
+		doTest(t, cli, "build")
+		doTest(t, cli, "build", "service")
 	})
 
 	t.Run("Bake by additional contexts", func(t *testing.T) {
@@ -297,7 +300,8 @@ func TestBuildImageDependencies(t *testing.T) {
 			"DOCKER_BUILDKIT=1", "COMPOSE_BAKE=1",
 			"COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml",
 		))
-		doTest(t, cli)
+		doTest(t, cli, "build")
+		doTest(t, cli, "build", "service")
 	})
 }