第41章|GitLab CI 缓存与制品:cache、artifacts、dependencies

流水线如果只算“跑没跑通”,往往漏掉一半工程:时间花在哪、产物怎么传、缓存会不会骗人。 本章把三个关键词拆成可操作的模型:cache车间旁的备件库(可 miss、可共享、不该当真相来源); artifacts贴上条码的交接箱(跟 pipeline 走、可下载、可过期); dependencies 则决定开箱时拿哪几箱的货。再配上 needs 的预告,你就能画出一条又快又可追溯的 DAG。

cache

加速重复工作

  • key / policy
  • key:files
  • runner-local vs shared
artifacts

可传递产物

  • paths · expire_in
  • reports (junit …)
  • size & security
graph

dependencies & needs

  • 默认拉取前一 stage
  • dependencies: []
  • needs 跨 stage 并行

1. 先立界:cache 不是 artifacts 的替代品

二者都减少重复劳动,但契约完全不同Cache 优化的是“同一类 job 反复装依赖”的成本,命中失败时你仍应从源码重建; Artifacts 是某次 job 明确产出的、要在后续 job 或发布中使用的目录/文件。把构建结果只写进 cache 而不声明 artifacts,一旦 key 失效或 runner 更换,你可能得到不可复现的“幽灵构建”。

Cache vs artifacts (different contracts) Best-effort acceleration vs explicit hand-off for this pipeline pipeline timeline → install build test package cache store shared key · may miss pull / push per job artifacts (explicit bundles) Uploaded to GitLab · downloaded by later jobs · expire_in applies dist/ junit.xml image.tar (watch size)
图 1:cache 挂在流水线旁做“加速”;artifacts 是 job 之间盖章交接的制品。职责不要混。
维度 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(默认)、pullpushnull 禁用。

default:
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
    policy: pull-push

install_deps:
  stage: build
  script:
    - npm ci
Runner 视角:缓存往往落在 runner 可访问的存储上(实现因部署而异)。不要假设“永远命中”,也不要把机密放进 cache paths; 也不要缓存不可复现或与 commit 强绑定的产物当唯一真相——那是 artifacts 或 registry 的职责。

3. artifactspaths、生命周期与报告

artifacts:paths 精确列出要上传的目录;大仓库里粗心的 **/* 会拖垮存储与下载时间。 expire_in 设定保留时长(如 1 week3 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
Artifact lifecycle (simplified) job produces local workspace upload (GitLab) bound to job + pipeline later job downloads dependencies / needs expire_in GC after TTL Use reports:* for test insights; keep paths minimal for transfer cost.
图 2:制品随 job 上传、被后续 job 拉取,最终被过期策略回收——整条链可审计。

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
Stage barrier vs needs (DAG) A) Stages only fast job slow job Next stage waits for BOTH downstream B) needs: pick upstream fast job slow job early consumer waits only for fast needs 缩短关键路径;dependencies 控制下载哪些 artifacts。两者搭配才能又快又省带宽。
图 3:纯 stage 时“慢队友”拖住全队;needs 让依赖明确的 job 先走一步。
Guardrails (size · secrets · TTL) Oversized artifact Bloats upload + every downstream fetch Prefer registry layers / slim dist/ Secrets in cache paths Shared key may leak across jobs Use CI secrets + protected refs No expire_in Storage + UI cost creep Default TTL per project policy
图 4:三类常见“翻车点”——用工程政策与架构选型一起挡住。

6. 反模式与治理清单

  • 巨型 artifacts:误把 node_modules、全量 .git 打进制品;应靠 cache / 重建策略解决。
  • 把密钥写进缓存路径:缓存可能被同 key 的其他 job 读到;机密用受保护变量与 KMS/secret 管理。
  • 永不 expire:存储与列表 API 压力上升;按合规设默认 TTL。
  • 盲目默认依赖:每个 job 都拉全量上游制品;用 dependencies 精确裁剪。

7. 与 GitHub Actions 的对照

Actions 的 actions/cacheupload-artifact / download-artifact 与 GitLab 的 cache / artifacts 角色相近;GitLab 的 needs 对应 Actions 里 job 级 needs 与 DAG。 迁移时优先对齐契约:什么是可丢的加速层,什么是必须随构建追溯的产物。

8. 本章清单

  1. 为依赖安装配置 cache:key:files 与合理 policy,观察命中率与构建时间。
  2. 为 build / test 配置最小 artifacts:pathsexpire_in;测试报告走 reports
  3. 对不需要上游制品的 job 使用 dependencies: []
  4. 在瓶颈路径上试验 needs,验证端到端时间与下载体积变化。
  5. 与平台约定 artifact 大小上限与清理策略,避免“流水线成功、存储爆掉”。
← 上一章:规则与触发 下一章:安全与合规 →

web · 轻松学习