A deploy should not be a moment of hope. Ours is a pipeline: it checks the code, builds the release, backs up the database, switches versions in one step and rolls back by itself if the site does not answer. This page describes the workflows that deploy 4wp.dev.
Two workflows, two environments
| Staging | Production | |
|---|---|---|
| Trigger | Push to the staging branch | Manual run, only from main |
| Database backup | No | Yes, before every release |
| Smoke test and rollback | Yes | Yes |
| Secrets | GitHub Environment staging | GitHub Environment production |
The pipeline
flowchart TB
Q["Quality gate<br/>bin/checks.sh"] --> B["Composer install<br/>--no-dev --optimize-autoloader"]
B --> S["Check secrets"]
S --> BK["Backup database<br/>production only"]
BK --> U["Upload release<br/>releases/timestamp"]
U --> L["Link shared .env and uploads<br/>switch current symlink"]
L --> W["Post-deploy WP-CLI<br/>update-db, rewrite flush"]
W --> T{"Smoke test"}
T -->|ok| K["Keep last 5 releases"]
T -->|fail| R["Roll back to previous release"]
- Quality gate. The same
bin/checks.shas the pre-commit hook: forbidden files, secrets, PHP syntax,composer validate. A local hook can be skipped; this step cannot. - Build.
composer install --no-dev --optimize-autoloader; staging caches Composer between runs. - Backup. Production exports the database with WP-CLI into
shared/backupsbefore the release. - Atomic release. The code goes into a new
releases/<timestamp>folder..envand uploads are linked fromshared/, and thecurrentsymlink switches in one step: visitors never see a half-uploaded site. - Post-deploy. WP-CLI checks the install, updates the database and flushes rewrite rules. Staging also resets OPcache after the symlink switch.
- Smoke test. WP-CLI confirms WordPress is installed and answers; production can also check the home page over HTTP.
- Rollback. If the smoke test fails,
currentpoints back to the previous release. - Cleanup. The last 5 releases are kept.
Secrets
Secrets live in GitHub Environments, separately for staging and production: host, user, path, SSH key, known hosts and Composer credentials. The .env files stay on the servers in shared/ and never enter Git.
What is next
Tests are the next stage of our pipeline: PHPUnit for our plugins and Playwright for end-to-end checks.
FAQ
Why is production manual?
A person decides when production changes. Everything else is automated.
What makes a deploy atomic?
The new release is complete before the current symlink switches to it, in one operation.
What if the database update breaks something?
Code rolls back automatically; the database backup taken before the release is the way back for data.