diff --git a/go.mod b/go.mod index be8f9392a..85bc15f43 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/buildpacks/pack v0.36.0 github.com/chainguard-dev/git-urls v1.0.2 github.com/cloudevents/sdk-go/v2 v2.15.2 + github.com/containerd/errdefs v0.3.0 github.com/containerd/platforms v0.2.1 github.com/containers/image/v5 v5.31.1 github.com/coreos/go-semver v0.3.1 @@ -119,7 +120,6 @@ require ( github.com/cloudevents/sdk-go/sql/v2 v2.15.2 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/errdefs v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/typeurl/v2 v2.2.0 // indirect diff --git a/hack/update-builder.go b/hack/update-builder.go index b5129da1d..259e87c21 100644 --- a/hack/update-builder.go +++ b/hack/update-builder.go @@ -26,6 +26,7 @@ import ( pack "github.com/buildpacks/pack/pkg/client" "github.com/buildpacks/pack/pkg/dist" bpimage "github.com/buildpacks/pack/pkg/image" + "github.com/containerd/errdefs" "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/registry" docker "github.com/docker/docker/client" @@ -108,7 +109,7 @@ func buildBuilderImage(ctx context.Context, variant, arch string) (string, error if err != nil { return "", fmt.Errorf("cannot parse reference to builder target: %w", err) } - desc, err := remote.Head(ref, remote.WithAuthFromKeychain(DefaultKeychain)) + desc, err := remote.Head(ref, remote.WithAuthFromKeychain(DefaultKeychain), remote.WithContext(ctx)) if err == nil { fmt.Fprintln(os.Stderr, "The image has been already built.") return newBuilderImage + "@" + desc.Digest.String(), nil @@ -131,7 +132,14 @@ func buildBuilderImage(ctx context.Context, variant, arch string) (string, error } addGoAndRustBuildpacks(&builderConfig) - packClient, err := pack.NewClient(pack.WithKeychain(DefaultKeychain)) + var dockerClient docker.CommonAPIClient + dockerClient, err = docker.NewClientWithOpts(docker.FromEnv, docker.WithAPIVersionNegotiation()) + if err != nil { + return "", fmt.Errorf("cannot create docker client") + } + dockerClient = &hackDockerClient{dockerClient} + + packClient, err := pack.NewClient(pack.WithKeychain(DefaultKeychain), pack.WithDockerClient(dockerClient)) if err != nil { return "", fmt.Errorf("cannot create pack client: %w", err) } @@ -162,11 +170,6 @@ func buildBuilderImage(ctx context.Context, variant, arch string) (string, error return "", fmt.Errorf("canont create builder: %w", err) } - dockerClient, err := docker.NewClientWithOpts(docker.FromEnv, docker.WithAPIVersionNegotiation()) - if err != nil { - return "", fmt.Errorf("cannot create docker client") - } - pushImage := func(img string) (string, error) { regAuth, err := dockerDaemonAuthStr(img) if err != nil { @@ -261,6 +264,7 @@ func buildBuilderImageMultiArch(ctx context.Context, variant string) error { remoteOpts := []remote.Option{ remote.WithAuthFromKeychain(DefaultKeychain), + remote.WithContext(ctx), } idx := mutate.IndexMediaType(empty.Index, types.DockerManifestList) @@ -768,3 +772,17 @@ func dockerDaemonAuthStr(img string) (string, error) { return base64.StdEncoding.EncodeToString(bs), nil } + +// Hack implementation of docker client returns NotFound for images ghcr.io/knative/buildpacks/* +// For some reason moby/docker erroneously returns 500 HTTP code for these missing images. +// Interestingly podman correctly returns 404 for same request. +type hackDockerClient struct { + docker.CommonAPIClient +} + +func (c hackDockerClient) ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error) { + if strings.HasPrefix(ref, "ghcr.io/knative/buildpacks/") { + return nil, fmt.Errorf("this image is supposed to exist only in daemon: %w", errdefs.ErrNotFound) + } + return c.CommonAPIClient.ImagePull(ctx, ref, options) +}