Skip to content

Commit c5efab5

Browse files
authored
chore: update kaniko fork to fix multi-stage cache probing (#325)
1 parent 8b9ec59 commit c5efab5

File tree

3 files changed

+158
-21
lines changed

3 files changed

+158
-21
lines changed

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22.4
44

55
// There are a few options we need added to Kaniko!
66
// See: https://github.com/GoogleContainerTools/kaniko/compare/main...coder:kaniko:main
7-
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240815135021-647365bde8a7
7+
replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko v0.0.0-20240830092517-0668f96c8816
88

99
// Required to import codersdk due to gvisor dependency.
1010
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20240702054557-aa558fbe5374
@@ -178,7 +178,6 @@ require (
178178
github.com/jmespath/go-jmespath v0.4.0 // indirect
179179
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect
180180
github.com/jsimonetti/rtnetlink v1.3.5 // indirect
181-
github.com/karrick/godirwalk v1.16.1 // indirect
182181
github.com/kevinburke/ssh_config v1.2.0 // indirect
183182
github.com/klauspost/compress v1.17.9 // indirect
184183
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
@@ -246,6 +245,7 @@ require (
246245
github.com/tailscale/wireguard-go v0.0.0-20231121184858-cc193a0b3272 // indirect
247246
github.com/tcnksm/go-httpstat v0.2.0 // indirect
248247
github.com/tinylib/msgp v1.1.8 // indirect
248+
github.com/twpayne/go-vfs/v5 v5.0.4 // indirect
249249
github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a // indirect
250250
github.com/valyala/fasthttp v1.55.0 // indirect
251251
github.com/vbatts/tar-split v0.11.5 // indirect

go.sum

+4-4
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
171171
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
172172
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352 h1:L/EjCuZxs5tOcqqCaASj/nu65TRYEFcTt8qRQfHZXX0=
173173
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352/go.mod h1:P1KoQSgnKEAG6Mnd3YlGzAophty+yKA9VV48LpfNRvo=
174-
github.com/coder/kaniko v0.0.0-20240815135021-647365bde8a7 h1:i5CTDhAUlZMXr4PdMz5RxTBiG0xltxj1npbEi1Ggzek=
175-
github.com/coder/kaniko v0.0.0-20240815135021-647365bde8a7/go.mod h1:xlfIeo8SYBw3zwKb73wzz4Q5Q1wtnJy8ofYqGDAl/NA=
174+
github.com/coder/kaniko v0.0.0-20240830092517-0668f96c8816 h1:idB8jAnkYWkHYddbJ+WnGtM2wrhh3+JpjPwHcQ2lYhU=
175+
github.com/coder/kaniko v0.0.0-20240830092517-0668f96c8816/go.mod h1:XoTDIhNF0Ll4tLmRYdOn31udU9w5zFrY2PME/crSRCA=
176176
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs=
177177
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0/go.mod h1:5UuS2Ts+nTToAMeOjNlnHFkPahrtDkmpydBen/3wgZc=
178178
github.com/coder/quartz v0.1.0 h1:cLL+0g5l7xTf6ordRnUMMiZtRE8Sq5LxpghS63vEXrQ=
@@ -489,8 +489,6 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
489489
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
490490
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
491491
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
492-
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
493-
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
494492
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
495493
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
496494
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
@@ -733,6 +731,8 @@ github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
733731
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
734732
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
735733
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
734+
github.com/twpayne/go-vfs/v5 v5.0.4 h1:/ne3h+rW7f5YOyOFguz+3ztfUwzOLR0Vts3y0mMAitg=
735+
github.com/twpayne/go-vfs/v5 v5.0.4/go.mod h1:zTPFJUbgsEMFNSWnWQlLq9wh4AN83edZzx3VXbxrS1w=
736736
github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a h1:BH1SOPEvehD2kVrndDnGJiUF0TrBpNs+iyYocu6h0og=
737737
github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
738738
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=

integration/integration_test.go

+152-15
Original file line numberDiff line numberDiff line change
@@ -1485,22 +1485,26 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
14851485
})
14861486

14871487
t.Run("CacheAndPushMultistage", func(t *testing.T) {
1488-
// Currently fails with:
1489-
// /home/coder/src/coder/envbuilder/integration/integration_test.go:1417: "error: unable to get cached image: error fake building stage: failed to optimize instructions: failed to get files used from context: failed to get fileinfo for /.envbuilder/0/root/date.txt: lstat /.envbuilder/0/root/date.txt: no such file or directory"
1490-
// /home/coder/src/coder/envbuilder/integration/integration_test.go:1156:
1491-
// Error Trace: /home/coder/src/coder/envbuilder/integration/integration_test.go:1156
1492-
// Error: Received unexpected error:
1493-
// error: unable to get cached image: error fake building stage: failed to optimize instructions: failed to get files used from context: failed to get fileinfo for /.envbuilder/0/root/date.txt: lstat /.envbuilder/0/root/date.txt: no such file or directory
1494-
// Test: TestPushImage/CacheAndPushMultistage
1495-
t.Skip("TODO: https://github.com/coder/envbuilder/issues/230")
14961488
t.Parallel()
14971489

14981490
srv := gittest.CreateGitServer(t, gittest.Options{
14991491
Files: map[string]string{
1500-
"Dockerfile": fmt.Sprintf(`FROM %s AS a
1501-
RUN date --utc > /root/date.txt
1502-
FROM %s as b
1503-
COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine),
1492+
"Dockerfile": fmt.Sprintf(`
1493+
FROM %[1]s AS prebuild
1494+
RUN mkdir /the-past /the-future \
1495+
&& echo "hello from the past" > /the-past/hello.txt \
1496+
&& cd /the-past \
1497+
&& ln -s hello.txt hello.link \
1498+
&& echo "hello from the future" > /the-future/hello.txt
1499+
1500+
FROM %[1]s
1501+
USER root
1502+
ARG WORKDIR=/
1503+
WORKDIR $WORKDIR
1504+
ENV FOO=bar
1505+
COPY --from=prebuild /the-past /the-past
1506+
COPY --from=prebuild /the-future/hello.txt /the-future/hello.txt
1507+
`, testImageAlpine),
15041508
},
15051509
})
15061510

@@ -1525,16 +1529,122 @@ COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine),
15251529
require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push")
15261530

15271531
// When: we run envbuilder with PUSH_IMAGE set
1532+
_, err = runEnvbuilder(t, runOpts{env: []string{
1533+
envbuilderEnv("GIT_URL", srv.URL),
1534+
envbuilderEnv("CACHE_REPO", testRepo),
1535+
envbuilderEnv("PUSH_IMAGE", "1"),
1536+
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
1537+
}})
1538+
require.NoError(t, err)
1539+
1540+
// Then: the image should be pushed
1541+
_, err = remote.Image(ref)
1542+
require.NoError(t, err, "expected image to be present after build + push")
1543+
1544+
// Then: re-running envbuilder with GET_CACHED_IMAGE should succeed
15281545
ctrID, err := runEnvbuilder(t, runOpts{env: []string{
1546+
envbuilderEnv("GIT_URL", srv.URL),
1547+
envbuilderEnv("CACHE_REPO", testRepo),
1548+
envbuilderEnv("GET_CACHED_IMAGE", "1"),
1549+
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
1550+
}})
1551+
require.NoError(t, err)
1552+
1553+
// Then: the cached image ref should be emitted in the container logs
1554+
ctx, cancel := context.WithCancel(context.Background())
1555+
t.Cleanup(cancel)
1556+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
1557+
require.NoError(t, err)
1558+
defer cli.Close()
1559+
logs, err := cli.ContainerLogs(ctx, ctrID, container.LogsOptions{
1560+
ShowStdout: true,
1561+
ShowStderr: true,
1562+
})
1563+
require.NoError(t, err)
1564+
defer logs.Close()
1565+
logBytes, err := io.ReadAll(logs)
1566+
require.NoError(t, err)
1567+
require.Regexp(t, `ENVBUILDER_CACHED_IMAGE=(\S+)`, string(logBytes))
1568+
1569+
// When: we pull the image we just built
1570+
rc, err := cli.ImagePull(ctx, ref.String(), image.PullOptions{})
1571+
require.NoError(t, err)
1572+
t.Cleanup(func() { _ = rc.Close() })
1573+
_, err = io.ReadAll(rc)
1574+
require.NoError(t, err)
1575+
1576+
// When: we run the image we just built
1577+
ctr, err := cli.ContainerCreate(ctx, &container.Config{
1578+
Image: ref.String(),
1579+
Entrypoint: []string{"sleep", "infinity"},
1580+
Labels: map[string]string{
1581+
testContainerLabel: "true",
1582+
},
1583+
}, nil, nil, nil, "")
1584+
require.NoError(t, err)
1585+
t.Cleanup(func() {
1586+
_ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{
1587+
RemoveVolumes: true,
1588+
Force: true,
1589+
})
1590+
})
1591+
err = cli.ContainerStart(ctx, ctr.ID, container.StartOptions{})
1592+
require.NoError(t, err)
1593+
1594+
// Then: The files from the prebuild stage are present.
1595+
out := execContainer(t, ctr.ID, "/bin/sh -c 'cat /the-past/hello.txt /the-future/hello.txt; readlink -f /the-past/hello.link'")
1596+
require.Equal(t, "hello from the past\nhello from the future\n/the-past/hello.txt", strings.TrimSpace(out))
1597+
})
1598+
1599+
t.Run("MultistgeCacheMissAfterChange", func(t *testing.T) {
1600+
t.Parallel()
1601+
dockerfilePrebuildContents := fmt.Sprintf(`
1602+
FROM %[1]s AS prebuild
1603+
RUN mkdir /the-past /the-future \
1604+
&& echo "hello from the past" > /the-past/hello.txt \
1605+
&& cd /the-past \
1606+
&& ln -s hello.txt hello.link \
1607+
&& echo "hello from the future" > /the-future/hello.txt
1608+
1609+
# Workaround for https://github.com/coder/envbuilder/issues/231
1610+
FROM %[1]s
1611+
`, testImageAlpine)
1612+
1613+
dockerfileContents := fmt.Sprintf(`
1614+
FROM %s
1615+
USER root
1616+
ARG WORKDIR=/
1617+
WORKDIR $WORKDIR
1618+
ENV FOO=bar
1619+
COPY --from=prebuild /the-past /the-past
1620+
COPY --from=prebuild /the-future/hello.txt /the-future/hello.txt
1621+
RUN echo $FOO > /root/foo.txt
1622+
RUN date --utc > /root/date.txt
1623+
`, testImageAlpine)
1624+
1625+
newServer := func(dockerfile string) *httptest.Server {
1626+
return gittest.CreateGitServer(t, gittest.Options{
1627+
Files: map[string]string{"Dockerfile": dockerfile},
1628+
})
1629+
}
1630+
srv := newServer(dockerfilePrebuildContents + dockerfileContents)
1631+
1632+
// Given: an empty registry
1633+
testReg := setupInMemoryRegistry(t, setupInMemoryRegistryOpts{})
1634+
testRepo := testReg + "/test"
1635+
ref, err := name.ParseReference(testRepo + ":latest")
1636+
require.NoError(t, err)
1637+
_, err = remote.Image(ref)
1638+
require.ErrorContains(t, err, "NAME_UNKNOWN", "expected image to not be present before build + push")
1639+
1640+
// When: we run envbuilder with PUSH_IMAGE set
1641+
_, err = runEnvbuilder(t, runOpts{env: []string{
15291642
envbuilderEnv("GIT_URL", srv.URL),
15301643
envbuilderEnv("CACHE_REPO", testRepo),
15311644
envbuilderEnv("PUSH_IMAGE", "1"),
15321645
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
15331646
}})
15341647
require.NoError(t, err)
1535-
// Then: The file copied from stage a should be present
1536-
out := execContainer(t, ctrID, "cat /date.txt")
1537-
require.NotEmpty(t, out)
15381648

15391649
// Then: the image should be pushed
15401650
_, err = remote.Image(ref)
@@ -1548,6 +1658,33 @@ COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine),
15481658
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
15491659
}})
15501660
require.NoError(t, err)
1661+
1662+
// When: we change the Dockerfile
1663+
srv.Close()
1664+
dockerfilePrebuildContents = strings.Replace(dockerfilePrebuildContents, "hello from the future", "hello from the future, but different", 1)
1665+
srv = newServer(dockerfilePrebuildContents)
1666+
1667+
// When: we rebuild the prebuild stage so that the cache is created
1668+
_, err = runEnvbuilder(t, runOpts{env: []string{
1669+
envbuilderEnv("GIT_URL", srv.URL),
1670+
envbuilderEnv("CACHE_REPO", testRepo),
1671+
envbuilderEnv("PUSH_IMAGE", "1"),
1672+
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
1673+
}})
1674+
require.NoError(t, err)
1675+
1676+
// Then: re-running envbuilder with GET_CACHED_IMAGE should still fail
1677+
// on the second stage because the first stage file has changed.
1678+
srv.Close()
1679+
srv = newServer(dockerfilePrebuildContents + dockerfileContents)
1680+
_, err = runEnvbuilder(t, runOpts{env: []string{
1681+
envbuilderEnv("GIT_URL", srv.URL),
1682+
envbuilderEnv("CACHE_REPO", testRepo),
1683+
envbuilderEnv("GET_CACHED_IMAGE", "1"),
1684+
envbuilderEnv("DOCKERFILE_PATH", "Dockerfile"),
1685+
envbuilderEnv("VERBOSE", "1"),
1686+
}})
1687+
require.ErrorContains(t, err, "error probing build cache: uncached COPY command")
15511688
})
15521689

15531690
t.Run("PushImageRequiresCache", func(t *testing.T) {

0 commit comments

Comments
 (0)