PHP Deployment Pipeline
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