The compose file was written via a bash << 'COMPOSE' heredoc nested inside
the YAML run: | block scalar. Lines like "name: petloft-staging" at column 0
cause the YAML parser to break out of the block scalar early, making the
entire workflow file invalid YAML — Gitea silently drops invalid workflows,
so no jobs triggered at all.
Fix: move compose.yml to deploy/staging/compose.yml in the repo, substitute
${REGISTRY} on the runner, base64-encode the result, and decode it on the VPS
inside the SSH session. No inner heredoc needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The VPS had no /opt/staging directory or compose file, causing the deploy
step to fail with "No such file or directory". Now the workflow:
- Creates /opt/staging if missing
- Writes compose.yml on every deploy (keeps it in sync with CI)
- Touches .env so podman compose doesn't error if no secrets file exists yet
Also adds deploy/staging/.env.example documenting runtime secrets that must
be set manually on the VPS after first deploy.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>