feat(gitops): Terraform plan/promote/apply/drift-check workflows + multi-repo CI provisioner #2
Loading…
Reference in a new issue
No description provided.
Delete branch "phase1/gitops-workflows"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
GitOps plan phase 1.
Not verified live (no Forgejo runner available when written): runner pickup of infra jobs, state-backend credentials on the runner, and the repo secrets these workflows read (FORGEJO_ADMIN_TOKEN, LINODE_TOKEN, CLOUDFLARE_API_TOKEN).
🤖 Generated with Claude Code
GitOps plan phase 1, steps 1a-1d. Real credentials CI already has for staging (LINODE_TOKEN, CLOUDFLARE_API_TOKEN) extend cleanly to owning the Terraform layer end-to-end -- no invariant conflict, unlike the Ansible layer (see roles/gitops_watcher, phase 4, not yet built). New: .forgejo/workflows/terraform-plan.yml (1a) -- posts `tofu plan` against the pinned `linode` workspace as a PR comment on any PR touching terraform/**. Read-only, never applies. Explicit workspace select always -- never the orphaned "default" workspace (docs/incidents.md: ungated by local.skip_dns, ~62 unrelated resources). New: .forgejo/workflows/drift-check.yml (1d) -- scheduled (6h) + workflow_dispatch `tofu plan -refresh-only -detailed-exitcode` across linode/ovh/ovh-dr (matrix), opens a Forgejo issue on drift. This is the direct, automatic fix for the incident that prompted this whole plan: Terraform declared cloudflare_record.proxied=true for vpn.jfraeys.com, live had drifted to false. -refresh-only already does this comparison correctly; the gap was purely "nobody runs it on a schedule." Modified: .forgejo/workflows/staging-validate.yml -- added a `promote` job (needs: validate) implementing 1b (promotion gate) and setting up 1c's trigger: - Pre-promotion production drift check: same -refresh-only mechanism as drift-check.yml, but run synchronously at promotion time -- answers "is prod already wrong, don't build on top of it" rather than only "did something change since the last deploy" (drift-check still runs on its own schedule too, for drift introduced *between* promotions). - On clean drift check: opens/updates a main->prod PR with the staging summary, drift-check result, and a synthetic-secrets Ansible preview attached. Merging that PR is the entire production approval event -- no separate approve command. - Removed the old "Run locally to deploy: ./setup --confirm-prod" message -- this replaces it. - Implemented as a same-workflow `needs:` job dependency rather than a separate promote-to-prod.yml relying on workflow_run/workflow_call, since Forgejo Actions' support for cross-workflow triggers wasn't confirmed -- needs: is unambiguously supported and guarantees ordering either way. Flagged as an open question in the plan; resolved this way during implementation. New: .forgejo/workflows/terraform-apply.yml (1c) -- applies Terraform automatically on push to `prod` (i.e. exactly when the promotion PR above gets merged). Deliberately does not touch Ansible-managed config -- roles/gitops_watcher (phase 4) owns that with real secrets this CI job never has. Includes a placeholder step for signaling gitops_watcher once that role exists. All four files' YAML validated with pyyaml, embedded bash blocks synax- checked with `bash -n`, embedded Python snippets compile-checked -- no live Forgejo Actions runner available in this environment to test an actual run.