Files
slp-modular-cms/aidlc-docs/features/gitea-deployment-workflow/operations/deployment/rollback-plan.md
T
Sluijsens 97f18d00e5 Names the deployed instance slpsoftware, not the software itself
SlpModularCms is the product; slpsoftware.nl is the customer running
it - the first one, and a fine stand-in for what a real deployment
looks like. Renamed the directories, systemd units, and backup paths
accordingly. Left the backup script's own filename alone since the
already-committed deploy-scp.yaml calls it by that exact name.
2026-07-28 22:16:04 +02:00

3.2 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/slpsoftware/<env>/releases
ls -1t                                    # confirm which directory is the previous, working release
ln -sfn ~/apps/slpsoftware/<env>/releases/<previous-timestamp> ~/apps/slpsoftware/<env>/current
systemctl --user restart slpsoftware-<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