|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Assert that every image reference the chart renders at its own defaults is |
| 3 | +# actually pullable from the registry. |
| 4 | +# |
| 5 | +# Regression guard for #113: release-please used to write a bare version into |
| 6 | +# values.yaml `image.tag` while the release workflow only publishes v-prefixed |
| 7 | +# tags, so `helm install` at the chart's own defaults produced ImagePullBackOff. |
| 8 | +# |
| 9 | +# Uses the anonymous registry token + manifest HEAD, so it needs no credentials |
| 10 | +# for public images. |
| 11 | +set -euo pipefail |
| 12 | + |
| 13 | +CHART_DIR="${CHART_DIR:-charts/hermes-operator}" |
| 14 | +APP_VERSION="$(sed -nE 's/^appVersion:[[:space:]]*"?([^"[:space:]]+)"?/\1/p' "${CHART_DIR}/Chart.yaml")" |
| 15 | + |
| 16 | +fail=0 |
| 17 | + |
| 18 | +# Resolve a ghcr.io reference to a manifest, following the OCI auth dance. |
| 19 | +check_ref() { |
| 20 | + local ref="$1" |
| 21 | + local repo tag host path token code |
| 22 | + |
| 23 | + host="${ref%%/*}" |
| 24 | + path="${ref#*/}" |
| 25 | + repo="${path%:*}" |
| 26 | + tag="${path##*:}" |
| 27 | + |
| 28 | + if [[ "$host" != "ghcr.io" ]]; then |
| 29 | + echo " SKIP $ref (only ghcr.io is checked)" |
| 30 | + return 0 |
| 31 | + fi |
| 32 | + |
| 33 | + # The operator image is only ever published v-prefixed. A bare semver here is |
| 34 | + # the #113 regression: it renders an unpullable reference. Catch it by shape, |
| 35 | + # so it fails even before the tag would have had a chance to exist. |
| 36 | + if [[ "$repo" == "paperclipinc/hermes-operator" && "$tag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then |
| 37 | + echo " FAIL $ref (bare version tag; the release workflow publishes v${tag})" |
| 38 | + fail=1 |
| 39 | + return 0 |
| 40 | + fi |
| 41 | + |
| 42 | + # The operator image is published by the release workflow, which runs *after* |
| 43 | + # release-please bumps appVersion. On a release PR (and on main until the |
| 44 | + # release job finishes) the chart legitimately renders a tag that does not |
| 45 | + # exist yet. Exempt exactly that case from the existence check, but still |
| 46 | + # enforce the v-prefix format that #113 was about. |
| 47 | + if [[ "$repo" == "paperclipinc/hermes-operator" && "$tag" == "v${APP_VERSION}" ]]; then |
| 48 | + if ! git rev-parse -q --verify "refs/tags/v${APP_VERSION}" >/dev/null 2>&1; then |
| 49 | + echo " SKIP $ref (v${APP_VERSION} is the pending release; format is correct)" |
| 50 | + return 0 |
| 51 | + fi |
| 52 | + fi |
| 53 | + |
| 54 | + token=$(curl -fsSL "https://ghcr.io/token?scope=repository:${repo}:pull&service=ghcr.io" \ |
| 55 | + | python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])') |
| 56 | + |
| 57 | + code=$(curl -s -o /dev/null -w '%{http_code}' -I \ |
| 58 | + -H "Authorization: Bearer ${token}" \ |
| 59 | + -H 'Accept: application/vnd.oci.image.index.v1+json' \ |
| 60 | + -H 'Accept: application/vnd.oci.image.manifest.v1+json' \ |
| 61 | + -H 'Accept: application/vnd.docker.distribution.manifest.list.v2+json' \ |
| 62 | + -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \ |
| 63 | + "https://ghcr.io/v2/${repo}/manifests/${tag}") |
| 64 | + |
| 65 | + if [[ "$code" == "200" ]]; then |
| 66 | + echo " OK $ref" |
| 67 | + else |
| 68 | + echo " FAIL $ref (HTTP $code — tag does not resolve)" |
| 69 | + fail=1 |
| 70 | + fi |
| 71 | +} |
| 72 | + |
| 73 | +echo "Rendering ${CHART_DIR} at its defaults..." |
| 74 | +refs=$(helm template hermes-operator "${CHART_DIR}" \ |
| 75 | + | grep -oE 'image: "?[a-z0-9./-]+:[A-Za-z0-9._-]+"?' \ |
| 76 | + | sed -E 's/^image: "?//; s/"?$//' \ |
| 77 | + | sort -u) |
| 78 | + |
| 79 | +if [[ -z "$refs" ]]; then |
| 80 | + echo "ERROR: no image references found in rendered chart — check the grep." >&2 |
| 81 | + exit 1 |
| 82 | +fi |
| 83 | + |
| 84 | +echo "Checking rendered image references:" |
| 85 | +while IFS= read -r ref; do |
| 86 | + [[ -n "$ref" ]] && check_ref "$ref" |
| 87 | +done <<<"$refs" |
| 88 | + |
| 89 | +if [[ "$fail" -ne 0 ]]; then |
| 90 | + echo |
| 91 | + echo "One or more chart default image tags are unpullable." >&2 |
| 92 | + echo "The release workflow publishes v-prefixed tags (v<version>), so the" >&2 |
| 93 | + echo "chart must render those — see hack/check-chart-image-tags.sh header." >&2 |
| 94 | + exit 1 |
| 95 | +fi |
| 96 | + |
| 97 | +echo "All chart default image tags resolve." |
0 commit comments