本文目录导读:

我来详细介绍 PHP 项目的 CI/CD 管道配置,包括常见的工具和实践方案。
常用 CI/CD 工具选择
# 常用工具组合 1. GitHub Actions / GitLab CI / Jenkins 2. PHPUnit + PHP CS Fixer + PHPStan 3. Composer 依赖管理 4. Docker 容器化部署 5. 部署工具:Deployer, Capistrano
GitHub Actions 配置示例
基础配置 .github/workflows/php.yml
name: PHP CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['8.0', '8.1', '8.2']
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, intl, pdo_mysql
coverage: xdebug
- name: Install Dependencies
run: |
composer install --no-progress --prefer-dist --optimize-autoloader
cp .env.example .env
php artisan key:generate
- name: Run Tests
run: |
php artisan migrate --force
vendor/bin/phpunit
env:
DB_CONNECTION: sqlite
DB_DATABASE: :memory:
- name: Run Code Style
run: |
vendor/bin/php-cs-fixer fix --dry-run --diff
vendor/bin/phpstan analyse --memory-limit=512M
- name: Run Security Check
run: composer audit
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v3
- name: Setup SSH
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy to Production
run: |
ssh deployer@server 'cd /var/www/app && git pull && composer install --no-dev && php artisan migrate --force && php artisan config:cache'
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
GitLab CI 配置示例
.gitlab-ci.yml
image: php:8.2
variables:
MYSQL_DATABASE: test_db
MYSQL_ROOT_PASSWORD: root
DB_HOST: mysql
DB_USERNAME: root
DB_PASSWORD: root
services:
- mysql:8.0
stages:
- test
- quality
- build
- deploy
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- vendor/
before_script:
- apt-get update -qq
- apt-get install -y -qq git zip unzip libxml2-dev libpq-dev
- docker-php-ext-install pdo pdo_mysql pdo_pgsql
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
test:
stage: test
script:
- composer install --no-progress --prefer-dist
- cp .env.testing .env
- php artisan migrate --force
- vendor/bin/phpunit --coverage-text --colors=never
artifacts:
reports:
cobertura: build/coverage.xml
code_quality:
stage: quality
script:
- vendor/bin/phpstan analyse --memory-limit=512M
- vendor/bin/php-cs-fixer fix --dry-run --diff
- vendor/bin/phpcs --standard=PSR2 app/ tests/
build:
stage: build
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
deploy_production:
stage: deploy
script:
- apt-get install -y -qq sshpass
- sshpass -p $PRODUCTION_PASSWORD ssh deployer@server "
cd /var/www/project &&
git pull origin main &&
composer install --no-dev --optimize-autoloader &&
php artisan migrate --force &&
php artisan cache:clear &&
php artisan config:cache &&
php artisan route:cache &&
php artisan view:cache
"
only:
- main
environment:
name: production
when: manual
Jenkins Pipeline 示例
Jenkinsfile
pipeline {
agent any
environment {
MYSQL_DATABASE = 'test_db'
MYSQL_USER = 'test_user'
MYSQL_PASSWORD = 'test_password'
MYSQL_HOST = 'localhost'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Setup') {
steps {
sh '''
apt-get update -qq
apt-get install -y -qq php php-cli php-mysql php-xml php-mbstring composer
composer install --no-progress --prefer-dist
cp .env.jenkins .env
php artisan key:generate
'''
}
}
stage('Test') {
parallel {
stage('PHPUnit') {
steps {
sh 'vendor/bin/phpunit --coverage-text'
}
}
stage('Static Analysis') {
steps {
sh 'vendor/bin/phpstan analyse --memory-limit=512M'
}
}
stage('Code Style') {
steps {
sh 'vendor/bin/php-cs-fixer fix --dry-run --diff'
}
}
}
}
stage('Security') {
steps {
sh 'composer audit --format=json > security_report.json'
}
}
stage('Build') {
steps {
sh '''
if [ "$GIT_BRANCH" = "origin/main" ]; then
docker build -t app:${GIT_COMMIT} .
docker push registry.example.com/app:${GIT_COMMIT}
fi
'''
}
}
stage('Deploy') {
when {
branch 'main'
}
steps {
script {
sh '''
ansible-playbook deploy.yml \
-e HOST=production \
-e VERSION=${GIT_COMMIT} \
--extra-vars "vault_password_file=~/.vault_pass"
'''
}
}
}
}
post {
always {
junit 'build/reports/phpunit/*.xml'
cleanWs()
}
failure {
slackSend(
color: 'danger',
message: "Job '${env.JOB_NAME}' (${env.BUILD_NUMBER}) failed: ${env.BUILD_URL}"
)
}
success {
slackSend(
color: 'good',
message: "Job '${env.JOB_NAME}' (${env.BUILD_NUMBER}) succeeded"
)
}
}
}
高级配置技巧
Docker 多阶段构建 Dockerfile
# 开发环境
FROM php:8.2-fpm-alpine AS dev
WORKDIR /var/www
# 生产环境
FROM node:16-alpine AS frontend-build
WORKDIR /app
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
FROM php:8.2-fpm-alpine AS prod
WORKDIR /var/www
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY --from=frontend-build /app/dist /var/www/public/dist
RUN docker-php-ext-install pdo_mysql opcache
COPY . .
COPY --from=dev /var/www/vendor /var/www/vendor
RUN chown -R www-data:www-data /var/www \
&& chmod -R 755 /var/www
USER www-data
CMD ["php-fpm"]
部署脚本示例
Deployer 配置 deploy.php
<?php
namespace Deployer;
require 'recipe/laravel.php';
set('application', 'My PHP Application');
set('repository', 'git@github.com:username/repo.git');
set('php_version', '8.2');
host('production')
->set('hostname', '203.0.113.10')
->set('user', 'deployer')
->set('deploy_path', '/var/www/app')
->set('branch', 'main')
->set('keep_releases', 5);
set('shared_files', [
'.env',
'storage/oauth-private.key',
'storage/oauth-public.key',
]);
task('deploy:quality', function () {
run('cd {{release_path}} && vendor/bin/phpstan analyse');
run('cd {{release_path}} && vendor/bin/php-cs-fixer fix --dry-run');
});
task('deploy:security', function () {
run('cd {{release_path}} && composer audit --no-dev');
});
task('deploy:healthcheck', function () {
run('curl -f http://localhost/health-check');
});
before('deploy', 'deploy:quality');
before('deploy', 'deploy:security');
after('deploy:success', 'deploy:healthcheck');
最佳实践建议
环境变量管理
# 使用 GitHub Secrets
secrets:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
APP_KEY: ${{ secrets.APP_KEY }}
PGP_KEY: ${{ secrets.PGP_KEY }}
数据库迁移策略
# CI 中使用内存数据库
DB_CONNECTION: sqlite
DB_DATABASE: :memory:
# 生产环境使用手动审批
deploy_production:
stage: deploy
when: manual
script:
- php artisan migrate --force --path=database/migrations
安全扫描
security_scan:
stage: test
script:
- composer audit --format=json
- vendor/bin/php-security-checker
- nmap -sV --script vulners target_server
完整生产级配置
创建 .env.ci 文件:
APP_ENV=testing APP_DEBUG=false APP_URL=http://ci.example.com DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 DB_DATABASE=test_db DB_USERNAME=test_user DB_PASSWORD=test_password CACHE_DRIVER=array SESSION_DRIVER=array QUEUE_CONNECTION=sync
关键要点
- 多环境支撑:开发、测试、生产环境配置分离
- 自动化测试:单元测试、集成测试、E2E 测试
- 质量检查:代码规范、静态分析、安全扫描
- 部署策略:蓝绿部署、滚动更新、灰度发布
- 监控反馈:部署后自动检查健康状态
这个配置涵盖了 PHP 项目 CI/CD 的完整流程,可以根据项目需求进行适当调整。