Commitec16b67unknown_key
fix(deploy): repair Hetzner git remote on every deploy — was 404ing 16h
fix(deploy): repair Hetzner git remote on every deploy — was 404ing 16h
ROOT CAUSE of the persistent admin-dashboard reload loop:
The Hetzner box at /opt/gluecron had its git `origin` remote set to
`https://gluecron.com/ccantynz/Gluecron.com.git`. The gluecron server
itself returns 404 for that URL (likely owner-case mismatch +
push-protection on the self-hosted repo). So on every deploy since
2026-05-15 10:27 UTC, the `git fetch` step in the SSH script failed:
remote: Repository not found
fatal: repository 'https://gluecron.com/ccantynz/Gluecron.com.git/' not found
Process exited with status 128
That meant every commit to main for the past 16+ hours — including
d7ba05d, 67f64a3, 2e8a4d5, 170ddb2, 904927d, and 44fe49b (the four
attempts to kill the AA reload loop) — never reached the live host.
The systemd unit kept running the stale code from yesterday, which
still served the buggy PWA layout, which still produced the SW
collision loop, which the user has been staring at for hours.
Fix: repair the remote on every deploy. The GitHub Actions runner
has GITHUB_TOKEN with `contents: read` (confirmed in the previous
run's permissions block) which is enough for fetch. We re-point
origin to GitHub HTTPS with the token interpolated as basic-auth
on every deploy. `git remote set-url` is idempotent — safe to run
forever, fixes the box automatically on the next deploy.
After this lands, the next push to main will:
1. Set the remote URL to GitHub (with auth)
2. fetch + reset --hard onto 44fe49b (+ this commit)
3. Run bun install / build / migrate / restart
4. Serve the NEW layout with no PWA service workers
5. The kill-switch in the new layout unregisters any SW left
behind in browsers, ending the loop within one page load
No code path other than the deploy script touches the remote URL,
so no other changes needed.1 file changed+16−1ec16b67db3d827f43e1b96b25e37c05daaf10f11
1 changed file+16−1
Modified.github/workflows/hetzner-deploy.yml+16−1View fileUnifiedSplit
@@ -138,6 +138,16 @@ jobs:
138138 APP_BASE_URL: ${{ secrets.APP_BASE_URL || 'https://gluecron.com' }}
139139 GH_RUN_ID: ${{ github.run_id }}
140140 GH_SHA: ${{ github.sha }}
141 # FIX (2026-05-16): the box's git remote was pointing at the
142 # self-hosted URL `https://gluecron.com/ccantynz/Gluecron.com.git`
143 # which the gluecron server itself returns 404 for (owner-case
144 # mismatch + push protection). That meant 16+ hours of failed
145 # deploys — the live site has been running stale since
146 # 2026-05-15 10:27 UTC. We now re-point the remote at GitHub on
147 # every deploy and authenticate with the workflow's GITHUB_TOKEN
148 # (which has contents:read — enough for fetch). Idempotent.
149 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
150 GH_REPO: ${{ github.repository }}
141151 with:
142152 host: ${{ secrets.HETZNER_HOST }}
143153 username: ${{ secrets.HETZNER_USER }}
@@ -148,7 +158,7 @@ jobs:
148158 # share one SSH session across all phases (git pull → install →
149159 # build → migrate → restart) so the in-script curl posts give us
150160 # the live timeline a black-box step boundary can't.
151 envs: DEPLOY_EVENT_TOKEN,APP_BASE_URL,GH_RUN_ID,GH_SHA
161 envs: DEPLOY_EVENT_TOKEN,APP_BASE_URL,GH_RUN_ID,GH_SHA,GH_TOKEN,GH_REPO
152162 script: |
153163 set -euo pipefail
154164 cd /opt/gluecron
@@ -174,6 +184,11 @@ jobs:
174184
175185 notify_step "git-pull" "in_progress"
176186 GP_START=$(date +%s)
187 # Repair the remote on every deploy. The box was historically
188 # pointed at the self-hosted gluecron-side URL which 404s; we
189 # now force it back to GitHub HTTPS with a workflow-scoped PAT
190 # for auth. `set-url` is idempotent.
191 git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GH_REPO}.git"
177192 git fetch --prune origin main
178193 git reset --hard origin/main
179194 new_sha=$(git rev-parse HEAD)
180195