From b8a2d8f6a592fc0988b153241505fce950f4c447 Mon Sep 17 00:00:00 2001 From: Richard Clark Date: Sat, 24 Oct 2026 19:32:01 +0100 Subject: [PATCH] Fetch cached OCI charts without contacting the registry A Helm chart's OCI layer is the chart .tgz, so when `sha256` is set its blob is `blobs/sha256:`. Try that blob first without a token, so a chart in the repository cache needs no token, manifest or blob request. On a miss, fall back to the token, manifest and blob requests as before. CI fetched every OCI test chart from its registry on each job, and the concurrent anonymous requests tripped ECR's rate limit (429). Also fail with the "is not a Helm chart package" message, rather than a key error, for a manifest without a `config` field. --- helm/private/import.bzl | 116 +++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/helm/private/import.bzl b/helm/private/import.bzl index 4eb1b42..5da03ea 100644 --- a/helm/private/import.bzl +++ b/helm/private/import.bzl @@ -130,55 +130,71 @@ def _helm_import_repository_impl(repository_ctx): url, _, chart_version = chart_url.rpartition(":") hostname, _, chart_path = url.removeprefix("oci://").partition("/") - au = authn.new(repository_ctx) - token = au.get_token(hostname, chart_path) - - # Find the digest for the layer with the chart package in the image manifest: - manifest_json = "manifest.json" - manifest_url = "https://{}/v2/{}/manifests/{}".format( - hostname, - chart_path, - chart_version, - ) - repository_ctx.download( - output = manifest_json, - url = manifest_url, - auth = { - manifest_url: token, - }, - # Copied from `helm pull --debug` - headers = { - "Accept": [ - "application/vnd.docker.distribution.manifest.v2+json", - "application/vnd.docker.distribution.manifest.list.v2+json", - "application/vnd.oci.image.manifest.v1+json", - "application/vnd.oci.image.index.v1+json", - "*/*", - ], - }, - ) - manifest = json.decode(repository_ctx.read(manifest_json)) - - # https://helm.sh/docs/topics/registries/#helm-chart-manifest - if manifest["config"]["mediaType"] != "application/vnd.cncf.helm.config.v1+json": - fail("{} is not a Helm chart package".format(chart_url)) - - chart_digest = _find_chart_digest(manifest) - chart_blob_url = "https://{}/v2/{}/blobs/{}".format( - hostname, - chart_path, - chart_digest, - ) - - # Download the chart package: - result = repository_ctx.download( - output = repository_ctx.path(chart_file), - url = chart_blob_url, - sha256 = repository_ctx.attr.sha256, - auth = { - chart_blob_url: token, - }, - ) + # A Helm chart's OCI layer is the chart .tgz, so `sha256` names its + # blob, and a cached blob needs neither a token nor the manifest. + result = None + if repository_ctx.attr.sha256: + result = repository_ctx.download( + output = repository_ctx.path(chart_file), + url = "https://{}/v2/{}/blobs/sha256:{}".format( + hostname, + chart_path, + repository_ctx.attr.sha256, + ), + sha256 = repository_ctx.attr.sha256, + allow_fail = True, + ) + + if not result or not result.success: + au = authn.new(repository_ctx) + token = au.get_token(hostname, chart_path) + + # Find the digest for the layer with the chart package in the image manifest: + manifest_json = "manifest.json" + manifest_url = "https://{}/v2/{}/manifests/{}".format( + hostname, + chart_path, + chart_version, + ) + repository_ctx.download( + output = manifest_json, + url = manifest_url, + auth = { + manifest_url: token, + }, + # Copied from `helm pull --debug` + headers = { + "Accept": [ + "application/vnd.docker.distribution.manifest.v2+json", + "application/vnd.docker.distribution.manifest.list.v2+json", + "application/vnd.oci.image.manifest.v1+json", + "application/vnd.oci.image.index.v1+json", + "*/*", + ], + }, + ) + manifest = json.decode(repository_ctx.read(manifest_json)) + + # https://helm.sh/docs/topics/registries/#helm-chart-manifest + if manifest.get("config", {}).get("mediaType") != "application/vnd.cncf.helm.config.v1+json": + fail("{} is not a Helm chart package".format(chart_url)) + + chart_digest = _find_chart_digest(manifest) + chart_blob_url = "https://{}/v2/{}/blobs/{}".format( + hostname, + chart_path, + chart_digest, + ) + + # Download the chart package: + result = repository_ctx.download( + output = repository_ctx.path(chart_file), + url = chart_blob_url, + sha256 = repository_ctx.attr.sha256, + auth = { + chart_blob_url: token, + }, + ) else: fail("cannot download {} from {}, unsupported scheme".format(repository_ctx.attr.chart_name, chart_url)) @@ -227,7 +243,7 @@ helm_import_repository = repository_rule( doc = "Chart repository url where to locate the requested chart. Mutually exclusive with `url`.", ), "sha256": attr.string( - doc = "The expected SHA-256 hash of the chart imported.", + doc = "The expected SHA-256 hash of the chart imported. For an `oci://` url, a chart already in the repository cache is then fetched without any request to the registry.", ), "url": attr.string( doc = "The url where a chart can be directly downloaded. Mutually exclusive with `chart_name`, `repository`, and `version`",