Skip to content

Commit bbbb69e

Browse files
authored
Re-derive git_commit_hash in manifest action to stop trailing-dash tags (#370)
## Summary Fixes the `<tag>-` (literal trailing dash, no commit hash) pollution on Docker Hub — e.g. `ethpandaops/teku:glamsterdam-devnet-0-` pushed at 2026-04-29T13:53:54Z. The shared manifest action concatenates `${target_tag}-${inputs.git_commit_hash}` with no validation. When the upstream `deploy` job's matrix output isn't readable — most commonly when someone uses **"Re-run failed jobs"** on the manifest job alone, since GitHub Actions [drops `needs.<job>.outputs.*` on re-runs](https://github.com/orgs/community/discussions/27905) — the input is empty and the action silently pushes a literal `<tag>-` manifest. The base `<tag>` is repointed to the same digest (so its `last_updated` doesn't move), which is exactly the fingerprint we saw on Docker Hub. This is a structural bug in the shared action, so the fix lands once in `.github/actions/manifest/action.yml` and covers every client (`teku`, `besu`, `geth`, `lighthouse`, `lodestar`, `nethermind`, `nimbus-eth2`, `prysm`, `reth`, `grandine`, `ethrex`, …). ## Changes - New `Resolve git commit hash` step in `manifest/action.yml`: - If `inputs.git_commit_hash` is non-empty → use it (current behaviour). - If empty → re-derive via `git ls-remote https://github.com/<source_repository>.git <source_ref>` and fall back to treating the ref as a SHA if `ls-remote` returns nothing. - If still empty → **fail the step** instead of pushing a trailing-dash tag. - All 5 references to `${{ inputs.git_commit_hash }}` in the action body now read `${{ steps.resolve_hash.outputs.git_commit_hash }}`. - `git_commit_hash` input flipped from `required: true` → `required: false` since callers no longer need to supply it for correct behaviour; description updated. ## Test plan - [ ] Trigger a normal `build-push-teku.yml` run and confirm both `<tag>` and `<tag>-<commit>` manifests are pushed (no behaviour change on the happy path). - [ ] Verify on a workflow that exercises Harbor (`HARBOR_REGISTRY` set) that the harbor manifest also gets the resolved commit hash. - [ ] Force the empty-input path by triggering "Re-run failed jobs" on a manifest job whose deploy succeeded in the prior run; confirm the action re-derives the hash and pushes `<tag>-<commit>` (not `<tag>-`). - [ ] Force a failure: pass an invalid `source_ref` with an empty `git_commit_hash`; confirm the step exits with `::error::Could not resolve git_commit_hash...` instead of pushing a trailing-dash tag. - [ ] Manually delete the existing `ethpandaops/teku:glamsterdam-devnet-0-` tag on Docker Hub once this lands.
1 parent f68bd44 commit bbbb69e

1 file changed

Lines changed: 31 additions & 7 deletions

File tree

.github/actions/manifest/action.yml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ inputs:
1616
type: string
1717
required: true
1818
git_commit_hash:
19-
description: The git commit hash that was used in the deploy action
19+
description: The git commit hash that was used in the deploy action. If empty (e.g. on a manifest-only "Re-run failed jobs"), it is re-derived from source_repository@source_ref.
2020
type: string
21-
required: true
21+
required: false
2222
target_tag:
2323
description: Docker hub tag to push to
2424
type: string
@@ -45,6 +45,30 @@ runs:
4545
steps:
4646
- name: Checkout this repo
4747
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
48+
- name: Resolve git commit hash
49+
id: resolve_hash
50+
shell: bash
51+
env:
52+
INPUT_HASH: ${{ inputs.git_commit_hash }}
53+
SOURCE_REPOSITORY: ${{ inputs.source_repository }}
54+
SOURCE_REF: ${{ inputs.source_ref }}
55+
run: |
56+
hash="$INPUT_HASH"
57+
if [ -z "$hash" ]; then
58+
# "Re-run failed jobs" drops needs.<job>.outputs.*; re-derive so we never push a "<tag>-" trailing-dash manifest.
59+
echo "git_commit_hash input was empty; re-deriving from ${SOURCE_REPOSITORY}@${SOURCE_REF}"
60+
url="https://github.com/${SOURCE_REPOSITORY}.git"
61+
hash=$(git ls-remote "$url" "$SOURCE_REF" 2>/dev/null | head -n1 | awk '{print $1}' | cut -c1-7)
62+
if [ -z "$hash" ] && [[ "$SOURCE_REF" =~ ^[0-9a-fA-F]{7,40}$ ]]; then
63+
hash=$(echo "$SOURCE_REF" | cut -c1-7)
64+
fi
65+
fi
66+
if [ -z "$hash" ]; then
67+
echo "::error::Could not resolve git_commit_hash from input or by re-deriving from ${SOURCE_REPOSITORY}@${SOURCE_REF}; refusing to push trailing-dash tag"
68+
exit 1
69+
fi
70+
echo "git_commit_hash=$hash" >> "$GITHUB_OUTPUT"
71+
echo "Resolved git_commit_hash: $hash"
4872
- name: Generate images list
4973
id: generate_images_list
5074
shell: bash
@@ -67,11 +91,11 @@ runs:
6791
exists=$(echo "$response" | jq -e '.results | length > 0') || exists="false"
6892
if [ "$exists" == "true" ]; then
6993
IMAGES+="${{ inputs.target_repository }}:${{ inputs.target_tag }}-$slug "
70-
TAGS+="${{ inputs.target_repository }}:${{ inputs.target_tag }}-$slug ${{ inputs.target_repository }}:${{ inputs.target_tag }}-$slug-${{ inputs.git_commit_hash }} "
94+
TAGS+="${{ inputs.target_repository }}:${{ inputs.target_tag }}-$slug ${{ inputs.target_repository }}:${{ inputs.target_tag }}-$slug-${{ steps.resolve_hash.outputs.git_commit_hash }} "
7195
fi
7296
done
7397
74-
TAGS+="${{ inputs.target_repository }}:${{ inputs.target_tag }} ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ inputs.git_commit_hash }} "
98+
TAGS+="${{ inputs.target_repository }}:${{ inputs.target_tag }} ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ steps.resolve_hash.outputs.git_commit_hash }} "
7599
76100
IMAGES=${IMAGES::-1} # Remove the trailing space
77101
echo "IMAGES: $IMAGES"
@@ -111,8 +135,8 @@ runs:
111135
- name: Create and push manifest images to dockerhub
112136
shell: bash
113137
run: |
114-
docker buildx imagetools create --dry-run -t ${{ inputs.target_repository }}:${{ inputs.target_tag }} -t ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ inputs.git_commit_hash }} ${{ steps.generate_images_list.outputs.images }}
115-
docker buildx imagetools create -t ${{ inputs.target_repository }}:${{ inputs.target_tag }} -t ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ inputs.git_commit_hash }} ${{ steps.generate_images_list.outputs.images }}
138+
docker buildx imagetools create --dry-run -t ${{ inputs.target_repository }}:${{ inputs.target_tag }} -t ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ steps.resolve_hash.outputs.git_commit_hash }} ${{ steps.generate_images_list.outputs.images }}
139+
docker buildx imagetools create -t ${{ inputs.target_repository }}:${{ inputs.target_tag }} -t ${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ steps.resolve_hash.outputs.git_commit_hash }} ${{ steps.generate_images_list.outputs.images }}
116140
- name: Create and push manifest images to harbor (best-effort)
117141
if: ${{ inputs.harbor_registry != '' && steps.harbor_login.outcome == 'success' }}
118142
continue-on-error: true
@@ -121,5 +145,5 @@ runs:
121145
echo "Pushing manifest to harbor registry (best-effort)..."
122146
docker buildx imagetools create \
123147
-t ${{ inputs.harbor_registry }}/${{ inputs.target_repository }}:${{ inputs.target_tag }} \
124-
-t ${{ inputs.harbor_registry }}/${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ inputs.git_commit_hash }} \
148+
-t ${{ inputs.harbor_registry }}/${{ inputs.target_repository }}:${{ inputs.target_tag }}-${{ steps.resolve_hash.outputs.git_commit_hash }} \
125149
${{ steps.generate_images_list.outputs.images }} || echo "Harbor manifest push failed, continuing..."

0 commit comments

Comments
 (0)