feat(deploy): add stage tier — park-buzi as the staging booth
Model the staging-vs-production split that fleet-deployment-komodo flagged as open. Three tiers: dev (working, no booth) -> stage (staging booth park-buzi, real-world test) -> main (production, manual + pinned). - build-images.yml: trigger on [dev, stage, main]. The tag computation is already branch-derived, so :stage / :stage-<sha> build with no other change. - komodo/resources.toml: park-buzi now branch=stage + TAG=stage-<sha> (pinned; no webhook even on staging). BACKUP_KEY already wired as a per-booth secret. - komodo/README.md: a Promotion (dev->stage->main) section; per-booth secret list now includes backup_key; hard-rule #1 generalised to pinned <branch>-<sha>. - wiki: fleet-deployment-komodo open-item resolved + a Promotion-tiers table; deploy-trigger choice generalised; container-deployment tag list gains :stage. Promotion is a merge: when dev is ready, merge dev->stage, CI builds the image, bump TAG=stage-<sha> in resources.toml, deploy from Core. stage is branched from dev HEAD so the first real-world test carries the full current app. Per-booth secrets must pre-exist in Core; migrations run at boot so a promotion auto-migrates the staging ledger (where a bad migration is caught before production). Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
+23
-6
@@ -16,7 +16,22 @@ run `booth.sh`.
|
||||
Procedures), synced into Core via a **ResourceSync**. This is the reviewable, version-
|
||||
controlled source of truth for *which booth runs what*.
|
||||
- **`.env.komodo.example`** — the variables a Stack expects, documenting what comes from Core's
|
||||
**secret store** (per-booth `JWT_SECRET` / `EVENT_SIGNING_KEY`) vs. plain Stack env.
|
||||
**secret store** (per-booth `JWT_SECRET` / `EVENT_SIGNING_KEY` / `BACKUP_KEY`) vs. plain Stack env.
|
||||
|
||||
## Promotion: dev → stage → main
|
||||
|
||||
Three tiers (see `wiki/decisions/fleet-deployment-komodo.md`):
|
||||
|
||||
- **`dev`** — the working branch. CI builds `:dev` / `:dev-<sha>`. No booth deploys off it.
|
||||
- **`stage`** — what the **staging booth (`park-buzi`)** runs, to test the app in real-world
|
||||
conditions. When `dev` is confident-ready, **merge `dev → stage`**; CI builds `:stage` /
|
||||
`:stage-<sha>`; then **bump `TAG=stage-<sha>` in `resources.toml`** to that build and deploy
|
||||
from Core (manual, pinned — no webhook even on staging).
|
||||
- **`main`** — vetted **production** booths: `:main-<sha>`, manual + pinned. `main` only gets what
|
||||
survived staging.
|
||||
|
||||
> The `TAG=stage-<sha>` in `resources.toml` is a **pinned pointer**: the moving `:stage` tag exists
|
||||
> but we deploy the immutable sha so a booth runs a known image. Re-pin on each promotion.
|
||||
|
||||
## How Core consumes this (one-time)
|
||||
|
||||
@@ -43,14 +58,16 @@ booth), and connects **outbound** — the booth opens **no inbound port**. The s
|
||||
## Adding booth N
|
||||
|
||||
Copy the `[[stack]]` block, change `name`, `server` (its onboarded name), and the per-booth
|
||||
secret references (`[[park_<site>_jwt_secret]]`, `[[park_<site>_event_signing_key]]`). Create
|
||||
those secrets in Core's store first.
|
||||
secret references (`[[park_<site>_jwt_secret]]`, `[[park_<site>_event_signing_key]]`,
|
||||
`[[park_<site>_backup_key]]`). Create those secrets in Core's store first. Set `branch` +
|
||||
`TAG` for the tier the booth runs (staging → `stage` / `stage-<sha>`; production → `main` /
|
||||
`main-<sha>`).
|
||||
|
||||
## Hard rules encoded here (do not relax without updating the decision page)
|
||||
|
||||
1. **No deploy webhook on a booth Stack.** Deploys are a human action; pin `TAG=dev-<sha>` before
|
||||
a production booth goes live. A moving `:dev` on a production booth is the non-determinism we
|
||||
rejected. (`TAG=dev` here is fine while staging.)
|
||||
1. **No deploy webhook on a booth Stack.** Deploys are a human action; pin an immutable
|
||||
`TAG=<branch>-<sha>` (staging → `stage-<sha>`, production → `main-<sha>`). A moving tag on a
|
||||
booth is the non-determinism we rejected — and we hold that line even on the staging booth.
|
||||
2. **Onboarding, outbound, mesh-only.** Servers self-register via an onboarding key; Periphery
|
||||
connects outbound to Core's mesh URL and exposes no inbound port. Never a LAN/WAN address.
|
||||
3. **Secrets are per-booth and unique.** `EVENT_SIGNING_KEY` signs the anti-fraud ledger — one
|
||||
|
||||
+10
-5
@@ -18,9 +18,12 @@
|
||||
# EVENT_SIGNING_KEY signs the append-only anti-fraud ledger; BACKUP_KEY encrypts on-site DB
|
||||
# backups (separate from the signing key; escrow it offsite — recovery needs both).
|
||||
#
|
||||
# Deploys are MANUAL + PINNED in spirit: bump TAG to an immutable dev-<sha> before a
|
||||
# production booth goes live (TAG=dev here is the moving tag, fine while staging). NO
|
||||
# deploy webhook is attached to a booth Stack.
|
||||
# Deploys are MANUAL + PINNED: park-buzi is the STAGING booth (real-world test of the app),
|
||||
# so it tracks the `stage` branch + the `:stage` image, but is still deployed by hand with a
|
||||
# PINNED immutable TAG=stage-<sha> (no webhook). Promotion: merge dev → stage when confident,
|
||||
# CI builds :stage / :stage-<sha>, then bump TAG below to that sha and deploy from Komodo Core.
|
||||
# A PRODUCTION booth tracks `main` + manual+pinned `:main-<sha>`. See
|
||||
# wiki/decisions/fleet-deployment-komodo.md (dev → stage → main tiers).
|
||||
|
||||
##############################################################################
|
||||
# Stack — the deployable unit for booth "park-buzi". One Stack per booth; add a
|
||||
@@ -34,7 +37,7 @@ server = "park-buzi"
|
||||
git_provider = "git.infra.msai.al"
|
||||
git_account = "komodo"
|
||||
repo = "mca/parking_solution"
|
||||
branch = "dev"
|
||||
branch = "stage"
|
||||
file_paths = [
|
||||
"docker-compose.yml",
|
||||
"docker-compose.prod.yml"
|
||||
@@ -43,7 +46,9 @@ registry_provider = "git.infra.msai.al"
|
||||
registry_account = "komodo"
|
||||
environment = """
|
||||
REGISTRY=git.infra.msai.al/mca/parking_solution
|
||||
TAG=dev
|
||||
# Staging booth: pin an immutable stage-<sha> per deploy (bump after merging dev → stage and
|
||||
# CI builds it). The moving `:stage` tag exists as the pointer; we deploy the sha, not the mover.
|
||||
TAG=stage-84f00db
|
||||
COOKIE_SECURE=0
|
||||
VISION_ENABLED=1
|
||||
WS_ALLOWED_ORIGINS=
|
||||
|
||||
Reference in New Issue
Block a user