CI/CD中缓存路径不生效主因是COMPOSER_CACHE_DIR未透传,需在GitHub Actions、GitLab CI或Docker中显式设置该环境变量并验证非空;其优先级最高,会覆盖composer config --global配置;缓存命中还需确保PHP版本、composer.lock哈希及镜像源URL三者一致。

CI/CD里缓存路径不生效,八成是COMPOSER_CACHE_DIR没透传
很多 CI 流水线写了 cache: 块,却始终看到 composer install 反复下载包——根本不是缓存没命中的问题,而是 Composer 根本没往你指定的路径写。默认情况下,GitLab CI、GitHub Actions 的 runner 都不会自动设置 COMPOSER_CACHE_DIR,即使你挂了缓存卷或声明了路径,Composer 仍会 fallback 到 ~/.composer/cache(Linux)或 %APPDATA%\Composer\Cache(Windows),而这些路径通常不在 CI 缓存策略覆盖范围内。
必须显式设置环境变量:
- GitHub Actions:在
env:或steps[*].env:中加COMPOSER_CACHE_DIR: ${{ github.workspace }}/.composer-cache - GitLab CI:在
variables:或before_script:中运行export COMPOSER_CACHE_DIR="$CI_PROJECT_DIR/.composer-cache" - Docker 构建中:在
Dockerfile顶部用ENV COMPOSER_CACHE_DIR=/tmp/composer-cache(不能用RUN export)
设完后立刻验证:php -r "echo getenv('COMPOSER_CACHE_DIR');" 输出必须是非空绝对路径;否则后续所有配置都白搭。
cache-dir 和 COMPOSER_CACHE_DIR 别混用,后者优先级最高
CI 脚本里如果既用了 composer config --global cache-dir /some/path,又设置了 COMPOSER_CACHE_DIR 环境变量,Composer 会直接忽略前者——COMPOSER_CACHE_DIR 是硬编码最高优先级,连全局配置都压不住它。这导致你查 composer config --global cache-dir 显示的是旧值,但实际行为完全由环境变量驱动。
建议统一用环境变量方式,原因有三:
- 无需写入用户配置文件(
~/.composer/config.json),避免多 job 并发写冲突 - 进程级生效,退出即失效,更符合 CI 一次构建、隔离运行的语义
- 路径可动态拼接,比如
COMPOSER_CACHE_DIR=$HOME/.composer-cache-$PHP_VERSION,天然支持多 PHP 版本共存
若已误配了全局 cache-dir,先清理:composer config --global --unset cache-dir,再上环境变量。
缓存 key 必须包含 composer.lock 哈希和镜像源一致性
即使路径对了、变量也透传了,缓存仍可能 0% 命中。常见原因是 key 设得太宽泛。例如 GitHub Actions 中只用 ${{ runner.os }}-php-${{ matrix.php-version }},没绑定 composer.lock 内容,一旦 lock 文件变,旧缓存就被跳过——但更隐蔽的问题是:镜像源地址也参与缓存校验。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
如果你本地开发用阿里云镜像 https://mirrors.aliyun.com/composer/,而 CI 脚本没显式 composer config --global repo.packagist composer https://mirrors.aliyun.com/composer/,那么即使 lock 文件完全一样,Composer 也会拒绝复用缓存(元数据 hash 不匹配)。
安全的 key 写法示例:
- GitHub Actions:
${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}-${{ env.COMPOSER_REPO_URL || 'default' }} - GitLab CI:
composer-cache-$CI_COMMIT_REF_SLUG-${CI_JOB_NAME}-$(sha256sum composer.lock | cut -d' ' -f1)
注意:镜像源 URL 必须与本地开发一致,否则缓存虽存在,却因校验失败被静默丢弃。
缓存目录权限和生命周期容易被忽略
CI 构建常以 root 或无特权用户运行,而缓存目录若没提前创建或权限不对,Composer 会静默退回到默认路径,且不报错。典型现象是:du -sh $(composer config --global cache-dir) 显示只有几 MB,但 du -sh ~/.cache/composer 却占满磁盘。
必须确保三点:
- 缓存目录在命令执行前已存在:
mkdir -p $COMPOSER_CACHE_DIR(Bash)或New-Item -ItemType Directory -Path $env:COMPOSER_CACHE_DIR -Force(PowerShell) - 属主和权限匹配运行用户:Linux 上
chown $USER:$USER $COMPOSER_CACHE_DIR && chmod 755 $COMPOSER_CACHE_DIR - 缓存卷必须持久化:Docker 构建时用
-v $(pwd)/.composer-cache:/tmp/composer-cache,别只靠COPY或临时目录
最后提醒:缓存不是越久越好。cache-files-ttl 默认 6 个月,但在 CI 中建议缩短到 30 天(composer config --global cache-files-ttl 2592000),避免长期积压过期包占用空间。

















