GITHUB_TOKEN expires with the workflow run, but `docker login` writes it
to /root/.docker/config.json on the host, where it stays. Docker then
presents that dead token on every subsequent pull and does NOT fall back
to anonymous, so even a public image fails with "No such image" -- which
reads as a missing image rather than a stale credential.
This broke deploys of services that have nothing to do with this workflow.
The workaround each time was to delete the ghcr.io auth entry by hand,
pull, and restore it; the stale entry has now been removed from the host
as well.
Uses a trap on EXIT rather than a trailing command so the logout also runs
when a pull or a stack deploy fails -- the failure case is exactly when a
half-finished run would otherwise leave the credential behind.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLYiaPYror1vLKApYKrxTu
Previously a devops push would re-deploy prod-stack against whatever
:main was cached locally on the host, silently reverting recent
frontend/api rolls.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors cipherdolls/devops layout. Hostinger Swarm stacks for the t4t
hosted-gateway and local docker-compose for development + e2e tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>