diff --git a/.github/workflows/rolling-update.yml b/.github/workflows/rolling-update.yml index 4344b5d62..b26112586 100644 --- a/.github/workflows/rolling-update.yml +++ b/.github/workflows/rolling-update.yml @@ -2,7 +2,7 @@ name: Rolling update # Manually-triggered production rollout. Joins the Tailnet, SSHes over # MagicDNS into each node, and invokes scripts/rolling-update.sh. -# See docs/design/2026_04_24_proposed_deploy_via_tailscale.md. +# See docs/design/2026_04_24_implemented_deploy_via_tailscale.md. on: workflow_dispatch: diff --git a/docs/deploy_via_tailscale_runbook.md b/docs/deploy_via_tailscale_runbook.md index 3a55f5914..ad5926afc 100644 --- a/docs/deploy_via_tailscale_runbook.md +++ b/docs/deploy_via_tailscale_runbook.md @@ -1,6 +1,6 @@ # Deploy via Tailscale + GitHub Actions — Runbook -Companion doc to `docs/design/2026_04_24_proposed_deploy_via_tailscale.md`. This +Companion doc to `docs/design/2026_04_24_implemented_deploy_via_tailscale.md`. This runbook is for operators: what to configure on GitHub and Tailscale so the `rolling-update` workflow can execute a production deploy. diff --git a/docs/design/2026_04_24_proposed_deploy_via_tailscale.md b/docs/design/2026_04_24_implemented_deploy_via_tailscale.md similarity index 88% rename from docs/design/2026_04_24_proposed_deploy_via_tailscale.md rename to docs/design/2026_04_24_implemented_deploy_via_tailscale.md index c7dc3acd8..cc79f9bbf 100644 --- a/docs/design/2026_04_24_proposed_deploy_via_tailscale.md +++ b/docs/design/2026_04_24_implemented_deploy_via_tailscale.md @@ -1,9 +1,17 @@ # Deploy via Tailscale + GitHub Actions -**Status:** Proposed +**Status:** Implemented **Author:** bootjp **Date:** 2026-04-24 +Implemented by `.github/workflows/rolling-update.yml` and +`docs/deploy_via_tailscale_runbook.md`. The workflow is manually triggered via +`workflow_dispatch`, joins the tailnet with `tailscale/github-action@v3`, +configures plain SSH over MagicDNS, renders `NODES` / `SSH_TARGETS` from the +GitHub production environment, runs SSH reachability checks, supports dry-run, +verifies the image tag exists, and invokes `scripts/rolling-update.sh` for live +rollouts. + --- ## 1. Background @@ -228,14 +236,22 @@ before production cutover. - Tailscale SSH (option A above). - A shared `deploy` user with restricted sudo. -## 5. Implementation plan - -1. Write `.github/workflows/rolling-update.yml` implementing §2.1. -2. Document the secrets/variables setup in - `docs/deploy_via_tailscale_runbook.md`. -3. Run once with `dry_run: true` on a feature branch to validate secrets - wiring without touching prod. -4. Run once with `dry_run: false` targeting a single node (via the `nodes` - input) to prove the happy path. -5. Cut over: archive the operator-local rolling flow, document the new one - as the canonical path. +## 5. Implementation status + +Implemented components: + +1. `.github/workflows/rolling-update.yml` implements the workflow shape in §2.1: + trusted default-branch checkout, GHCR image existence check, ephemeral + tailnet join, SSH configuration, rendered `NODES` / `SSH_TARGETS`, dry-run, + and live rollout paths. +2. `docs/deploy_via_tailscale_runbook.md` documents Tailscale node setup, + ACLs, OAuth client setup, GitHub production environment secrets/variables, + dry-run/live run sequence, rollback, cancellation recovery, and known + troubleshooting cases. +3. `scripts/rolling-update.sh` remains the rollout executor used by the + workflow; the workflow now supplies its environment and calls the script in + either `--dry-run` or live mode. + +Operational cutover is controlled outside the repository by the GitHub +production environment configuration and the node-level Tailscale/SSH setup +described in the runbook.