Skip to content

Commit 07244fd

Browse files
authored
Merge pull request #5960 from tonistiigi/workdir-epoch
dockerfile: make WORKDIR respect SOURCE_DATE_EPOCH
2 parents 3bee376 + 01b3eb4 commit 07244fd

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

frontend/dockerfile/dockerfile2llb/convert.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,9 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
13991399
if user := d.image.Config.User; user != "" {
14001400
mkdirOpt = append(mkdirOpt, llb.WithUser(user))
14011401
}
1402+
if d.epoch != nil {
1403+
mkdirOpt = append(mkdirOpt, llb.WithCreatedTime(*d.epoch))
1404+
}
14021405
platform := opt.targetPlatform
14031406
if d.platform != nil {
14041407
platform = *d.platform

frontend/dockerfile/dockerfile_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ var heredocTests = []integration.Test{}
234234
// Tests that depend on reproducible env
235235
var reproTests = integration.TestFuncs(
236236
testReproSourceDateEpoch,
237+
testWorkdirSourceDateEpochReproducible,
237238
)
238239

239240
var (
@@ -910,6 +911,84 @@ WORKDIR /
910911
require.Equal(t, true, fi.IsDir())
911912
}
912913

914+
// testWorkdirSourceDateEpochReproducible ensures that WORKDIR is reproducible with SOURCE_DATE_EPOCH.
915+
func testWorkdirSourceDateEpochReproducible(t *testing.T, sb integration.Sandbox) {
916+
integration.SkipOnPlatform(t, "windows")
917+
workers.CheckFeatureCompat(t, sb, workers.FeatureOCIExporter, workers.FeatureSourceDateEpoch)
918+
f := getFrontend(t, sb)
919+
920+
dockerfile := []byte(`
921+
FROM alpine
922+
WORKDIR /mydir
923+
`)
924+
925+
dir := integration.Tmpdir(
926+
t,
927+
fstest.CreateFile("Dockerfile", dockerfile, 0600),
928+
)
929+
930+
c, err := client.New(sb.Context(), sb.Address())
931+
require.NoError(t, err)
932+
defer c.Close()
933+
934+
destDir1 := t.TempDir()
935+
epoch := fmt.Sprintf("%d", time.Date(2023, 1, 10, 15, 34, 56, 0, time.UTC).Unix())
936+
937+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
938+
FrontendAttrs: map[string]string{
939+
"build-arg:SOURCE_DATE_EPOCH": epoch,
940+
},
941+
Exports: []client.ExportEntry{
942+
{
943+
Type: client.ExporterOCI,
944+
OutputDir: destDir1,
945+
Attrs: map[string]string{
946+
"tar": "false",
947+
},
948+
},
949+
},
950+
LocalMounts: map[string]fsutil.FS{
951+
dockerui.DefaultLocalNameDockerfile: dir,
952+
dockerui.DefaultLocalNameContext: dir,
953+
},
954+
}, nil)
955+
require.NoError(t, err)
956+
957+
index1, err := os.ReadFile(filepath.Join(destDir1, "index.json"))
958+
require.NoError(t, err)
959+
960+
// Prune all cache
961+
ensurePruneAll(t, c, sb)
962+
963+
time.Sleep(3 * time.Second)
964+
965+
destDir2 := t.TempDir()
966+
_, err = f.Solve(sb.Context(), c, client.SolveOpt{
967+
FrontendAttrs: map[string]string{
968+
"build-arg:SOURCE_DATE_EPOCH": epoch,
969+
},
970+
Exports: []client.ExportEntry{
971+
{
972+
Type: client.ExporterOCI,
973+
OutputDir: destDir2,
974+
Attrs: map[string]string{
975+
"tar": "false",
976+
},
977+
},
978+
},
979+
LocalMounts: map[string]fsutil.FS{
980+
dockerui.DefaultLocalNameDockerfile: dir,
981+
dockerui.DefaultLocalNameContext: dir,
982+
},
983+
}, nil)
984+
require.NoError(t, err)
985+
986+
index2, err := os.ReadFile(filepath.Join(destDir2, "index.json"))
987+
require.NoError(t, err)
988+
989+
require.Equal(t, index1, index2)
990+
}
991+
913992
func testCacheReleased(t *testing.T, sb integration.Sandbox) {
914993
f := getFrontend(t, sb)
915994

0 commit comments

Comments
 (0)