Merge pull request 'Retry the Harbor manifest copy instead of a probe for it' (#3) from fix-harbor-tag-retry into main
build / build (push) Successful in 2m56s

Reviewed-on: #3
This commit was merged in pull request #3.
This commit is contained in:
2026-10-11 07:58:50 +00:00
3 changed files with 23 additions and 2 deletions
+11 -2
View File
@@ -66,14 +66,23 @@ jobs:
cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache,mode=max
# The primary tag is already pushed and deployable by the time this runs:
# the image policy selects `main-<timestamp>`, so a failure here costs the
# SHA audit tag, not the rollout.
- name: Wait for Harbor policy, then add SHA tag - name: Wait for Harbor policy, then add SHA tag
shell: bash
env: env:
PRIMARY: ${{ steps.tags.outputs.primary }} PRIMARY: ${{ steps.tags.outputs.primary }}
QUALIFIED: ${{ steps.tags.outputs.qualified }} QUALIFIED: ${{ steps.tags.outputs.qualified }}
run: | run: |
# Harbor's vulnerability policy blocks manifest reads while Trivy's scan
# is still Running, and `imagetools create` copies the manifest. Retry
# that copy itself rather than an `inspect` probe: a probe that passes is
# no guarantee the copy will, and under the default `bash -e` the first
# blocked copy aborted the step before its retries could run.
for attempt in $(seq 1 60); do for attempt in $(seq 1 60); do
if docker buildx imagetools inspect "$PRIMARY" >/dev/null 2>&1; then if docker buildx imagetools create --tag "$QUALIFIED" "$PRIMARY"; then
docker buildx imagetools create --tag "$QUALIFIED" "$PRIMARY" echo "tagged $QUALIFIED on attempt $attempt"
exit 0 exit 0
fi fi
echo "waiting for Harbor scan/pull policy ($attempt/60)" echo "waiting for Harbor scan/pull policy ($attempt/60)"
+6
View File
@@ -35,6 +35,12 @@ The image does not set `BTCDATA_URL`; deployments must provide it. `BUILD_SHA` i
runner, then publishes immutable linux/amd64 images to runner, then publishes immutable linux/amd64 images to
`harbor.pmagnus.cloud/btcprice/btcprice`. It embeds the short Git SHA as `APP_VERSION`. `harbor.pmagnus.cloud/btcprice/btcprice`. It embeds the short Git SHA as `APP_VERSION`.
The build pushes two tags: `main-<timestamp>`, then a companion `main-<timestamp>-<sha>` for
audit. Harbor's vulnerability policy blocks manifest reads while Trivy is still scanning, so
the companion tag is retried until the scan clears. Only the first tag matters for deployment —
the Flux image policy matches `^main-<14 digits>$` — so a failure in that last step costs the
audit tag and nothing else.
Flux image automation updates the manifests in the separate `magnus/deploy` repository and Flux Flux image automation updates the manifests in the separate `magnus/deploy` repository and Flux
reconciles k3s. CI has no Kubernetes credentials. Production runs two replicas—one on hostinger and reconciles k3s. CI has no Kubernetes credentials. Production runs two replicas—one on hostinger and
one on citadel—and is served at https://btcprice.k8s.pmagnus.cloud through ingress-nginx and one on citadel—and is served at https://btcprice.k8s.pmagnus.cloud through ingress-nginx and
+6
View File
@@ -35,6 +35,12 @@ The image does not set `BTCDATA_URL`; deployments must provide it. `BUILD_SHA` i
runner, then publishes immutable linux/amd64 images to runner, then publishes immutable linux/amd64 images to
`harbor.pmagnus.cloud/btcprice/btcprice`. It embeds the short Git SHA as `APP_VERSION`. `harbor.pmagnus.cloud/btcprice/btcprice`. It embeds the short Git SHA as `APP_VERSION`.
The build pushes two tags: `main-<timestamp>`, then a companion `main-<timestamp>-<sha>` for
audit. Harbor's vulnerability policy blocks manifest reads while Trivy is still scanning, so
the companion tag is retried until the scan clears. Only the first tag matters for deployment —
the Flux image policy matches `^main-<14 digits>$` — so a failure in that last step costs the
audit tag and nothing else.
Flux image automation updates the manifests in the separate `magnus/deploy` repository and Flux Flux image automation updates the manifests in the separate `magnus/deploy` repository and Flux
reconciles k3s. CI has no Kubernetes credentials. Production runs two replicas—one on hostinger and reconciles k3s. CI has no Kubernetes credentials. Production runs two replicas—one on hostinger and
one on citadel—and is served at https://btcprice.k8s.pmagnus.cloud through ingress-nginx and one on citadel—and is served at https://btcprice.k8s.pmagnus.cloud through ingress-nginx and