Deployment & CI/CD
keepcadence deploys with trunk-based development + build-once image promotion. There are no long-lived environment branches.
The flow
Section titled “The flow”feature/* ──PR──▶ main │ push to main ───┼──▶ CI (check + python) .github/workflows/ci.yml │ └──▶ Release: build sha-<SHA> .github/workflows/release.yml images → ghcr.io/schneid-l/* └──▶ auto-deploy STAGING
git tag vX.Y.Z ──▶ promote: retag sha-<SHA> → vX.Y.Z + latest (no rebuild) └──▶ deploy PRODUCTIONThe image tested on staging is the exact same digest promoted to
production — promote only retags, it never rebuilds.
Ship to staging
Section titled “Ship to staging”Merge a PR into main (or push to main). That’s it:
ci.ymlrunscheck(lint, types, build, unit tests) +python(worker pytest).e2eruns on PRs and nightly only — not on every push (private-repo Actions minutes are metered).release.ymlbuilds the six app images taggedsha-<commit>, cosign-signs them, attaches an SBOM, pushes to GHCR, then triggers the Coolify staging deploy for all six apps.
Staging URLs: see runbooks/coolify.md. Health: curl https://api.staging.keepcadence.stream/health/ping.
Ship to production
Section titled “Ship to production”Production deploys are gated — only a version tag can trigger one:
git tag v1.4.0 && git push origin v1.4.0This runs promote (retags the already-built sha-<commit> images to
v1.4.0 + latest) then deploy-production. The production GitHub
Environment restricts deployments to v* tags.
Rollback = deploy an earlier tag’s image (re-run deploy-production
for the previous v*, or point Coolify at the older image).
CI speed
Section titled “CI speed”turbo build/test/check-types hit a self-hosted Turborepo remote
cache at https://turbo-cache.host.schne.id (a container in the
keepcadence-infra Coolify project). An unchanged push is a near-total
cache hit. TURBO_TOKEN/TURBO_TEAM are the repo secret/variable.
Concurrency
Section titled “Concurrency”- Image builds never cancel (a half-pushed layer is corrupt).
- Staging deploys cancel superseded runs — newest commit wins.
- Production deploys never cancel — a tag promotion must complete.
Infrastructure map
Section titled “Infrastructure map”| Piece | Where |
|---|---|
| Apps (6) | Coolify project keepcadence, staging environment |
| DB | Coolify-managed Postgres (pgvector); daily backup → R2 |
| Shared infra | Coolify project keepcadence-infra — Actions runner, turbo cache |
| Worker GPUs | RunPod serverless, 9 endpoints |
| TLS | Traefik + Let’s Encrypt (letsencryptkc HTTP-01 resolver) |
| Analytics | PostHog proxy at users.keepcadence.stream |
Required GitHub secrets / variables
Section titled “Required GitHub secrets / variables”Repo: COOLIFY_DEPLOY_TOKEN, COOLIFY_WEBHOOK_{API,ORCHESTRATOR,APP,ADMIN,LANDING,DOCS},
TURBO_TOKEN, KC_CF_API_TOKEN, KC_CF_ACCOUNT_ID, KC_STAGING_PG_PASSWORD.
Repo vars: COOLIFY_API_URL, TURBO_TEAM.
Environments: staging (no gate), production (v* tags only).