ci: auto-deploy main → prod (GHCR build + pull-deploy on gerty)#50
Conversation
Wire continuous deployment to teal.dotmavriq.life on push to main, gated
on the existing quality + tests jobs.
- compose: app/queue now run the CI-built GHCR image
(ghcr.io/dotmavriq/teal:${TEAL_TAG}) instead of building on gerty's
1-core/2GB box. Commits the prod-only .env ro-mount. db service is
left completely untouched.
- docker/deploy-prod.sh: data-safe pull-deploy run on gerty. Acts on
app+queue by name only; never down/-v/volume rm; never touches the
teal-db-data volume. Verified pg_dump backup before anything goes live
(no backup = abort), destructive-migration guard (HALT on
DROP/TRUNCATE/DELETE in pending migrations), health-gated with
auto-rollback to the previous image.
- workflow: build-and-deploy job (needs quality+tests, push-to-main only)
builds+pushes the image to GHCR then SSHes to gerty to run the deploy.
Secrets (.env/.env.production) stay on gerty and are never shipped from
CI. Requires repo secrets GERTY_HOST/GERTY_USER/GERTY_SSH_KEY.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
Caution Review failedPull request was closed or merged during review Note
|
| Layer / File(s) | Summary |
|---|---|
CI Build & Push to GHCR .github/workflows/tests.yml |
New build-and-deploy job triggers on push to main after tests pass, builds the production Docker image, pushes to GHCR with SHA and latest tags, then SSH deploys using the deploy script with TEAL_TAG set to the commit SHA. |
Docker Compose Image Configuration docker-compose.yml |
app and queue services switch from local builds to image references using ${TEAL_IMAGE}:${TEAL_TAG}. app service adds read-only .env mount with clarifying comments on secret handling vs. image build separation. |
Deploy Script Initialization & Guards docker/deploy-prod.sh |
Script sets strict error handling, defines config and logging helpers, validates project directory, enforces input guards against destructive teardown commands, and pre-flight-checks required files, Docker network, and teal-db health. |
Backup, Safety Checks & Live Deployment docker/deploy-prod.sh |
Captures current image for rollback, creates timestamped gzipped database backups with integrity checks and schema validation, pulls new image, runs migrations in pretend mode to scan for destructive SQL patterns (DROP/TRUNCATE/DELETE), then brings up app + queue with the new image while preserving the database. |
Health Monitoring & Automated Rollback docker/deploy-prod.sh |
Polls teal-app health status until healthy or timeout, prunes unused images on success. On failure, rolls back to the previous image if it matches GHCR repository prefix; otherwise aborts with instructions while preserving the database and backup. |
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Poem
🚀 From source code to the cloud it flies,
With tests that pass and images rise,
Backups stand guard, migrations beware,
Health checks confirm—then rollback's there!
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title directly captures the main change: adding CI-driven auto-deployment to production when pushing to main, building and pushing images to GHCR, then deploying on the gerty host. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
📝 Generate docstrings
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
ci/auto-deploy-prod
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
Log in to ghcr.io with the workflow's GITHUB_TOKEN before pulling, so the image can stay a private package (no manual visibility flip). Logout after.
What
Continuous deployment to teal.dotmavriq.life on every push to
main, gated on the existingquality+testsjobs. Image is built in CI and pulled on gerty (gerty's 1-core/2 GB box never builds).Flow
🛡️ Data protection (prime directive)
The prod Postgres data lives in the named volume
teal-db-data, separate from the app image.docker/deploy-prod.sh:app+queueonly, by explicit name — never touches thedbservice or its volumedown,down -v,volume rm,--renew-anon-volumesgzip -t+ table-presence)pg_dumpruns before anything goes live; rotates last 10migrate --pretendand HALTS onDROP TABLE/COLUMN,TRUNCATE,DELETE FROM(additive migrations auto-apply)teal-appfails its health checkSecrets
.env/.env.productionstay only on gerty (the image carries no secrets). CI needs repo secretsGERTY_HOST,GERTY_USER,GERTY_SSH_KEY(set out-of-band) and the built-inGITHUB_TOKENfor GHCR.Notes
app/queuebuild:blocks becomeimage:. Local/dev builds usedocker-compose.dev.yml.🤖 Generated with Claude Code
Summary by CodeRabbit