Skip to content

Commit 90254ef

Browse files
fix(ci): resolve nightly packages digest without image-specific skopeo ops
The Nightly workflow has never completed a run. Every scheduled run since NIGHTLY_ENABLED was set has failed in `mirror` at "Resolve source commit and version", ~80s in: level=fatal msg="unsupported image-specific operation on artifact with type \"application/vnd.cncf.flux.config.v1+json\"" cozystack-packages is a Flux OCI artifact, not a container image: its config mediaType is application/vnd.cncf.flux.config.v1+json. Plain `skopeo inspect` parses the config blob as an image config and fatals on any non-image artifact, so resolving the digest with `inspect --format '{{.Digest}}'` could never work. Fetch the :main manifest once with `inspect --raw` and derive both the digest (`skopeo manifest-digest`, which just hashes the manifest bytes — no image-specific parsing) and the revision annotation from those exact bytes. This also tightens the race the original comment describes: the digest and the annotation now come from a single fetch, so there is no window at all between pinning the tag and reading its revision, and one registry round-trip is saved. Because the workflow never ran past this step, the rest was unproven. Also fix both `flux pull artifact` calls, which passed an --output directory that does not exist and would have failed with "invalid output path": create it first, matching the established idiom in pull-requests.yaml ("Pull current-main packages tree"). Verified against the live OCIR artifact: the fixed step resolves packages_ref to the same digest the registry reports and yields main's current HEAD sha; the fixed pull extracts the tree. skopeo copy on Flux artifacts, the flux push digest awk parse, the cozy-installer chart name and nightly-mirror.sh's per-image digest verification were each checked and are correct as-is. Signed-off-by: Myasnikov Daniil <[email protected]>
1 parent 4a00b50 commit 90254ef

1 file changed

Lines changed: 25 additions & 8 deletions

File tree

‎.github/workflows/nightly.yaml‎

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,22 @@ jobs:
8383
id: resolve
8484
run: |
8585
set -eu
86-
# Pin :main to its current digest first, then read the revision
87-
# annotation and pull the baked tree from that SAME digest below, so a
88-
# concurrent build-main push of :main cannot make us check out commit A
89-
# while mirroring tree B.
90-
packages_ref="$(skopeo inspect --format '{{.Digest}}' "docker://${SRC_REGISTRY}/cozystack-packages:main")"
91-
rev="$(skopeo inspect --raw "docker://${SRC_REGISTRY}/cozystack-packages@${packages_ref}" \
92-
| yq -r '.annotations["org.opencontainers.image.revision"] // ""' -p json 2>/dev/null || true)"
86+
# Fetch the :main manifest ONCE and derive BOTH its digest and the
87+
# revision annotation from those exact bytes, then pull the baked tree
88+
# from that SAME digest below, so a concurrent build-main push of :main
89+
# cannot make us check out commit A while mirroring tree B.
90+
#
91+
# --raw is mandatory here: cozystack-packages is a Flux OCI artifact
92+
# (config mediaType application/vnd.cncf.flux.config.v1+json), not a
93+
# container image, so a plain `skopeo inspect` attempts an
94+
# image-specific operation and fatals on it. `manifest-digest` hashes
95+
# the manifest bytes, which is exactly what the registry addresses it
96+
# by — no image-specific parsing involved.
97+
manifest="${RUNNER_TEMP}/cozystack-packages-main.json"
98+
skopeo inspect --raw "docker://${SRC_REGISTRY}/cozystack-packages:main" > "$manifest"
99+
packages_ref="$(skopeo manifest-digest "$manifest")"
100+
rev="$(yq -r '.annotations["org.opencontainers.image.revision"] // ""' -p json "$manifest" 2>/dev/null || true)"
101+
rm -f "$manifest"
93102
# revision is "<git-describe>:<sha>"; take the sha.
94103
sha="${rev##*:}"
95104
# The sha flows into `actions/checkout` ref: — validate it is a bare
@@ -118,7 +127,12 @@ jobs:
118127
# Pull the digest-vendored tree build-main baked (but never committed).
119128
# Pinned to the digest resolved above, not the mutable :main tag.
120129
- name: Pull baked package tree
121-
run: flux pull artifact "oci://${SRC_REGISTRY}/cozystack-packages@${{ steps.resolve.outputs.packages_ref }}" --output _baked
130+
run: |
131+
set -eu
132+
# `flux pull artifact` rejects an --output path that does not already
133+
# exist ("invalid output path"), so create it first.
134+
rm -rf _baked && mkdir -p _baked
135+
flux pull artifact "oci://${SRC_REGISTRY}/cozystack-packages@${{ steps.resolve.outputs.packages_ref }}" --output _baked
122136
123137
# Copy every cozystack-owned component image OCIR -> GHCR by digest and
124138
# rewrite the baked tree's image hosts to GHCR (digests untouched).
@@ -239,6 +253,9 @@ jobs:
239253
PACKAGES_DIGEST: ${{ needs.mirror.outputs.packages_digest }}
240254
run: |
241255
set -eu
256+
# `flux pull artifact` rejects an --output path that does not already
257+
# exist ("invalid output path"), so create it first.
258+
rm -rf _rw && mkdir -p _rw
242259
flux pull artifact "oci://${DST_REGISTRY}/cozystack-packages:${VERSION}" --output _rw
243260
cp -r _rw/. packages/
244261
yq -i ".cozystackOperator.platformSourceUrl = \"oci://${DST_REGISTRY}/cozystack-packages\"" packages/core/installer/values.yaml

0 commit comments

Comments
 (0)