Skip to content

Commit e157bb6

Browse files
authored
fix: Skip platform-specific digest resolution with --pull-policy never (#2498)
* fix: Skip platform-specific digest resolution with --pull-policy never When using --pull-policy never, pack now skips the platform-specific digest resolution that requires network access to fetch the manifest list. Instead, it uses the image name directly from the daemon. This fix addresses issue #2496 where builds fail when using --pull-policy never because pack cannot resolve the platform-specific digest of the lifecycle image without network access. The trade-off is that users may encounter containerd storage issues if Docker is configured to use containerd storage. In such cases, users should manually pull the platform-specific digest or use a different pull policy. Related to PR #2467 which introduced platform-specific digest resolution to fix containerd storage issues. Fixes #2496 Signed-off-by: Juan Bustamante <[email protected]> * test: Use daemon OS instead of runtime OS in PullNever test This fixes test failures on Windows runners running Linux containers. The test was using runtime.GOOS which returns 'windows' on Windows hosts, but the Docker daemon may be running Linux containers. Now we use the daemon's actual OS type queried via docker.Info(). Signed-off-by: Juan Bustamante <[email protected]> --------- Signed-off-by: Juan Bustamante <[email protected]>
1 parent 3a89ee8 commit e157bb6

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

pkg/image/fetcher.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ func (f *Fetcher) FetchForPlatform(ctx context.Context, name string, options Fet
257257
return nil, err
258258
}
259259

260+
platformStr := options.Target.ValuesAsPlatform()
261+
262+
// When PullPolicy is PullNever, skip platform-specific digest resolution as it requires
263+
// network access to fetch the manifest list. Instead, use the image as-is from the daemon.
264+
// Note: This may cause issues with containerd storage. Users should pre-pull the platform-specific
265+
// digest if they encounter errors.
266+
if options.Daemon && options.PullPolicy == PullNever {
267+
f.logger.Debugf("Using lifecycle %s with platform %s (skipping digest resolution due to --pull-policy never)", name, platformStr)
268+
return f.Fetch(ctx, name, options)
269+
}
270+
260271
// Build platform and registry settings from options
261272
platform := imgutil.Platform{
262273
OS: options.Target.OS,
@@ -275,7 +286,6 @@ func (f *Fetcher) FetchForPlatform(ctx context.Context, name string, options Fet
275286
}
276287

277288
// Log the resolution for visibility
278-
platformStr := options.Target.ValuesAsPlatform()
279289
f.logger.Debugf("Using lifecycle %s; pulling digest %s for platform %s", name, resolvedName, platformStr)
280290

281291
return f.Fetch(ctx, resolvedName, options)

pkg/image/fetcher_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,49 @@ func testFetcher(t *testing.T, when spec.G, it spec.S) {
732732
h.AssertError(t, err, "")
733733
})
734734
})
735+
736+
when("pull policy is PullNever with daemon", func() {
737+
var localImageName string
738+
739+
it.Before(func() {
740+
// Use a different name for the local image to avoid conflicts
741+
localImageName = "pack.local/test-" + h.RandString(10)
742+
743+
// Create a local daemon image with platform information
744+
// Use osType (daemon OS) instead of runtime.GOOS to handle cases where
745+
// Windows runner is running Linux containers
746+
img, err := local.NewImage(localImageName, docker, local.WithDefaultPlatform(imgutil.Platform{
747+
OS: osType,
748+
Architecture: runtime.GOARCH,
749+
}))
750+
h.AssertNil(t, err)
751+
h.AssertNil(t, img.Save())
752+
})
753+
754+
it.After(func() {
755+
h.DockerRmi(docker, localImageName)
756+
})
757+
758+
it("skips platform-specific digest resolution and uses tag directly", func() {
759+
target := dist.Target{
760+
OS: osType,
761+
Arch: runtime.GOARCH,
762+
}
763+
764+
fetchedImg, err := imageFetcher.FetchForPlatform(context.TODO(), localImageName, image.FetchOptions{
765+
Daemon: true,
766+
PullPolicy: image.PullNever,
767+
Target: &target,
768+
})
769+
770+
// Should succeed without network access (digest resolution skipped)
771+
h.AssertNil(t, err)
772+
h.AssertNotNil(t, fetchedImg)
773+
774+
// Verify debug message about skipping digest resolution
775+
h.AssertContains(t, outBuf.String(), "skipping digest resolution due to --pull-policy never")
776+
})
777+
})
735778
})
736779

737780
when("#CheckReadAccess", func() {

0 commit comments

Comments
 (0)