compose integration tests

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2025-07-24 11:45:30 +02:00
parent a1ca46e85e
commit 03000cc590
6 changed files with 209 additions and 8 deletions
+4
View File
@@ -12,6 +12,7 @@ ARG DOCKER_CLI_VERSION=${DOCKER_VERSION}
ARG GOTESTSUM_VERSION=v1.12.0 ARG GOTESTSUM_VERSION=v1.12.0
ARG REGISTRY_VERSION=3.0.0 ARG REGISTRY_VERSION=3.0.0
ARG BUILDKIT_VERSION=v0.23.2 ARG BUILDKIT_VERSION=v0.23.2
ARG COMPOSE_VERSION=v2.39.0
ARG UNDOCK_VERSION=0.9.0 ARG UNDOCK_VERSION=0.9.0
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@@ -24,6 +25,7 @@ FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_27 AS docker-cli-alt27
FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_26 AS docker-cli-alt26 FROM dockereng/cli-bin:$DOCKER_VERSION_ALT_26 AS docker-cli-alt26
FROM registry:$REGISTRY_VERSION AS registry FROM registry:$REGISTRY_VERSION AS registry
FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit
FROM docker/compose-bin:$COMPOSE_VERSION AS compose
FROM crazymax/undock:$UNDOCK_VERSION AS undock FROM crazymax/undock:$UNDOCK_VERSION AS undock
FROM golatest AS gobase FROM golatest AS gobase
@@ -137,8 +139,10 @@ COPY --link --from=docker-cli-alt27 / /opt/docker-alt-27/
COPY --link --from=docker-cli-alt26 / /opt/docker-alt-26/ COPY --link --from=docker-cli-alt26 / /opt/docker-alt-26/
COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/
COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/
COPY --link --from=compose /docker-compose /usr/bin/compose
COPY --link --from=undock /usr/local/bin/undock /usr/bin/ COPY --link --from=undock /usr/local/bin/undock /usr/bin/
COPY --link --from=binaries /buildx /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/
RUN mkdir -p /usr/local/lib/docker/cli-plugins && ln -s /usr/bin/buildx /usr/local/lib/docker/cli-plugins/docker-buildx
ENV TEST_DOCKER_EXTRA="docker@27.5=/opt/docker-alt-27,docker@26.1=/opt/docker-alt-26" ENV TEST_DOCKER_EXTRA="docker@27.5=/opt/docker-alt-27,docker@26.1=/opt/docker-alt-26"
FROM integration-test-base AS integration-test FROM integration-test-base AS integration-test
+6 -6
View File
@@ -72,9 +72,9 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeMetadataWarningsDedup, testBakeMetadataWarningsDedup,
testBakeMultiExporters, testBakeMultiExporters,
testBakeLoadPush, testBakeLoadPush,
testListTargets, testBakeListTargets,
testListVariables, testBakeListVariables,
testListTypedVariables, testBakeListTypedVariables,
testBakeCallCheck, testBakeCallCheck,
testBakeCallCheckFlag, testBakeCallCheckFlag,
testBakeCallMetadata, testBakeCallMetadata,
@@ -1691,7 +1691,7 @@ target "default" {
// TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181 // TODO: test metadata file when supported by multi exporters https://github.com/docker/buildx/issues/2181
} }
func testListTargets(t *testing.T, sb integration.Sandbox) { func testBakeListTargets(t *testing.T, sb integration.Sandbox) {
bakefile := []byte(` bakefile := []byte(`
target "foo" { target "foo" {
description = "This builds foo" description = "This builds foo"
@@ -1714,7 +1714,7 @@ target "abc" {
require.Equal(t, "TARGET\tDESCRIPTION\nabc\t\nfoo\tThis builds foo", strings.TrimSpace(out)) require.Equal(t, "TARGET\tDESCRIPTION\nabc\t\nfoo\tThis builds foo", strings.TrimSpace(out))
} }
func testListVariables(t *testing.T, sb integration.Sandbox) { func testBakeListVariables(t *testing.T, sb integration.Sandbox) {
bakefile := []byte(` bakefile := []byte(`
variable "foo" { variable "foo" {
default = "bar" default = "bar"
@@ -1743,7 +1743,7 @@ target "default" {
require.Equal(t, "VARIABLE\tTYPE\tVALUE\tDESCRIPTION\nabc\t\t\t<null>\t\ndef\t\t\t\t\nfoo\t\t\tbar\tThis is foo", strings.TrimSpace(out)) require.Equal(t, "VARIABLE\tTYPE\tVALUE\tDESCRIPTION\nabc\t\t\t<null>\t\ndef\t\t\t\t\nfoo\t\t\tbar\tThis is foo", strings.TrimSpace(out))
} }
func testListTypedVariables(t *testing.T, sb integration.Sandbox) { func testBakeListTypedVariables(t *testing.T, sb integration.Sandbox) {
bakefile := []byte(` bakefile := []byte(`
variable "abc" { variable "abc" {
type = string type = string
+2 -2
View File
@@ -76,7 +76,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildSecret, testBuildSecret,
testBuildDefaultLoad, testBuildDefaultLoad,
testBuildCall, testBuildCall,
testCheckCallOutput, testBuildCheckCallOutput,
testBuildExtraHosts, testBuildExtraHosts,
} }
@@ -1241,7 +1241,7 @@ COPy --from=base \
}) })
} }
func testCheckCallOutput(t *testing.T, sb integration.Sandbox) { func testBuildCheckCallOutput(t *testing.T, sb integration.Sandbox) {
t.Run("check for warning count msg in check without warnings", func(t *testing.T) { t.Run("check for warning count msg in check without warnings", func(t *testing.T) {
dockerfile := []byte(` dockerfile := []byte(`
FROM busybox AS base FROM busybox AS base
+172
View File
@@ -0,0 +1,172 @@
package tests
import (
"fmt"
"os"
"testing"
"github.com/containerd/continuity/fs/fstest"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/integration"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
)
var composeTests = []func(t *testing.T, sb integration.Sandbox){
testComposeBuildLocalStore,
testComposeBuildRegistry,
testComposeBuildMultiPlatform,
testComposeBuildCheck,
}
func testComposeBuildLocalStore(t *testing.T, sb integration.Sandbox) {
if !isDockerWorker(sb) && !isDockerContainerWorker(sb) {
t.Skip("only testing with docker and docker-container worker")
}
target := "buildx:local-" + identity.NewID()
dir := composeTestProject(target, t)
t.Cleanup(func() {
cmd := dockerCmd(sb, withArgs("image", "rm", target))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())
})
cmd := composeCmd(sb, withDir(dir), withArgs("build"))
out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out))
cmd = dockerCmd(sb, withArgs("image", "inspect", target))
cmd.Stderr = os.Stderr
require.NoError(t, cmd.Run())
}
func testComposeBuildRegistry(t *testing.T, sb integration.Sandbox) {
registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)
target := registry + "/buildx/registry:latest"
dir := composeTestProject(target, t)
cmd := composeCmd(sb, withDir(dir), withArgs("build", "--push"))
out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out))
desc, provider, err := contentutil.ProviderFromRef(target)
require.NoError(t, err)
_, err = testutil.ReadImages(sb.Context(), provider, desc)
require.NoError(t, err)
}
func testComposeBuildMultiPlatform(t *testing.T, sb integration.Sandbox) {
registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
t.Skip(err.Error())
}
require.NoError(t, err)
target := registry + "/buildx/registry:latest"
dockerfile := []byte(`
FROM busybox:latest
COPY foo /etc/foo
`)
composefile := fmt.Appendf([]byte{}, `
services:
bar:
build:
context: .
platforms:
- linux/amd64
- linux/arm64
image: %s
`, target)
dir := tmpdir(
t,
fstest.CreateFile("compose.yml", composefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)
cmd := composeCmd(sb, withDir(dir), withArgs("build", "--push"))
out, err := cmd.CombinedOutput()
if !isMobyWorker(sb) {
require.NoError(t, err, string(out))
desc, provider, err := contentutil.ProviderFromRef(target)
require.NoError(t, err)
imgs, err := testutil.ReadImages(sb.Context(), provider, desc)
require.NoError(t, err)
img := imgs.Find("linux/amd64")
require.NotNil(t, img)
img = imgs.Find("linux/arm64")
require.NotNil(t, img)
} else {
require.Error(t, err, string(out))
require.Contains(t, string(out), "Multi-platform build is not supported")
}
}
func testComposeBuildCheck(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`
frOM busybox as base
cOpy Dockerfile .
from scratch
COPy --from=base \
/Dockerfile \
/
`)
composefile := []byte(`
services:
bar:
build:
context: .
`)
dir := tmpdir(
t,
fstest.CreateFile("compose.yml", composefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)
cmd := composeCmd(sb, withDir(dir), withArgs("build", "--check"))
out, err := cmd.CombinedOutput()
require.Error(t, err, string(out))
require.Contains(t, string(out), "Check complete, 3 warnings have been found!")
}
func composeTestProject(imageName string, t *testing.T) string {
dockerfile := []byte(`
FROM busybox:latest AS base
COPY foo /etc/foo
RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
composefile := fmt.Appendf([]byte{}, `
services:
bar:
build:
context: .
image: %s
`, imageName)
return tmpdir(
t,
fstest.CreateFile("compose.yml", composefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)
}
+24
View File
@@ -75,6 +75,30 @@ func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
return cmd return cmd
} }
func composeCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
cmd := exec.Command("compose")
cmd.Env = os.Environ()
for _, opt := range opts {
opt(cmd)
}
if builder := sb.Address(); builder != "" {
cmd.Env = append(cmd.Env,
"BUILDX_CONFIG="+buildxConfig(sb),
"BUILDX_BUILDER="+builder,
)
}
if context := sb.DockerAddress(); context != "" {
cmd.Env = append(cmd.Env, "DOCKER_CONTEXT="+context)
}
if v := os.Getenv("GO_TEST_COVERPROFILE"); v != "" {
coverDir := filepath.Join(filepath.Dir(v), "helpers")
cmd.Env = append(cmd.Env, "GOCOVERDIR="+coverDir)
}
cmd.Env = append(cmd.Env, "COMPOSE_BAKE=true")
return cmd
}
func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
cmd := exec.Command("docker") cmd := exec.Command("docker")
cmd.Env = os.Environ() cmd.Env = os.Environ()
+1
View File
@@ -32,6 +32,7 @@ func TestIntegration(t *testing.T) {
tests = append(tests, createTests...) tests = append(tests, createTests...)
tests = append(tests, rmTests...) tests = append(tests, rmTests...)
tests = append(tests, dialstdioTests...) tests = append(tests, dialstdioTests...)
tests = append(tests, composeTests...)
testIntegration(t, tests...) testIntegration(t, tests...)
} }