悠悠楠杉
GitHubActions怎么缓存composer依赖
正文:
在PHP项目的持续集成(CI)流程中,Composer依赖安装往往是耗时最长的步骤之一。每次触发GitHub Actions时重新下载所有依赖,不仅浪费带宽,还会拖慢构建速度。本文将手把手教你如何通过缓存机制优化这一过程,让你的CI流程飞起来。
为什么需要缓存Composer依赖?
以Laravel项目为例,首次执行composer install可能需要下载上百个包,耗时超过1分钟。而实际上,依赖列表(composer.lock)未变化时,这些文件完全可以复用。通过缓存机制,后续构建可直接从缓存加载依赖,速度可提升80%以上。
缓存实现的核心逻辑
GitHub Actions提供了actions/cache官方Action,其原理是:
1. 根据唯一缓存键(如composer.lock的哈希值)检查是否存在缓存
2. 命中缓存时,将依赖直接还原到vendor目录
3. 未命中时正常安装依赖,并在流程结束后保存新缓存
实战代码示例
以下是一个完整的.github/workflows/ci.yml配置片段:
name: CI
on: [push, pull_request]
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Cache Composer dependencies
id: composer-cache
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress
- name: Run tests
run: php vendor/bin/phpunit
关键点解析
- 缓存路径:指定
vendor目录为缓存目标 - 缓存键生成:
- 主键:
${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}(系统+文件哈希) - 备用键:
${{ runner.os }}-composer-(允许部分匹配)
- 主键:
- 条件安装:仅当缓存未命中时执行
composer install
高级技巧
- 多工作流共享缓存
添加cache-dependency-path参数实现跨工作流共享:
- uses: actions/cache@v3
with:
path: vendor
key: global-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
global-composer-
清理过期缓存
GitHub会自动清理7天内未使用的缓存,但也可以通过API手动删除:bash gh api repos/{owner}/{repo}/actions/caches --jq '.actions_caches[] | select(.key | startswith("linux-composer")) | .id' | xargs -I{} gh api repos/{owner}/{repo}/actions/caches/{cache_id} -X DELETE监控缓存效果
在步骤中添加统计输出:
- name: Cache statistics
run: |
echo "Cache hit: ${{ steps.composer-cache.outputs.cache-hit }}"
du -sh vendor
常见问题解决方案
Q:为什么缓存没有生效?
A:检查composer.lock是否已提交到仓库,且哈希计算路径正确Q:不同PHP版本会混用缓存吗?
A:建议在缓存键中加入PHP版本:${{ runner.os }}-php${{ matrix.php-version }}-composer-...Q:缓存后构建仍很慢?
A:可能是缓存未完全命中,尝试调整restore-keys匹配范围
通过合理使用缓存机制,我们的一个中型项目构建时间从平均3分12秒降至47秒。现在就去你的GitHub Actions中实践吧!
