#!/usr/bin/env bash # check-base-hash.sh — guard the base-rebuild invariant. # # Every floating `ARG *_REF` consumed by Dockerfile.base MUST be folded # into the base_tag hash in the docker-publish workflow. Otherwise a # ref-only change to that dependency does not change the base hash, the # Docker Hub probe finds the old base tag, and the base is NOT rebuilt — # the dependency fix silently fails to land. This is the v1.1.2-class # staleness footgun (then it was mempalace-toolkit; this guard stops the # next one before it ships). # # Runs in CI (base-decide job) and locally: bash scripts/check-base-hash.sh set -euo pipefail cd "$(dirname "$0")/.." WF=".gitea/workflows/docker-publish-split.yml" DF="Dockerfile.base" # Extract the hash-compute block: the `HASH=$( … ) | sha256sum | cut` # brace-group in the "Compute base tag" step. This lives in a separate # file from the workflow, so scanning $WF here is free of the self-match # hazard an inline workflow step would have. block=$(awk '/HASH=\$\(/{f=1} f{print} f && /cut -c1-12/{exit}' "$WF") if [ -z "$block" ]; then echo "::error::could not locate the HASH=\$( … ) | sha256sum block in $WF" exit 1 fi refs=$(grep -oE '^ARG [A-Z0-9_]+_REF' "$DF" | awk '{print $2}' | sort -u) fail=0 for r in $refs; do lc=$(printf '%s' "$r" | tr '[:upper:]' '[:lower:]') if ! printf '%s' "$block" | grep -q "outputs.$lc"; then echo "::error::Dockerfile.base declares '$r' but it is NOT folded into the base_tag hash in $WF." echo "::error::Add echo \"\${{ needs.resolve-versions.outputs.$lc }}\" inside the HASH=\$( … ) | sha256sum block, or a $r-only change will silently fail to rebuild the base." fail=1 fi done if [ "$fail" = 0 ]; then echo "OK: all Dockerfile.base *_REF args are folded into base_tag (${refs:-none})." fi exit $fail