PHP Deployment Pipeline
debt(d9/e7/b7/t7)
Closest to 'silent in production until users hit it' (d9). The detection_hints note 'automated: no' and the code_pattern describes manual processes — no automated tool from the list (github-actions, gitlab-ci, deployer, envoyer, capistrano) will flag the absence of a pipeline. The absence of a proper pipeline only becomes visible when a bad deploy causes downtime, stale OPcache serves old code, or dropped requests occur during FPM restarts — all of which are silent until users experience errors.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix outlines a multi-stage pipeline: composer install → phpcs → phpstan → test → build docker image → push to registry → deploy to staging → smoke test → deploy to production. Moving from FTP/manual deploys to a fully automated atomic pipeline with zero-downtime deploys, OPcache clearing, and smoke tests requires coordinating CI/CD configuration files, server setup, Docker infrastructure, and potentially DNS/load balancer changes — spanning the entire delivery infrastructure.
Closest to 'strong gravitational pull' (b7). The deployment strategy shapes every aspect of the development workflow — how branches are structured, how environments are managed, how hotfixes are handled, and how the team responds to incidents. A poor or absent pipeline creates ongoing drag on every release cycle, affects both web and cli contexts per applies_to, and the lack of rollback mechanisms means every future deploy carries elevated risk until the pipeline is properly established.
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field directly states the canonical wrong belief: 'FTP uploading files to a server is a valid PHP deployment strategy.' This is a well-established mental model carried over from earlier PHP development practices where FTP was the norm. Developers familiar with this approach don't realize it leaves the server in a mixed state mid-deploy, skips tests, and prevents atomic rollback — behaviors that contradict how modern deployment tools from the detection_hints list operate.
Also Known As
TL;DR
Explanation
A mature PHP deployment pipeline: (1) Push triggers CI — composer install --no-dev, phpcs, phpstan analyse, phpunit --coverage-clover, security audit. (2) Docker image built from production Dockerfile — tagged with git SHA. (3) Image pushed to container registry. (4) Staging deploy — image rolled out to staging environment, migrations run, smoke tests executed against staging. (5) Manual or automatic approval gate. (6) Production deploy — rolling or blue/green, zero downtime, post-deploy health check. (7) Automated rollback if health check fails. Tools: GitHub Actions / GitLab CI for orchestration, Deployer or Kubernetes for deployment, Sentry for error monitoring post-release. Keep the pipeline fast — under 10 minutes total is the target. Flaky tests erode trust and must be fixed immediately.
Common Misconception
Why It Matters
Common Mistakes
- No zero-downtime deploy — FPM restart during traffic causes dropped requests.
- Running composer install on production instead of deploying vendor/ or a built artifact.
- Not clearing OPcache after deploy — stale bytecode serves old code.
- No smoke test after deploy — a broken deploy serves errors until someone notices.
Code Examples
# Naive deploy — causes downtime:
git pull origin main
composer install # Runs on live server
php artisan migrate # Runs on live server
systemctl restart php-fpm # Drops in-flight requests
# Better: atomic symlink swap after all prep is done on idle copy
# PHP deployment pipeline — .github/workflows/deploy.yml
steps:
# 1. Install dependencies (production only)
- run: composer install --no-dev --optimize-autoloader --no-interaction
# 2. Quality gates (fail fast)
- run: composer audit # CVE check
- run: vendor/bin/phpcs --standard=PSR12 # code style
- run: vendor/bin/phpstan analyse # type errors
- run: vendor/bin/phpunit # tests
# 3. Build assets
- run: npm ci && npm run build
# 4. Deploy
- run: rsync -az --delete public/ deploy@prod:/var/www/app/public/
# 5. Migrations (backwards-compatible first)
- run: ssh deploy@prod 'php /var/www/app/artisan migrate --force'
# 6. Cache warm + graceful restart
- run: ssh deploy@prod 'php /var/www/app/artisan optimize && sudo systemctl reload php8.3-fpm'
# 7. Health check
- run: curl --fail https://yourapp.com/health