1. 概述

GitLab 为了提升 CI/CD 流水线的安全性、可靠性和执行效率,默认对不同阶段(stage)和任务(job)进行了隔离。每个任务都在一个独立环境中运行,避免任务之间产生意外干扰。这也意味着在一个阶段中生成的文件,默认不会自动传递到后续阶段中

本篇文章将介绍如何使用 GitLab 的 artifacts(制品) 机制,在不同阶段之间传递数据。

2. 基本概念

在 GitLab CI/CD 中,跨任务传递制品是一个两步过程

  1. 一个任务生成制品(artifacts)
  2. 另一个任务下载并使用这些制品

这就形成了任务之间的依赖关系:任务 B 的成功执行依赖于任务 A 成功生成制品

GitLab Artifact Usage

3. 使用 dependencies 关键字

GitLab 默认会为每个任务自动下载其前面所有阶段产生的制品。但如果你希望控制这种行为,可以使用 dependencies 关键字来指定任务需要下载哪些上游任务的制品。

以下是一个典型的 .gitlab-ci.yml 配置示例:

stages:
  - stage1
  - stage2
  - stage3

job1:
  stage: stage1
  script:
    - echo "job1 - executing task1" > task1.txt
    - echo "job1 - executing task2" > task2.txt
  artifacts:
    paths:
      - task1.txt
      - task2.txt

job2:
  stage: stage2
  script:
    - cat task1.txt
    - cat task2.txt
    - echo "job2 - executing task1" > task1.txt
    - echo "job2 - executing task2" > task2.txt
  artifacts:
    paths:
      - task1.txt
      - task2.txt

job3:
  stage: stage3
  script:
    - cat task1.txt
    - cat task2.txt

在这个例子中:

  • job1job2 都生成了 task1.txttask2.txt 作为制品
  • job3 默认会下载所有前序阶段的制品,但只会保留 job2 的版本(即最后生成的版本)

注意: 如果你只想让 job3 下载 job1 的制品,可以显式设置依赖:

job3:
  stage: stage3
  dependencies:
    - job1
  script:
    - cat task1.txt
    - cat task2.txt

⚠️ 注意: 使用 dependencies 不会改变任务的执行顺序,任务仍然按阶段顺序执行。

4. 使用 needs 关键字实现更灵活的依赖控制

如果你希望更灵活地控制任务之间的执行顺序和制品依赖,可以使用 needs 关键字。

needs 支持跨阶段并行执行任务,并能指定只依赖某些特定任务的制品。

示例配置如下:

stages:
  - stage1
  - stage2
  - stage3

job1:
  stage: stage1
  needs: []
  script:
    - echo "job1 - executing task1" > task1.txt
    - echo "job1 - executing task2" > task2.txt
  artifacts:
    paths:
      - task1.txt
      - task2.txt

job2:
  stage: stage2
  needs: ["job1"]
  script:
    - echo "job2 - executing task1" > task1.txt
    - echo "job2 - executing task2" > task2.txt
  artifacts:
    paths:
      - task1.txt
      - task2.txt

job3:
  stage: stage3
  needs: ["job1"]
  script:
    - cat task1.txt
    - cat task2.txt

在这个配置中:

  • job2job3 都依赖 job1
  • GitLab 会并行执行 job2job3,从而提升流水线执行效率

⚠️ 注意: 虽然任务并行执行,但计费时仍会按每个任务的实际运行时间累加。

GitLab Pipeline - needs Keyword

5. 使用 API 显式下载制品

除了通过 dependenciesneeds 自动下载制品,你还可以使用 GitLab 提供的 REST API 显式下载某个任务的制品,从而获得更细粒度的控制。

你可以通过设置 artifacts: false 来关闭自动下载:

job3:
  stage: stage3
  needs: 
    - job: job1
      artifacts: false
    - job: job2
      artifacts: false
  script: |
    for job in job1 job2
    do
        curl --silent --location --output artifacts_$job.zip \
          "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/$CI_COMMIT_BRANCH/download?job=$job&job_token=$CI_JOB_TOKEN"
        unzip -o artifacts_$job.zip
        cat task1.txt
        cat task2.txt
    done

这个脚本做了以下几件事:

  • 使用 GitLab API 下载 job1job2 的制品
  • 解压并读取文件内容

这种方式适用于需要更精细控制下载行为的场景,比如:

  • 同时下载多个任务的制品
  • 根据条件选择性下载
  • 避免文件覆盖问题

6. 小结

✅ 本文介绍了三种在 GitLab CI/CD 流水线中传递制品的方式:

方法 是否自动下载制品 是否支持并行执行 适用场景
dependencies ✅ 是 ❌ 否 简单依赖,按阶段顺序执行
needs ✅ 是 ✅ 是 提升执行效率,跨阶段并行
API 显式下载 ❌ 否 ✅ 是 精细控制下载行为

💡 使用建议:

  • 优先使用 needs 实现任务并行,提升流水线执行效率
  • 如果有复杂下载逻辑,可以结合 API 实现
  • 注意文件覆盖问题,避免因同名文件导致意料之外的结果

如需查看完整示例代码,可前往 GitHub 仓库


原始标题:Guide to Passing GitLab Artifacts to Another Stage