Skip to content

Commit 4d7be04

Browse files
Update Coverage for client and proveance
Signed-off-by: Natnael Gebremariam <ngebremariam@microsoft.com>
1 parent 649062d commit 4d7be04

File tree

3 files changed

+86
-25
lines changed

3 files changed

+86
-25
lines changed

.github/workflows/.test.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ jobs:
8989
name: Build
9090
uses: docker/bake-action@v6
9191
with:
92+
files: |
93+
./docker-bake.hcl
9294
targets: integration-tests-base
9395
set: |
9496
*.cache-from=type=gha,scope=${{ inputs.cache_scope }}
@@ -110,11 +112,13 @@ jobs:
110112
- containerd-rootless
111113
- containerd-1.7
112114
- containerd-2.0
113-
- containerd-snapshotter-stargz
115+
# Disabled: requires kernel modules not available on GitHub-hosted runners
116+
# - containerd-snapshotter-stargz
114117
- oci
115118
- oci-rootless
116119
- oci-rootless-slirp4netns-detachnetns
117-
- oci-snapshotter-stargz
120+
# Disabled: requires kernel modules not available on GitHub-hosted runners
121+
# - oci-snapshotter-stargz
118122
pkg: ${{ fromJson(needs.prepare.outputs.pkgs) }}
119123
kind: ${{ fromJson(needs.prepare.outputs.kinds) }}
120124
tags: ${{ fromJson(needs.prepare.outputs.tags) }}
@@ -155,6 +159,8 @@ jobs:
155159
name: Build test image
156160
uses: docker/bake-action@v6
157161
with:
162+
files: |
163+
./docker-bake.hcl
158164
targets: integration-tests
159165
set: |
160166
*.cache-from=type=gha,scope=${{ inputs.cache_scope }}

client/client_test.go

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,11 +1710,30 @@ func testFrontendImageNaming(t *testing.T, sb integration.Sandbox) {
17101710
}
17111711

17121712
func testSecretMounts(t *testing.T, sb integration.Sandbox) {
1713-
integration.SkipOnPlatform(t, "windows")
1713+
// https://docs.docker.com/engine/swarm/secrets/
1714+
1715+
// Windows vs Linux secret implementation differences:
1716+
//
1717+
// Linux: Secrets are mounted as files using tmpfs at /run/secrets/ (RAM-based, encrypted)
1718+
//
1719+
// Windows: Secrets are stored in C:\ProgramData\Docker\internal\secrets (clear text on disk)
1720+
// Symbolic links point to the desired target (default: C:\ProgramData\Docker\secrets)
1721+
// Windows does NOT support tmpfs or non-directory file bind-mounts
1722+
// UID/GID/mode options are NOT supported on Windows
1723+
// Recommend BitLocker for at-rest encryption
1724+
//
1725+
// BuildKit Issue: The "invalid windows mount type: 'tmpfs'" error occurs because BuildKit
1726+
// currently tries to use tmpfs for all secret mounts. This needs to be fixed in BuildKit's
1727+
// secret mount implementation to use the Windows symlink approach instead.
1728+
1729+
// For now, this test is Linux-only until BuildKit properly implements Windows secret mounts
1730+
// without tmpfs. Use testSecretEnv for Windows-compatible environment-based secrets.
1731+
integration.SkipOnPlatform(t, "windows", "Windows does not support tmpfs for secret mounts")
17141732
c, err := New(sb.Context(), sb.Address())
17151733
require.NoError(t, err)
17161734
defer c.Close()
17171735

1736+
// Test 1: Basic secret mount with content verification (Linux only)
17181737
st := llb.Image("busybox:latest").
17191738
Run(llb.Shlex(`sh -c 'mount | grep mysecret | grep "type tmpfs" && [ "$(cat /run/secrets/mysecret)" = 'foo-secret' ]'`), llb.AddSecret("/run/secrets/mysecret"))
17201739

@@ -1728,7 +1747,7 @@ func testSecretMounts(t *testing.T, sb integration.Sandbox) {
17281747
}, nil)
17291748
require.NoError(t, err)
17301749

1731-
// test optional, mount should not exist when secret not present in SolveOpt
1750+
// Test 2: Optional secret - mount should not exist when secret not present in SolveOpt
17321751
st = llb.Image("busybox:latest").
17331752
Run(llb.Shlex(`test ! -f /run/secrets/mysecret2`), llb.AddSecret("/run/secrets/mysecret2", llb.SecretOptional))
17341753

@@ -1743,6 +1762,7 @@ func testSecretMounts(t *testing.T, sb integration.Sandbox) {
17431762
_, err = c.Solve(sb.Context(), def, SolveOpt{}, nil)
17441763
require.NoError(t, err)
17451764

1765+
// Test 3: Required secret missing - should error
17461766
st = llb.Image("busybox:latest").
17471767
Run(llb.Shlex(`echo secret3`), llb.AddSecret("/run/secrets/mysecret3"))
17481768

@@ -1754,7 +1774,7 @@ func testSecretMounts(t *testing.T, sb integration.Sandbox) {
17541774
}, nil)
17551775
require.Error(t, err)
17561776

1757-
// test id,perm,uid
1777+
// Test 4: Secret with custom ID and file permissions
17581778
st = llb.Image("busybox:latest").
17591779
Run(llb.Shlex(`sh -c '[ "$(stat -c "%u %g %f" /run/secrets/mysecret4)" = "1 1 81ff" ]' `), llb.AddSecret("/run/secrets/mysecret4", llb.SecretID("mysecret"), llb.SecretFileOpt(1, 1, 0777)))
17601780

@@ -1768,7 +1788,7 @@ func testSecretMounts(t *testing.T, sb integration.Sandbox) {
17681788
}, nil)
17691789
require.NoError(t, err)
17701790

1771-
// test empty cert still creates secret file
1791+
// Test 5: Empty secret still creates secret file
17721792
st = llb.Image("busybox:latest").
17731793
Run(llb.Shlex(`test -f /run/secrets/mysecret5`), llb.AddSecret("/run/secrets/mysecret5", llb.SecretID("mysecret")))
17741794

@@ -1784,13 +1804,22 @@ func testSecretMounts(t *testing.T, sb integration.Sandbox) {
17841804
}
17851805

17861806
func testSecretEnv(t *testing.T, sb integration.Sandbox) {
1787-
integration.SkipOnPlatform(t, "windows")
17881807
c, err := New(sb.Context(), sb.Address())
17891808
require.NoError(t, err)
17901809
defer c.Close()
17911810

1792-
st := llb.Image("busybox:latest").
1793-
Run(llb.Shlex(`sh -c '[ "$(echo ${MY_SECRET})" = 'foo-secret' ]'`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1811+
imgName := integration.UnixOrWindows("busybox:latest", "nanoserver:latest")
1812+
var st llb.ExecState
1813+
1814+
// Test 1: Verify secret value is accessible as environment variable
1815+
switch imgName {
1816+
case "nanoserver:latest":
1817+
st = llb.Image(imgName).
1818+
Run(llb.Shlex(`cmd /C "if "%MY_SECRET%"=="foo-secret" (exit 0) else (exit 1)"`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1819+
case "busybox:latest":
1820+
st = llb.Image(imgName).
1821+
Run(llb.Shlex(`sh -c '[ "$(echo ${MY_SECRET})" = 'foo-secret' ]'`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1822+
}
17941823

17951824
def, err := st.Marshal(sb.Context())
17961825
require.NoError(t, err)
@@ -1802,9 +1831,15 @@ func testSecretEnv(t *testing.T, sb integration.Sandbox) {
18021831
}, nil)
18031832
require.NoError(t, err)
18041833

1805-
// test optional
1806-
st = llb.Image("busybox:latest").
1807-
Run(llb.Shlex(`sh -c '[ -z "${MY_SECRET}" ]'`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true), llb.SecretOptional))
1834+
// Test 2: Optional secret not provided should be unset/empty
1835+
switch imgName {
1836+
case "nanoserver:latest":
1837+
st = llb.Image(imgName).
1838+
Run(llb.Shlex(`cmd /C "if not defined MY_SECRET (exit 0) else (exit 1)"`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true), llb.SecretOptional))
1839+
case "busybox:latest":
1840+
st = llb.Image(imgName).
1841+
Run(llb.Shlex(`sh -c '[ -z "${MY_SECRET}" ]'`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true), llb.SecretOptional))
1842+
}
18081843

18091844
def, err = st.Marshal(sb.Context())
18101845
require.NoError(t, err)
@@ -1817,8 +1852,15 @@ func testSecretEnv(t *testing.T, sb integration.Sandbox) {
18171852
_, err = c.Solve(sb.Context(), def, SolveOpt{}, nil)
18181853
require.NoError(t, err)
18191854

1820-
st = llb.Image("busybox:latest").
1821-
Run(llb.Shlex(`echo foo`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1855+
// Test 3: Required secret not provided should error
1856+
switch imgName {
1857+
case "nanoserver:latest":
1858+
st = llb.Image(imgName).
1859+
Run(llb.Shlex(`cmd /C "echo foo"`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1860+
case "busybox:latest":
1861+
st = llb.Image(imgName).
1862+
Run(llb.Shlex(`echo foo`), llb.AddSecret("MY_SECRET", llb.SecretAsEnv(true)))
1863+
}
18221864

18231865
def, err = st.Marshal(sb.Context())
18241866
require.NoError(t, err)
@@ -1828,12 +1870,21 @@ func testSecretEnv(t *testing.T, sb integration.Sandbox) {
18281870
}, nil)
18291871
require.Error(t, err)
18301872

1831-
// test id
1832-
st = llb.Image("busybox:latest").
1833-
Run(llb.Shlex(`sh -c '[ "$(echo ${MYPASSWORD}-${MYTOKEN})" = "pw-token" ]' `),
1834-
llb.AddSecret("MYPASSWORD", llb.SecretID("pass"), llb.SecretAsEnv(true)),
1835-
llb.AddSecret("MYTOKEN", llb.SecretAsEnv(true)),
1836-
)
1873+
// Test 4: Multiple secrets with custom IDs
1874+
switch imgName {
1875+
case "nanoserver:latest":
1876+
st = llb.Image(imgName).
1877+
Run(llb.Shlex(`cmd /C "if "%MYPASSWORD%-%MYTOKEN%"=="pw-token" (exit 0) else (exit 1)"`),
1878+
llb.AddSecret("MYPASSWORD", llb.SecretID("pass"), llb.SecretAsEnv(true)),
1879+
llb.AddSecret("MYTOKEN", llb.SecretAsEnv(true)),
1880+
)
1881+
case "busybox:latest":
1882+
st = llb.Image(imgName).
1883+
Run(llb.Shlex(`sh -c '[ "$(echo ${MYPASSWORD}-${MYTOKEN})" = "pw-token" ]' `),
1884+
llb.AddSecret("MYPASSWORD", llb.SecretID("pass"), llb.SecretAsEnv(true)),
1885+
llb.AddSecret("MYTOKEN", llb.SecretAsEnv(true)),
1886+
)
1887+
}
18371888

18381889
def, err = st.Marshal(sb.Context())
18391890
require.NoError(t, err)
@@ -5125,7 +5176,7 @@ func testBuildExportWithUncompressed(t *testing.T, sb integration.Sandbox) {
51255176
}
51265177

51275178
func testBuildExportZstd(t *testing.T, sb integration.Sandbox) {
5128-
integration.SkipOnPlatform(t, "windows")
5179+
integration.SkipOnPlatform(t, "windows", "Windows container support incomplete: AddMount() fails with 'number of mounts should always be 1 for Windows layers', OCI export fails with 'windowsLcowDiff does not implement Compare method'")
51295180
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter)
51305181
c, err := New(sb.Context(), sb.Address())
51315182
require.NoError(t, err)

frontend/dockerfile/dockerfile_provenance_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,6 @@ ENV FOO=bar
13491349

13501350
// https://github.com/moby/buildkit/issues/3562
13511351
func testDuplicatePlatformProvenance(t *testing.T, sb integration.Sandbox) {
1352-
integration.SkipOnPlatform(t, "windows")
13531352
workers.CheckFeatureCompat(t, sb, workers.FeatureProvenance)
13541353
ctx := sb.Context()
13551354

@@ -1361,19 +1360,24 @@ func testDuplicatePlatformProvenance(t *testing.T, sb integration.Sandbox) {
13611360

13621361
dockerfile := []byte(
13631362
`
1364-
FROM alpine as base-linux
1365-
FROM nanoserver as base-windows
1363+
FROM alpine AS base-linux
1364+
FROM nanoserver AS base-windows
13661365
FROM base-$TARGETOS
13671366
`,
13681367
)
13691368
dir := integration.Tmpdir(
13701369
t,
13711370
fstest.CreateFile("Dockerfile", dockerfile, 0600),
13721371
)
1372+
1373+
platform := integration.UnixOrWindows(
1374+
"linux/amd64,linux/amd64", // Linux worker: duplicate call on Linux platform
1375+
"windows/amd64,windows/amd64", // Windows worker: duplicate call on Windows platform
1376+
)
13731377
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
13741378
FrontendAttrs: map[string]string{
13751379
"attest:provenance": "mode=max",
1376-
"platform": "linux/amd64,linux/amd64",
1380+
"platform": platform,
13771381
},
13781382
LocalMounts: map[string]fsutil.FS{
13791383
dockerui.DefaultLocalNameDockerfile: dir,

0 commit comments

Comments
 (0)