新手PHP项目CI/CD应首选GitHub Actions:无需配置Runner,Ubuntu环境预装PHP扩展,.github/workflows/main.yml放即生效,本地可用actionlint验证语法,调试成本远低于GitLab CI的Alpine容器环境。

PHP 项目做 CI/CD 不需要先学完所有 DevOps 工具链,关键是从「能跑通一次自动化测试 + 部署」开始。真正卡住人的从来不是概念,而是 .gitlab-ci.yml 里某一行权限报错、composer install 在容器里找不到扩展、或者 phpunit 因环境差异漏掉一个 bootstrap.php 路径。
怎么选第一个 CI 平台:GitHub Actions 还是 GitLab CI?
新手直接用 GitHub Actions,理由很实际:main.yml 放进 .github/workflows/ 就生效,不用配 Runner,也不用开新账号或建私有 Runner 实例。
GitLab CI 虽然配置更统一(.gitlab-ci.yml 全在仓库里),但本地调试困难——你没法轻易复现 gitlab-runner 启动的 Alpine 容器环境,出错时经常卡在 PHP extension 'mbstring' not loaded 这类基础问题上。
-
GitHub Actions默认用 Ubuntu runner,PHP 扩展基本预装全,php -m | grep mbstring大概率直接有 - 想本地验证
.yml语法?用 actionlint 命令行工具,不依赖 GitHub - 别一上来就写部署到生产服务器的 job——先确保
composer install && vendor/bin/phpunit能绿
为什么 composer install 总失败?三个高频原因
CI 环境不是你本地的 MAMP 或 Docker Desktop,composer install 报错十次里有七次和这三件事有关:
立即学习“PHP免费学习笔记(深入)”;
- 没加
--no-interaction --prefer-dist --optimize-autoloader参数:交互式提示、源码包下载、未优化自动加载都会导致超时或权限拒绝 -
COMPOSER_HOME没设或缓存路径不可写:GitHub Actions 默认不持久化~/.composer/cache,得显式用actions/cache@v4缓存vendor/或~/.composer/cache - 用了
require-dev里的扩展(比如phpunit/phpunit),但 CI 镜像 PHP 版本太低:检查php --version输出,再核对phpunit的composer.json要求
示例修正写法:
steps:
- uses: actions/checkout@v4
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
- name: Install dependencies
run: composer install --no-interaction --prefer-dist --optimize-autoloader
env:
COMPOSER_MEMORY_LIMIT: -1
phpunit 在 CI 里跑不通?先关掉这些默认行为
本地能过、CI 报 Class 'Tests\TestCase' not found 或 Cannot declare class, because the name is already in use,大概率是 autoloader 或配置没对齐。
- 确认
phpunit.xml里bootstrap指向的是tests/bootstrap.php,且该文件存在并 require 了vendor/autoload.php - 删掉
phpunit.xml里的<logging>区块:CI 日志输出慢,XML/coverage 报告生成容易超时 - 不要用
./vendor/bin/phpunit --colors=never:某些镜像里--colors参数不被识别,直接去掉最稳 - 如果用 Laravel,
APP_ENV=testing必须显式设在 env 下,不能只靠.env.testing—— CI 不读 .env 文件
部署到服务器前,必须验证的三件事
CI 流水线最后一环不是 ssh user@host 'cd /var/www && git pull',那只是“伪自动化”。真要上线,得过这三关:
-
rsync同步后,检查目标目录下vendor/autoload.php是否可读(权限常为 600,Web 服务器用户读不了) - 运行
php artisan config:clear(Laravel)或php app/console cache:clear(Symfony)前,确认 CLI PHP 和 Web PHP 是同一版本、同套扩展 - 部署脚本末尾加个健康检查:
curl -f http://your-app.com/health || exit 1,失败就中断,不发告警也比静默挂掉强
复杂点在于:不同环境的 opcache.enable_cli、date.timezone、memory_limit 往往不一致,而 CI 流水线本身不会暴露这些。最容易被忽略的,是 Web 服务器用户(如 www-data)对 storage/logs 目录没有写权限——它不会在 CI 里报错,但上线第一秒就 500。



















