GitLab CI中Laravel测试失败主因是环境未对齐:PHP版本不符、必需扩展缺失、MySQL服务未就绪或健康检查缺失、.env未生成及配置未重载,四者占失败原因80%。

GitLab CI 跑不起来 Laravel 测试?大概率不是代码问题,而是环境没对齐——PHP 版本、扩展缺失、数据库服务未就绪、.env 未生成这四点占了 80% 的失败原因。
为什么 php artisan test 在 GitLab CI 里报错找不到 APP_KEY 或 DB_CONNECTION
本地跑得通,CI 里直接报 Illuminate\Database\QueryException 或 RuntimeException: No application encryption key has been specified,本质是 Laravel 启动前缺少初始化步骤。
-
.env文件不会被 Git 跟踪,CI 环境里必须手动复制或生成:用cp .env.example .env+php artisan key:generate --no-interaction -
DB_CONNECTION默认是mysql,但 CI 里没启动 MySQL 服务;要么改用sqlite(DB_DATABASE=:memory:),要么在services块中声明mysql:8.0 - 别依赖
.env.testing—— GitLab CI 不自动加载它,得显式用APP_ENV=testing+php artisan config:clear确保配置重载
composer install 失败:扩展缺失或版本锁死
常见报错如 The requested PHP extension mbstring is missing 或 Your lock file does not contain a compatible set of packages,说明 runner 环境和本地开发不一致。
- GitLab Runner 默认用系统 PHP(常是 7.4 或 8.0),而 Laravel 10+ 要求 PHP 8.1+;必须在 job 中显式指定:
image: php:8.2-cli - 用
shivammathur/setup-php@v2这类 GitHub Actions 动作不适用于 GitLab CI;GitLab 需改用before_script安装扩展:docker-php-ext-install mbstring pdo_mysql curl -
composer install --no-dev在测试阶段会跳过phpunit,导致php artisan test找不到命令;测试 job 必须保留--no-interaction但不能加--no-dev
MySQL 服务启动后连接超时:端口、用户、健康检查没配对
即使写了 services: mysql:8.0,job 里仍报 SQLSTATE[HY000] [2002] Connection refused,问题出在服务就绪时机和权限上。
- GitLab 的
services是并行启动的,Laravel job 可能比 MySQL 快几毫秒;必须加等待逻辑:while ! mysqladmin ping -hmysql --silent; do sleep 1; done - MySQL 8.0 默认用
caching_sha2_password认证插件,PHP PDO 不兼容;需在 service 配置里加command: ['--default-authentication-plugin=mysql_native_password'] -
MYSQL_ROOT_PASSWORD和DB_PASSWORD必须一致,且DB_HOST必须写成mysql(service 别名),不能写localhost或127.0.0.1
Artifacts 传不过去:路径没匹配或 stage 顺序错乱
想把 storage/logs/test.log 传到 GitLab UI 查看,但下载按钮灰掉,或者提示 No artifacts found。
-
artifacts: paths:是相对当前 job 工作目录的路径,不是项目根目录;如果 job 运行在/builds/group/project下,就得写storage/logs/,而不是./storage/logs/ - 只有成功完成的 job 才上传 artifacts;若测试失败(exit code ≠ 0),默认不传;加
artifacts: when: always强制上传 - 构建产物(如
public/build/)要给 deploy job 用,必须确保 build job 和 deploy job 在同一stage后续阶段,且 deploy job 声明needs: [build_job]显式依赖
最易被忽略的是 MySQL 的认证插件和 artifacts 的 when 行为——前者让连接看起来“随机失败”,后者让日志根本看不到,排查时容易误判成代码问题。


















