Spec: Deployment Atomic Rollback
Date: 2026-04-26 Status: Draft
Overview
When AbstractProvider::apply() fails mid-deployment (steps 2-15 after site creation succeeds in step 1), there is no automatic cleanup of created resources. This leaves orphaned sites, databases, and other provisioned resources.
Problem Statement
The 15-step apply() sequence creates resources in order:
- Site (site manager)
- Repository (new sites only)
- Databases
- PHP version
- Nginx config
- Deploy script
- Deployment execution ← most likely failure point
- SSL certificate
- Domain aliases
- Environment variables
- Queue workers
- Cron jobs
- Redirects
- Daemons
- Network rules
If step 7+ fails, steps 1-6 remain provisioned with no rollback.
Proposed Solution
Add an AtomicDeployment wrapper that tracks created resources and cleans up on failure:
class AtomicDeployment {
private array $createdResources = [];
public function trackSite(int $siteId): void { ... }
public function trackDatabase(int $dbId): void { ... }
public function rollback(): void { ... }
}
Rollback behavior:
- Site creation failure → no rollback needed (site not created)
- Repository failure after site creation → destroy site
- Database failure after site creation → destroy site + delete DBs created in this run
- Deployment failure → site remains but is marked failed; continue to allow re-apply
- Step 8-15 failure → site remains, user can fix and re-apply
Alternative: Synchronous Rollback
On apply() failure at any step after step 1, call rollback in reverse order:
15 → 14 → ... → 2 → 1 (reverse destroy order)
Acceptance Criteria
-
AtomicDeploymentclass created -
AbstractProvider::apply()wraps execution in atomic block - Failed deployment after site creation triggers cleanup
- Tests verify rollback behavior
- Rollback does NOT trigger on deployment failure alone (site is provisioned, just deployment failed)