1. 先立界:cache 不是 artifacts 的替代品
二者都减少重复劳动,但契约完全不同。Cache 优化的是“同一类 job 反复装依赖”的成本,命中失败时你仍应从源码重建; Artifacts 是某次 job 明确产出的、要在后续 job 或发布中使用的目录/文件。把构建结果只写进 cache 而不声明 artifacts,一旦 key 失效或 runner 更换,你可能得到不可复现的“幽灵构建”。
| 维度 | cache | artifacts |
|---|---|---|
| 主要目的 | 缩短 install / 依赖准备时间 | 在 job 之间或发布后传递构建结果 |
| 可靠性 | 尽力而为,可失效 | 由 pipeline 绑定,可下载追溯 |
| 典型内容 | node_modules、包管理器缓存 | dist/、测试报告、镜像层导出 |
2. cache:key、policy 与失效哲学
cache:key 决定“哪把钥匙开哪把锁”。常用做法是用分支、lockfile 哈希或显式 cache:key:files 绑定 package-lock.json / poetry.lock:依赖不变则命中率高,变更则自然失效避免错依赖。 policy 控制拉取/推送时机:pull-push(默认)、pull、push、null 禁用。
default:
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull-push
install_deps:
stage: build
script:
- npm ci
3. artifacts:paths、生命周期与报告
用 artifacts:paths 精确列出要上传的目录;大仓库里粗心的 **/* 会拖垮存储与下载时间。 expire_in 设定保留时长(如 1 week、3 days),平衡可追溯与成本。 artifacts:reports:junit 等可把测试结果嵌进 GitLab UI,失败时排障路径更短。
build_frontend:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
expire_in: 3 days
unit_tests:
stage: test
script:
- npm ci
- npm test -- --reporters=jest-junit
artifacts:
when: always
reports:
junit: junit.xml
paths:
- junit.xml
expire_in: 1 week
4. dependencies:默认继承与“空手进场”
默认情况下,某 job 会下载紧邻上一 stage 各 job 产出的 artifacts(具体行为以所用 GitLab 版本文档为准)。 若只需某一两个上游的构建结果,应显式列出 job 名以减少下载。若某 job 根本不需要任何上游制品(纯静态检查、独立扫描),使用 dependencies: [] 可避免无谓下载,缩短排队时间与网络开销。
lint_shell:
stage: test
dependencies: []
script:
- shellcheck scripts/**/*.sh
需要仅从部分上游 job拉取制品时,在列表中写出那些 job 名:
integration_test:
stage: test
dependencies:
- build_api
script:
- ./run_integration.sh
5. needs:跨 stage 的“近路”与真并行
仅靠 stage 顺序时,后续 stage 必须等整个前一 stage 完成。needs 让你声明 DAG:某个 job 只依赖指定上游, 上游完成即可启动,不必等同 stage 的其它慢 job。常与 artifacts 联用以缩短端到端时间。 注意与 dependencies 的组合语义:需要同时理解“何时调度”与“下载哪些制品”。
fast_feedback:
stage: report
needs:
- job: unit_tests
artifacts: true
script:
- ./aggregate_coverage.sh
6. 反模式与治理清单
- 巨型 artifacts:误把 node_modules、全量 .git 打进制品;应靠 cache / 重建策略解决。
- 把密钥写进缓存路径:缓存可能被同 key 的其他 job 读到;机密用受保护变量与 KMS/secret 管理。
- 永不 expire:存储与列表 API 压力上升;按合规设默认 TTL。
- 盲目默认依赖:每个 job 都拉全量上游制品;用 dependencies 精确裁剪。
7. 与 GitHub Actions 的对照
Actions 的 actions/cache、upload-artifact / download-artifact 与 GitLab 的 cache / artifacts 角色相近;GitLab 的 needs 对应 Actions 里 job 级 needs 与 DAG。 迁移时优先对齐契约:什么是可丢的加速层,什么是必须随构建追溯的产物。
8. 本章清单
- 为依赖安装配置 cache:key:files 与合理 policy,观察命中率与构建时间。
- 为 build / test 配置最小 artifacts:paths 与 expire_in;测试报告走 reports。
- 对不需要上游制品的 job 使用 dependencies: []。
- 在瓶颈路径上试验 needs,验证端到端时间与下载体积变化。
- 与平台约定 artifact 大小上限与清理策略,避免“流水线成功、存储爆掉”。