1. 概述
GitLab 为了提升 CI/CD 流水线的安全性、可靠性和执行效率,默认对不同阶段(stage)和任务(job)进行了隔离。每个任务都在一个独立环境中运行,避免任务之间产生意外干扰。这也意味着在一个阶段中生成的文件,默认不会自动传递到后续阶段中。
本篇文章将介绍如何使用 GitLab 的 artifacts(制品) 机制,在不同阶段之间传递数据。
2. 基本概念
在 GitLab CI/CD 中,跨任务传递制品是一个两步过程:
- 一个任务生成制品(artifacts)
- 另一个任务下载并使用这些制品
这就形成了任务之间的依赖关系:任务 B 的成功执行依赖于任务 A 成功生成制品。
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
在这个例子中:
job1
和job2
都生成了task1.txt
和task2.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
在这个配置中:
job2
和job3
都依赖job1
- GitLab 会并行执行
job2
和job3
,从而提升流水线执行效率
⚠️ 注意: 虽然任务并行执行,但计费时仍会按每个任务的实际运行时间累加。
5. 使用 API 显式下载制品
除了通过 dependencies
和 needs
自动下载制品,你还可以使用 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 下载
job1
和job2
的制品 - 解压并读取文件内容
这种方式适用于需要更精细控制下载行为的场景,比如:
- 同时下载多个任务的制品
- 根据条件选择性下载
- 避免文件覆盖问题
6. 小结
✅ 本文介绍了三种在 GitLab CI/CD 流水线中传递制品的方式:
方法 | 是否自动下载制品 | 是否支持并行执行 | 适用场景 |
---|---|---|---|
dependencies |
✅ 是 | ❌ 否 | 简单依赖,按阶段顺序执行 |
needs |
✅ 是 | ✅ 是 | 提升执行效率,跨阶段并行 |
API 显式下载 | ❌ 否 | ✅ 是 | 精细控制下载行为 |
💡 使用建议:
- 优先使用
needs
实现任务并行,提升流水线执行效率 - 如果有复杂下载逻辑,可以结合 API 实现
- 注意文件覆盖问题,避免因同名文件导致意料之外的结果
如需查看完整示例代码,可前往 GitHub 仓库。