diff --git a/scripts/nl-stats-publish.sh b/scripts/nl-stats-publish.sh index fdf441f..fa16963 100644 --- a/scripts/nl-stats-publish.sh +++ b/scripts/nl-stats-publish.sh @@ -169,7 +169,12 @@ $DOCKER run --rm -e REPO_URL="$REPO_URL" -e BRANCH="$BRANCH" -e DEPLOY="$DEPLOY" # so copy it to a private path rather than loosening the file on the host. install -m 600 /tangled_key /root/tangled_key export GIT_SSH_COMMAND="ssh -i /root/tangled_key -o IdentitiesOnly=yes -o User=git -o StrictHostKeyChecking=accept-new" - git clone --quiet --branch "$BRANCH" "$REPO_URL" /site + # Clone from Tangled (the home base and single source of truth), NOT the Codeberg source + # mirror. Cloning the mirror caused a two-way divergence deadlock: the mirror gained stats + # commits while Tangled gained feature commits, so neither push fast-forwarded and every + # deploy silently froze. Basing the stats commit on Tangled HEAD makes the deploy push a + # guaranteed fast-forward. + git clone --quiet --branch "$BRANCH" "$TANGLED_URL" /site cd /site cp /data/nl-stats.json src/data/nl-stats.json cp /data/europe-stats.json src/data/europe-stats.json @@ -182,29 +187,30 @@ $DOCKER run --rm -e REPO_URL="$REPO_URL" -e BRANCH="$BRANCH" -e DEPLOY="$DEPLOY" if ! git diff --quiet -- src/data/nl-stats.json src/data/europe-stats.json src/data/europe-facts.json src/data/be-facts.json src/data/no-facts.json; then git add src/data/nl-stats.json src/data/europe-stats.json src/data/europe-facts.json src/data/be-facts.json src/data/no-facts.json git commit -q -m "chore(stats): refresh nl-stats.json + europe-stats.json + europe-facts.json" - git push -q origin "$BRANCH" - echo "[nl-stats] committed refreshed stats to $BRANCH (codeberg)" + echo "[nl-stats] committed refreshed stats to $BRANCH" else echo "[nl-stats] stats unchanged" fi - # Tangled is the home base and must not fall behind Codeberg. Non-fatal: a - # deploy is still worth doing if only the mirror push fails, but it says so - # loudly rather than drifting in silence. - git remote add tangled "$TANGLED_URL" 2>/dev/null || git remote set-url tangled "$TANGLED_URL" - if git push -q tangled "$BRANCH"; then - echo "[nl-stats] pushed $BRANCH to tangled (home base)" + # Push to Tangled (origin, since we cloned it). This is the deploy trigger: the Spindle CI + # (.tangled/workflows/deploy.yml) fires on push to main, builds every scope, and publishes each + # dist/ to its Codeberg Pages repo. Fast-forward by construction (this commit is based on + # Tangled HEAD), so it no longer deadlocks the way pushing the diverged mirror to Tangled did. + if git push -q origin "$BRANCH"; then + echo "[nl-stats] pushed $BRANCH to tangled (home base) -- Spindle will redeploy all scopes" else - echo "[nl-stats] WARNING: push to tangled FAILED - remotes are now out of sync" >&2 + echo "[nl-stats] WARNING: push to tangled FAILED" >&2 + fi + # Keep the Codeberg source mirror as a pure downstream copy of Tangled: FORCE it to match, + # never fast-forward-merge. The NAS bootstrap fetches this script and the python helpers from + # Codeberg raw main, so the mirror must track Tangled or the host runs stale code. Force (not a + # plain push) guarantees the mirror can never drift ahead again and re-create the deadlock; any + # stats commit it held is regenerated next run. Non-fatal. + git remote add codeberg "$REPO_URL" 2>/dev/null || git remote set-url codeberg "$REPO_URL" + if git push -qf codeberg "$BRANCH"; then + echo "[nl-stats] force-synced $BRANCH to the codeberg source mirror" + else + echo "[nl-stats] WARNING: codeberg source-mirror sync failed (non-fatal)" >&2 fi - # Deploy is handled by the Tangled Spindle CI (.tangled/workflows/deploy.yml), triggered by the - # tangled push above: it builds all seven scopes and publishes each to its Codeberg Pages repo. - # This job no longer deploys -- it used to loop deploy-codeberg.sh per scope, which duplicated - # the Spindle and could clobber it from a stale clone. Stats still reach the live sites because - # the stats commit + push retriggers the Spindle, which rebuilds with the fresh JSON. (This also - # retires the old "only .nl auto-deploys" trap: the per-scope loop needed a token with write to - # all seven Pages repos, but the .codeberg-token used here only has atprotonl-website, so .be/.eu/.no - # silently returned 403. Moot now -- the Spindle deploys with its own all-seven secret; the token is - # still used, but only to clone + push the source mirror above, which it can do.) else npm ci --silent npm run build