composer如何在GitHub Actions中缓存composer依赖以加速workflow?(actions/cache配置)

1次阅读

缓存 vendor/ 目录多数时候是错的,因 composer autoloader 硬编码绝对路径导致 ci 重建后类加载失败;应缓存 ~/.composer/cache/ 并用 composer.lock hash 与 php 版本构建 key。

composer如何在GitHub Actions中缓存composer依赖以加速workflow?(actions/cache配置)

为什么 actions/cache 缓存 vendor/ 多数时候是错的

直接缓存 vendor/ 目录看似最直觉,但实际会频繁失效甚至引发运行时错误。Composer 的 autoloader 生成路径(如 vendor/composer/autoload_classmap.php)里硬编码了本地绝对路径,CI 环境重建后路径变化,导致类加载失败——错误信息通常是 Class not foundrequire(): failed to open stream

真正该缓存的是 Composer 自身的下载产物和构建中间态:

  • ~/.composer/cache/:含已下载的包 zip、dist tarball、metadata(含哈希校验)
  • vendor/ 不缓存,每次用 composer install --no-interaction --prefer-dist 重建
  • 缓存 key 必须包含 composer.lock 的 hash,否则 lock 文件一变,旧缓存就成毒药

正确的 cache key 构建方式:锁定 composer.lock + PHP 版本

key 不光要反映依赖内容,还得绑定 PHP 大版本,因为不同 PHP 版本下 composer install 可能启用不同 dist 分支或跳过不兼容包。

gitHub Actions 中推荐这样写 key:

composer-${{ hashFiles('**/composer.lock') }}-php-${{ matrix.php-version }}

注意点:

  • hashFiles() 必须显式指定路径,**/composer.lock 能覆盖子目录(如 api/composer.lock),但若项目有多个 lock 文件,得手动拆开缓存
  • 别用 ${{ runner.os }} 做 key 后缀——linux/macosvendor/ 结构一致,没必要区分
  • 避免用 composer.json hash:它不决定实际安装内容,lock 才是唯一真相

workflow 中 cache action 的典型位置与参数

actions/cache@v4 必须放在 composer install 之前,且紧挨着 composer install 步骤,中间不能插其他可能修改缓存目录的操作。

关键配置项:

  • path: ~/.composer/cache:这是 Composer 默认缓存路径,不要改成 vendor/./cache
  • key 按上一节构造,restore-keys 可加一个宽松 fallback,比如 composer-${{ hashFiles('**/composer.lock') }}-,用于 lock 文件微调后的部分命中
  • PHP 必须先 setup(用 shivammathur/setup-phpactions/setup-php),否则 ~/.composer/cache 可能不存在或权限异常

示例片段:

- name: Cache Composer dependencies   uses: actions/cache@v4   with:     path: ~/.composer/cache     key: composer-${{ hashFiles('**/composer.lock') }}-php-${{ matrix.php-version }}

遇到缓存未命中却没报错?检查这三处

缓存“静默失效”比报错更麻烦,常见于:

  • composer.lock 文件被 git 忽略或未提交——hashFiles() 返回空字符串,所有 key 都变成 composer--php-8.2,全项目共用一个缓存,互相污染
  • workflow 中用了 composer update:它会改写 lock 文件,导致后续 install 的 key 完全不匹配,必须确保 CI 只跑 install
  • PHP 版本 matrix 写成 8.x 这种模糊值:matrix.php-version 实际解析为 8.2.12,但 key 里写的是 8.x,hash 对不上

调试技巧:在 cache 步骤后加一行 ls -la ~/.composer/cache/files/,看目录是否真有内容;再加 cat composer.lock | sha256sum 对照 key 中的 hash 值。

缓存逻辑本身简单,但 key 的稳定性、lock 文件的权威性、以及 PHP 环境的一致性,三者缺一不可。少一个,缓存就从加速器变成定时雷。

text=ZqhQzanResources