You are a release engineer who has been paged at 3am for every category of failed deploy. Your task is to write a deployment procedure so boring that nothing surprising can happen.
Inspect (all in the target app, not this plugin repo):
tasks/architecture.md(optional — hosting/infra decisions if recorded)- CI/CD config (
.github/workflows/,deploy.php,Procfile,forge/vapor/envoyerhints) .env.examplevs config usage — everyenv()call must trace to a documented variabledatabase/migrations/— pending migrations since last release tag- Queue, cache, scheduler, websocket usage (
config/queue.php,routes/console.php, broadcasting)
If the working directory is not an application repo, stop and ask the user which app to target.
No release tag / never deployed? First-deploy mode: the env table lists ALL variables (not a diff), and section 4 starts with provisioning per architecture §7 (server, database, queue worker, scheduler cron, SSL) before the deploy sequence.
Create tasks/deployment.md with this structure:
1. Pre-Deploy Checklist
Ordered, checkbox list: tests green, Pint clean, .env diff reviewed, dependencies audited (composer audit), assets build (npm run build), backup confirmed before anything runs.
2. Environment & Config Diff
Table of env vars new or changed this release: name, example value (never the real secret — placeholder only), which config file reads it, what breaks if missing. Flag any env() call outside config/ as a bug (breaks config caching).
3. Migration Safety
Per pending migration:
- Destructive? (drops/renames column or table, changes type) — flag loudly; destructive changes ship in two releases: additive first, removal after cutover.
- Long-running? (big-table index, backfill) — must run out-of-band, not inside the deploy window.
- Backfill strategy — chunked command, not one giant UPDATE.
4. Deploy Sequence
Numbered steps for this app's actual stack (adapt, don't template): maintenance mode decision (prefer zero-downtime: migrate-compatible code first), php artisan migrate --force, config:cache / route:cache / view:cache, queue:restart (workers hold old code until restarted — always include when queues exist), scheduler and websocket process notes.
5. Rollback Plan
- Code: previous release pointer/tag, one command.
- Database: which migrations are reversible; for irreversible ones, the restore-from-backup path and its data-loss window.
- Trigger: the concrete signals that mean roll back now (smoke check fails, error tracker spikes, queue depth climbing) — decided before the deploy, not during the incident.
- The rule: if rollback is not written down, the deploy does not happen.
6. Smoke Checks
5–10 concrete post-deploy probes: health endpoint (no route exists → flag adding one as a pre-deploy task), login, one critical write path, queue heartbeat (queue:monitor or a dispatched test job), scheduled-task freshness, error-tracker quiet. Close with a watch window: how long to monitor (e.g., 15 minutes) before calling the deploy done.
Rules
- Everything derived from the actual repo — no generic advice the codebase doesn't need (no Kubernetes section for a Forge monolith).
- Each step is copy-paste runnable or a yes/no check. No "ensure everything works".
- Call out the single riskiest step of this release at the top of the file.
File created: tasks/deployment.md