Files
slp-modular-cms/aidlc-docs/features/gitea-deployment-workflow/operations/deployment/rollback-plan.md
T
Sluijsens 843253888e Nests environments under one slpmodularcms folder instead of siblings
Applies to both the app's own release tree and the website upload
path - slpmodularcms/test and slpmodularcms/production side by side
under one parent, not two separately-named directories. Service unit
names stay hyphenated; those aren't folders.
2026-07-28 21:43:37 +02:00

3.3 KiB
Raw Blame History

Rollback Plan

Mechanism (D-26, infrastructure-design.md § 34): two releases are always retained — current plus exactly one previous. Pruning only ever runs after a passing health check, so a failed deploy never leaves fewer than two releases on disk.

When to Roll Back

  • The deploy workflow's health check failed (job already shows red; current was left pointing at the new, unhealthy release — no automatic rollback, per infrastructure-design.md § 4)
  • The deploy succeeded and passed its health check, but a defect surfaces afterward that only shows up under real traffic

Fast Rollback (Previous Release Still on Disk) — the Common Case

No rebuild needed. Over SSH, on the Pi:

cd ~/apps/slpmodularcms/<env>/releases
ls -1t                                    # confirm which directory is the previous, working release
ln -sfn ~/apps/slpmodularcms/<env>/releases/<previous-timestamp> ~/apps/slpmodularcms/<env>/current
systemctl --user restart slpmodularcms-<env>.service
curl -f https://<env-domain>/health       # confirm the rollback itself is healthy

This is the same atomic-switch primitive the deploy workflow itself uses — pointing it backward instead of forward. wwwroot/web/ is untouched either way, since it was never part of the switched directory to begin with (FR-08).

Rebuild-and-Redeploy Rollback (Older Than One Release Back)

If the defect predates the retained previous release, redeploy an earlier commit through the normal pipeline:

  1. git revert or check out the last-known-good commit on a branch
  2. Push to master (test) or run workflow_dispatch with deploy_production: true (production) — the same gates and deploy sequence run as any other deploy
  3. This only works because migrations are required to be forward-compatible and non-destructive (D-26) — redeploying an older commit's code against a database that has since had newer migrations applied must not break. If a migration since the target commit was destructive, this path is not safe and the database backup (§ below) is the actual recovery route instead

Database Rollback

A backup is taken before every production deploy (operations/deployment/deployment-instructions.md § 4, invoked by deploy-scp.yaml when run_db_backup: true). To restore:

sqlcmd -S <server> -U <user> -P <password> -C -Q \
  "RESTORE DATABASE [SlpModularCmsProduction] FROM DISK = N'<path-to-backup>.bak' WITH REPLACE"

Restoring a database backup and rolling back the application release are independent actions — decide based on the actual failure whether one, the other, or both are needed. Rolling back the app without restoring the database is usually sufficient (migrations are non-destructive by design); restoring the database without rolling back the app should be rare and deliberate.

What Is Never Part of a Rollback

  • wwwroot/web/ (the customer's website) — structurally outside every release directory; no rollback action should ever touch it
  • The Data Protection key ring — lives in the database, not the release directory; rolling back the app release does not affect it
  • Gitea Actions variables/secrets — these describe the target, not a specific release; nothing about them changes during a rollback