GitLab Runner Pipeline 缓存机制详解
缓存概述
在 GitLab CI/CD 流水线中,cache 用于跨作业持久化保存依赖文件或构建产物。需特别注意的是,缓存应当仅用于存储运行环境所需的依赖项,而非作为作业间传递构建产物的机制——后者应使用 artifacts 实现。
缓存配置支持全局作用域与作业作用域两种模式。当 cache 定义于流水线顶层时,所有作业均继承该配置;若作业内部未显式配置且全局也未定义,则缓存功能处于禁用状态。
1. 路径配置 paths
paths 参数用于精确指定需要缓存的文件或目录,路径基准为项目根目录,不支持超出项目范围的引用。系统变量 $CI_PROJECT_DIR 指向当前项目的工作目录。
作业级配置将覆盖全局设置。以下为典型示例:
# 全局缓存配置
cache:
paths:
- my/files
compile:
script: echo "building..."
cache:
key: compile
paths:
- build/output/
由于缓存默认在多个作业间共享存储空间,不同作业若缓存相同路径极易发生互相覆盖。解决方案是为各作业分配独立的缓存标识,即通过 cache:key 实现隔离。
2. 缓存标识 key
为缓存添加唯一标识,可基于作业名称、分支名称等维度实现精细化控制。当各作业配置不同的 key 时,GitLab 会为每个作业维护独立的缓存空间,从根本上避免冲突。
以分支维度隔离缓存:
cache:
key: ${CI_COMMIT_REF_SLUG}
基于文件变动的动态标识
通过 files 子指令可监听最多两个文件的变化,系统会自动计算其 SHA 校验和作为缓存键值的一部分:
cache:
key:
files:
- package-lock.json
- yarn.lock
prefix: ${CI_JOB_NAME}
paths:
- node_modules
prefix 参数允许将静态前缀与文件生成的动态哈希拼接。假设 package-lock.json 内容未变更,实际生成的缓存键为 test-default;若文件发生修改,则类似 test-a1b2c3d... 的形式,此时系统会创建全新的缓存条目。
3. 缓存策略 policy
默认行为为 pull-push,即作业启动时下载缓存,执行完毕后上传更新。根据场景需求可调整为以下模式:
pull:仅下载缓存,跳过上传阶段push:仅上传缓存,跳过下载阶段
典型场景为编译作业生成依赖缓存,测试作业仅读取而不回写:
stages:
- prepare
- verify
deps:
stage: prepare
cache:
key: npm-deps
paths:
- node_modules/
script:
- npm ci
jest:
stage: verify
cache:
key: npm-deps
paths:
- node_modules/
policy: pull
script:
- npx jest
4. 全局缓存实战演示
variables:
SITE_DOMAIN: demo.example.com
cache:
paths:
- dist/
stages:
- build
- verify
- release
build:
stage: build
tags: [builder]
only: [main]
script:
- npm run build
- ls dist/
lint:
stage: verify
tags: [builder]
only: [main]
script:
- echo "lint check" >> dist/report.txt
- ls dist/
ship:
stage: release
tags: [builder]
only: [main]
script:
- ls dist/
上述配置中,lint 作业对 dist/ 的修改会被写入缓存,后续 ship 作业拉取时能看到这些变更。但需注意:若多个作业并发修改同一路径,最终缓存内容将不可预测。
5. 精细化策略控制
针对编译类作业,通常无需下载历史缓存(因其职责是生成最新构建产物),可显式设置策略优化性能:
build:
stage: build
cache:
key: build-cache
paths:
- dist/
policy: push # 仅上传,不下载
script:
- npm run build
# 下游作业正常拉取
test:
stage: verify
cache:
key: build-cache
paths:
- dist/
policy: pull # 仅下载,不上传
script:
- cat dist/version.txt
若 build 作业错误配置了 policy: pull,由于首次执行时缓存尚未生成,dist/ 目录不存在,任何读取操作均会导致流水线失败。