PHP项目如何实现CI/CD?

wen java案例 2

本文目录导读:

PHP项目如何实现CI/CD?

  1. 核心流程概述
  2. 工具选型
  3. 具体配置示例(两种主流方案)
  4. 关键实践与注意事项
  5. 针对不同 PHP 框架的注意点
  6. 进阶:蓝绿部署与金丝雀发布
  7. 最佳实践清单

在 PHP 项目中实现 CI/CD(持续集成/持续部署),核心目标是自动化代码的构建、测试、部署流程,下面从工具选型、流程设计和具体配置示例三个方面来详细说明。

核心流程概述

一个典型的 PHP CI/CD 流水线包含以下阶段:

代码提交(Git Push) 
    → 触发 CI 
    → 环境准备(Composer install) 
    → 代码质量检查(PHPStan, PHPCS) 
    → 单元测试(PhpUnit) 
    → 构建产物(可选, 如打包Docker镜像) 
    → 部署到测试/预发/生产环境

工具选型

代码托管 & CI 平台

  • GitHub Actions(最推荐,与GitHub深度集成,免费额度足够小团队)
  • GitLab CI/CD(配合自建GitLab或GitLab SaaS)
  • Jenkins(适合复杂、高度自定义的企业项目)
  • Bitbucket Pipelines(如果代码托管在Bitbucket)
  • Drone / CircleCI / Travis CI(其他选择)

测试与代码质量工具

  • Composer:依赖管理
  • PHPUnit:单元测试框架
  • PHP_CodeSniffer:代码风格检查
  • PHPStan / Psalm:静态分析(推荐必须使用)
  • Deptrac:依赖检查(大型项目推荐)

部署方式

  • 通过 SSH + rsync/scp:传统、直接
  • 通过 Docker 镜像:更现代化、环境一致性好
  • 使用 Envoy / Deployer:PHP 专用的部署工具
  • 通过 K8s:容器化后的最佳选择

具体配置示例(两种主流方案)

GitHub Actions + Docker 部署(推荐)

项目根目录创建 .github/workflows/deploy.yml

name: PHP CI/CD
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
jobs:
  test_and_lint:
    runs-on: ubuntu-latest
    services:
      # 如果需要MySQL或Redis服务
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: test
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
    steps:
      - uses: actions/checkout@v4
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: mbstring, intl, pdo_mysql, redis
          coverage: xdebug
      - name: Validate composer.json
        run: composer validate --strict
      - name: Get Composer cache directory
        id: composer-cache
        run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
      - name: Cache Composer dependencies
        uses: actions/cache@v3
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: ${{ runner.os }}-composer-
      - name: Install dependencies
        run: composer install --prefer-dist --no-progress
      - name: Copy .env
        run: cp .env.example .env
      - name: Generate key
        run: php artisan key:generate
      - name: Run PHPStan (静态分析)
        run: vendor/bin/phpstan analyse --level=6 app/
      - name: Run PHPCS (代码风格)
        run: vendor/bin/phpcs --standard=PSR12 app/
      - name: Run tests (单元测试)
        run: vendor/bin/phpunit --coverage-text
      - name: Run security check (安全扫描)
        run: vendor/bin/security-checker security:check composer.lock
  build_and_deploy:
    needs: [test_and_lint]  # 依赖测试阶段通过
    if: github.ref == 'refs/heads/main'  # 仅 main 分支执行部署
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker Image
        run: |
          docker build -t your-app:${{ github.sha }} .
          docker tag your-app:${{ github.sha }} your-registry/your-app:latest
      - name: Push to Container Registry
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - run: docker push your-registry/your-app:latest
      - name: Deploy to Production
        run: |
          # 假设你有一个部署脚本来更新K8s或服务器
          ssh deployer@your-server "cd /var/www/app && git pull && docker-compose up -d"

GitLab CI/CD + Deployer 部署(适合 PHP 传统项目)

项目根目录创建 .gitlab-ci.yml

stages:
  - test
  - deploy
variables:
  COMPOSER_CACHE_DIR: '$CI_PROJECT_DIR/.composer-cache'
cache:
  paths:
    - vendor/
    - .composer-cache/
before_script:
  - apt-get update -qq && apt-get install -y -qq git unzip
  - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
  - composer install --prefer-dist --no-ansi --no-interaction --no-progress
test:phpunit:
  stage: test
  script:
    - cp .env.ci .env
    - php artisan key:generate
    - php artisan migrate --force
    - ./vendor/bin/phpunit --coverage-text --colors=never
  only:
    - main
    - develop
test:phpstan:
  stage: test
  script:
    - ./vendor/bin/phpstan analyse app/ --level=6 --no-progress
  only:
    - main
    - develop
deploy:staging:
  stage: deploy
  script:
    - composer install --prefer-dist --no-dev --optimize-autoloader
    - php artisan optimize
    # 使用 Deployer 或其他部署工具
    - php deployer.phar deploy staging
  only:
    - develop
  environment:
    name: staging
    url: https://staging.your-site.com
deploy:production:
  stage: deploy
  script:
    - composer install --prefer-dist --no-dev --optimize-autoloader
    - php artisan optimize
    - php deployer.phar deploy production
  only:
    - main
  when: manual  # 生产环境需要手动触发
  environment:
    name: production
    url: https://your-site.com

配合 deployerdeploy.php 配置文件(示例):

<?php
namespace Deployer;
require 'recipe/laravel.php'; // 如果是Laravel项目
// 配置
set('repository', 'git@gitlab.com:your/project.git');
set('git_tty', true);
set('shared_files', ['.env']);
set('shared_dirs', ['storage']);
set('writable_dirs', ['storage', 'bootstrap/cache']);
// 服务器
host('production')
    ->hostname('your-server-ip')
    ->user('deploy')
    ->port(22)
    ->forwardAgent()
    ->multiplexing(true)
    ->addSshOption('UserKnownHostsFile', '/dev/null')
    ->set('deploy_path', '/var/www/app');

关键实践与注意事项

环境变量管理

  • 永远不要在代码仓库中保留 .env 文件(.gitignore 排除)。
  • 在 CI/CD 平台(GitHub Secrets / GitLab Variable)中存储数据库密码、API Key 等敏感信息。
  • 部署时通过脚本生成或下载 .env 文件。

数据库迁移

  • 在测试/部署阶段执行 php artisan migrate
  • 生产环境迁移必须谨慎,建议使用自动化回滚脚本,且最好在无流量时段执行。
  • 考虑是否使用 --force 参数,以及是否在 deploy 的不同步骤执行。

缓存与优化

  • 在部署生产时执行:php artisan optimize (Laravel),php artisan config:cacheroute:cacheview:cache
  • 注意:配置缓存后,.env 修改不会生效,需重新执行。

零停机部署

  • 方案一(传统):使用 deployer 创建软链接,新版本部署在 releases/ 目录下,完成后将 current 链接指向新版本。
  • 方案二(容器化):使用 Docker + 负载均衡,先启动新容器,旧容器保留,待健康检查通过后移除旧容器。
  • 方案三(K8s):RollingUpdate 策略,逐步替换 Pod。

回滚策略

  • 在部署脚本中保留回滚能力(deployer 原生支持 rollback)。
  • CI/CD 流水线中为部署任务添加手动确认步骤(特别是生产环境)。

安全性

  • 在 CI 中使用 security-checkersymfony 的安全检查工具扫描依赖漏洞。
  • 限制 CI/CD 触发条件(仅 main 分支可部署生产)。
  • 使用 SSH Keys / Deploy Tokens 而不是密码。

针对不同 PHP 框架的注意点

框架 额外 CI/CD 步骤
Laravel artisan migrateartisan optimizeartisan passport:install(如果用到)
Symfony cache:clearassets:installdoctrine:migrations:migrate
ThinkPHP 路由缓存,配置缓存
WordPress 通常不需要复杂CI/CD,重点在主题/插件测试
纯PHP 关注静态分析 + 单元测试

进阶:蓝绿部署与金丝雀发布

如果项目规模较大,可以:

  1. 蓝绿部署

    • 准备两套完全相同的环境(蓝和绿)。
    • 新版本部署到非活跃环境,测试通过后切换流量。
    • 切换失败可快速切回。
  2. 金丝雀发布

    • 新版本先部署到少量实例(如1台服务器)。
    • 监控几分钟,如果无异常再逐步全量部署。
    • 需要配合负载均衡(如 Nginx + upstream)或 K8s Service。

最佳实践清单

  1. ✅ 统一开发、测试、生产环境(Docker 或 Vagrant)。
  2. ✅ 每次代码提交都自动触发测试。
  3. ✅ 代码质量检查(PHPStan级别≥5,代码规范PHPCS)。
  4. ✅ 单元测试覆盖核心业务逻辑。
  5. ✅ 生产部署使用“手动触发” + “回滚按钮”。
  6. ✅ 敏感信息用 CI/CD 的 Secrets 功能。
  7. ✅ 日志与监控(部署后自动检查 200 状态码、日志错误率)。

快速上手建议

小型项目:GitHub Actions + 直接 SSH 部署。 中型项目:GitLab CI + Docker Compose + 多环境。 大型/企业级:K8s + GitOps (ArgoCD/Flux) + 蓝绿/金丝雀。

选择方案时,平衡“自动化程度”与“团队维护成本”,先跑通简版再逐步完善。

抱歉,评论功能暂时关闭!