GitLab CI配置多缓存时全局缓存未生效,如何在构建阶段启用全局缓存
原配置全局缓存不生效的核心原因
- 变量解析时机错配:你在
before_script中导出的GRADLE_USER_HOME变量,需要在作业启动、脚本执行阶段才会被加载;但GitLab CI的缓存路径解析、缓存拉取动作,是在before_script执行之前就完成的。此时$GRADLE_USER_HOME还未被定义,全局缓存配置里写的$GRADLE_USER_HOME/caches、$GRADLE_USER_HOME/wrapper路径会解析为空,根本匹配不到磁盘上的实际文件,自然没法正常存取Wrapper和依赖缓存。 - 配置完全覆盖:GitLab CI中,作业级别的自定义
cache配置会完全覆盖全局层级定义的cache配置,不会自动做规则合并。你在build、test作业内单独写了本地缓存配置,直接把全局定义的公共缓存规则完全替换掉了,这两个作业从执行开始就没加载过全局缓存。 - 结构不支持多缓存共存:单作业单个缓存的配置形式,没法同时承载两套key规则、生命周期完全不同的缓存——全局缓存需要跨分支共享,本地构建缓存需要按分支隔离,硬把两类缓存的路径塞到同一个key下,会导致缓存内容混存,既没法按分支隔离编译输出,也没法跨分支共享公共依赖。
调整方案
- 将
GRADLE_USER_HOME的定义提前到全局variables块,保证缓存解析、脚本执行全阶段都能读取到正确的绝对路径,从根源上解决变量未定义导致的路径匹配失败问题。 - 利用GitLab CI 14.0+支持的单作业多缓存能力,将原有的单个
cache配置改为caches数组,数组内每一项都是独立的缓存规则,拥有独立的key、策略、路径,实现两类缓存完全独立存取。 - 按作业所处阶段匹配缓存策略:首个执行的构建类作业对两类缓存都采用
pull-push策略,既拉取历史缓存,也将新生成的缓存内容推回;后续测试类作业对两类缓存都采用pull策略,仅拉取历史缓存即可,减少重复推送的存储流量。
修正后完整配置
image: name: gradle:jdk11 # 全局变量提前定义,全阶段可读取 variables: GRADLE_USER_HOME: "${CI_PROJECT_DIR}/.gradle_home" before_script: - mkdir -p $GRADLE_USER_HOME # 提前创建缓存目录,避免文件写入失败 # 隐藏作业仅用于存储全局缓存锚点,不会被流水线执行 .cache_global: &cache_global key: gradle_global_cache # 关联构建脚本,脚本变更时自动刷新全局缓存 files: - build.gradle - settings.gradle paths: - $GRADLE_USER_HOME/caches - $GRADLE_USER_HOME/wrapper build: stage: build script: ./gradlew assemble # 单作业多缓存配置:同时加载独立的全局缓存、本地构建缓存 caches: # 全局公共缓存:构建阶段拉取+推送新下载的依赖 - <<: *cache_global policy: pull-push # 本地构建缓存:按分支存储编译输出,供后续阶段复用 - key: "local-build-${CI_COMMIT_REF_NAME}" policy: pull-push paths: - build - .gradle test: stage: test script: ./gradlew check caches: # 全局公共缓存:测试阶段仅拉取即可,无需重复推送 - <<: *cache_global policy: pull # 本地构建缓存:仅拉取build阶段输出的编译产物 - key: "local-build-${CI_COMMIT_REF_NAME}" policy: pull paths: - build - .gradle
生效效果
调整后Gradle不会再每次重新下载Wrapper组件:只要build.gradle、settings.gradle无变更,就会从全局缓存中读取已经下载好的Wrapper发行版和公共依赖;同时build阶段编译生成的build目录产物,会通过本地缓存传递给test阶段,减少test阶段的重复编译耗时。
内容的提问来源于stack exchange,提问作者mreiterer
相关产品推荐
相关产品推荐

