ADR-082: GitOps App Deploy via stack-test and GitHub Actions¶
- Status: Accepted
- Date: 2026-05-08
- Authors: Podcast Scraper Team
- Related RFCs: RFC-082
Context & Problem Statement¶
The always-on host must run the same GHCR image tags and compose overlays as validated in CI.
Operators should not SSH for routine releases; main should remain the source of truth for
what is intended to run after gates pass.
Decision¶
Application promotion to the production VPS follows this contract:
mainis the branch that reflects production intent after review.Stack testonmainmust succeed before treating that SHA as a release candidate for the Docker compose stack.- Image publish to GHCR (tags including
:sha-<short>forapi,viewer, andpipeline-llm) is tied to the validatedmainpipeline. deploy-prod.ymlperforms Tailscale SSH todeploy@and runsinfra/deploy/deploy.sh, wiringPODCAST_RELEASE=sha-<short>for the chosen SHA.
Automation target (RFC-082 Decision 6): add workflow_run on successful Stack test
so deploy starts automatically after publish for the same commit family. Until that trigger is merged,
deploy-prod.yml may remain workflow_dispatch only; operators then gh workflow run
deploy-prod.yml after the same gates (see PROD_RUNBOOK.md).
Infrastructure (infra/**) is not auto-applied on merge: PR CI shows tofu plan;
infra-apply.yml stays manual workflow_dispatch with operator approval so a bad merge
cannot immediately mutate Hetzner or shared Tailscale resources.
Rationale¶
- App vs infra blast radius — frequent image rollouts are low-touch and gate on stack-test; rare cloud changes stay human-gated (RFC-082 Decision 6).
- Single promotion line — stack-test ties the running digest to integration validation on
main.
Alternatives Considered¶
- Deploy on every green
mainpush without stack-test — Rejected; weakens the compose-level gate that catches failures Python-only CI can miss. - Auto
tofu applyon merge forinfra/**— Rejected; risks destroy/typo blast radius; plan in PR + manual apply is the control. - Kubernetes + Flux/ArgoCD — Explicit non-goal in RFC-082 for this footprint.
Consequences¶
- Positive: Routine releases do not require ad-hoc
docker pullon the laptop; deploy logs live in GitHub Actions onceworkflow_runis enabled. - Negative: If stack-test is red,
mainmust not be treated as deploy-ready; with manualdeploy-prod, operators must not deploy before confirming stack-test green. - Neutral: Drill uses
drill-deploy.ymlwith the same image contract, different SSH secret and environment.
Implementation Notes¶
- Workflows:
.github/workflows/deploy-prod.yml, stack-test workflow(s), image publish jobs onmain - Operator docs: PROD_RUNBOOK.md