@@ -40,9 +40,11 @@ import (
40
40
"github.com/moby/buildkit/solver/errdefs"
41
41
"github.com/moby/buildkit/solver/pb"
42
42
"github.com/moby/buildkit/util/contentutil"
43
+ "github.com/moby/buildkit/util/iohelper"
43
44
"github.com/moby/buildkit/util/testutil"
44
45
"github.com/moby/buildkit/util/testutil/httpserver"
45
46
"github.com/moby/buildkit/util/testutil/integration"
47
+ digest "github.com/opencontainers/go-digest"
46
48
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
47
49
"github.com/pkg/errors"
48
50
"github.com/stretchr/testify/require"
@@ -168,6 +170,11 @@ var networkTests = []integration.Test{}
168
170
// Tests that depend on heredoc support
169
171
var heredocTests = []integration.Test {}
170
172
173
+ // Tests that depend on reproducible env
174
+ var reproTests = integration .TestFuncs (
175
+ testReproSourceDateEpoch ,
176
+ )
177
+
171
178
var opts []integration.TestOpt
172
179
var securityOpts []integration.TestOpt
173
180
@@ -217,6 +224,10 @@ func TestIntegration(t *testing.T) {
217
224
integration .Run (t , heredocTests , opts ... )
218
225
integration .Run (t , outlineTests , opts ... )
219
226
integration .Run (t , targetsTests , opts ... )
227
+
228
+ integration .Run (t , reproTests , append (opts ,
229
+ // Only use the amd64 digest, regardless to the host platform
230
+ integration .WithMirroredImages (integration .OfficialImages ("debian:bullseye-20230109-slim@sha256:1acb06a0c31fb467eb8327ad361f1091ab265e0bf26d452dea45dcb0c0ea5e75" )))... )
220
231
}
221
232
222
233
func testDefaultEnvWithArgs (t * testing.T , sb integration.Sandbox ) {
@@ -6470,6 +6481,87 @@ COPY Dockerfile \
6470
6481
require .Equal (t , 1 , w .Level )
6471
6482
}
6472
6483
6484
+ func testReproSourceDateEpoch (t * testing.T , sb integration.Sandbox ) {
6485
+ integration .CheckFeatureCompat (t , sb , integration .FeatureOCIExporter , integration .FeatureSourceDateEpoch )
6486
+ if sb .Snapshotter () == "native" {
6487
+ t .Skip ("the digest is not reproducible with the \" native\" snapshotter because hardlinks are processed in a different way: https://github.com/moby/buildkit/pull/3456#discussion_r1062650263" )
6488
+ }
6489
+ if runtime .GOARCH != "amd64" {
6490
+ t .Skip ("FIXME: the image cannot be pulled on non-amd64 (`docker.io/arm64v8/debian:bullseye-20230109-slim@...: not found`): https://github.com/moby/buildkit/pull/3456#discussion_r1068989918" )
6491
+ }
6492
+
6493
+ f := getFrontend (t , sb )
6494
+
6495
+ tm := time .Date (2023 , time .January , 10 , 12 , 34 , 56 , 0 , time .UTC )
6496
+ t .Logf ("SOURCE_DATE_EPOCH=%d" , tm .Unix ())
6497
+
6498
+ dockerfile := []byte (`# The base image cannot be busybox, due to https://github.com/moby/buildkit/issues/3455
6499
+ FROM --platform=linux/amd64 debian:bullseye-20230109-slim@sha256:1acb06a0c31fb467eb8327ad361f1091ab265e0bf26d452dea45dcb0c0ea5e75
6500
+ RUN touch /foo
6501
+ RUN touch /foo.1
6502
+ RUN touch -d '2010-01-01 12:34:56' /foo-2010
6503
+ RUN touch -d '2010-01-01 12:34:56' /foo-2010.1
6504
+ RUN touch -d '2030-01-01 12:34:56' /foo-2030
6505
+ RUN touch -d '2030-01-01 12:34:56' /foo-2030.1
6506
+ RUN rm -f /foo.1
6507
+ RUN rm -f /foo-2010.1
6508
+ RUN rm -f /foo-2030.1
6509
+
6510
+ # Limit the timestamp upper bound to SOURCE_DATE_EPOCH.
6511
+ # Workaround for https://github.com/moby/buildkit/issues/3180
6512
+ ARG SOURCE_DATE_EPOCH
6513
+ RUN find $( ls / | grep -E -v "^(dev|mnt|proc|sys)$" ) -newermt "@${SOURCE_DATE_EPOCH}" -writable -xdev | xargs touch --date="@${SOURCE_DATE_EPOCH}" --no-dereference
6514
+
6515
+ # Squash the entire stage for resetting the whiteout timestamps.
6516
+ # Workaround for https://github.com/moby/buildkit/issues/3168
6517
+ FROM scratch
6518
+ COPY --from=0 / /
6519
+ ` )
6520
+
6521
+ const expectedDigest = "sha256:9e36395384d073e711102b13bd0ba4b779ef6afbaf5cadeb77fe77dba8967d1f"
6522
+
6523
+ dir , err := integration .Tmpdir (
6524
+ t ,
6525
+ fstest .CreateFile ("Dockerfile" , dockerfile , 0600 ),
6526
+ )
6527
+ require .NoError (t , err )
6528
+ defer os .RemoveAll (dir )
6529
+
6530
+ c , err := client .New (sb .Context (), sb .Address ())
6531
+ require .NoError (t , err )
6532
+ defer c .Close ()
6533
+
6534
+ outDigester := digest .SHA256 .Digester ()
6535
+ outW := & iohelper.NopWriteCloser {Writer : outDigester .Hash ()}
6536
+
6537
+ _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
6538
+ FrontendAttrs : map [string ]string {
6539
+ "build-arg:SOURCE_DATE_EPOCH" : fmt .Sprintf ("%d" , tm .Unix ()),
6540
+ "platform" : "linux/amd64" ,
6541
+ },
6542
+ LocalDirs : map [string ]string {
6543
+ builder .DefaultLocalNameDockerfile : dir ,
6544
+ builder .DefaultLocalNameContext : dir ,
6545
+ },
6546
+ Exports : []client.ExportEntry {
6547
+ {
6548
+ Type : client .ExporterOCI ,
6549
+ Attrs : map [string ]string {
6550
+ // Remove buildinfo, as it contains the digest of the frontend image
6551
+ "buildinfo" : "false" ,
6552
+ },
6553
+ Output : fixedWriteCloser (outW ),
6554
+ },
6555
+ },
6556
+ }, nil )
6557
+ require .NoError (t , err )
6558
+
6559
+ outDigest := outDigester .Digest ().String ()
6560
+ t .Logf ("OCI archive digest=%q" , outDigest )
6561
+ t .Log ("The digest may change depending on the BuildKit version, the snapshotter configuration, etc." )
6562
+ require .Equal (t , expectedDigest , outDigest )
6563
+ }
6564
+
6473
6565
func runShell (dir string , cmds ... string ) error {
6474
6566
for _ , args := range cmds {
6475
6567
var cmd * exec.Cmd
0 commit comments