如何将工件传递到另一个阶段?
Posted
技术标签:
【中文标题】如何将工件传递到另一个阶段?【英文标题】:How can I pass artifacts to another stage? 【发布时间】:2016-11-03 14:31:27 【问题描述】:我想将 GitLab CI 与 .gitlab-ci.yml 文件一起使用,以使用单独的脚本运行不同的阶段。第一阶段生成一个工具,必须在稍后阶段使用该工具来执行测试。我已将生成的工具声明为工件。
现在如何在后期作业中执行该工具?正确的路径是什么,它周围会有什么文件?
例如,第一阶段构建 artifacts/bin/TestTool/TestTool.exe,该目录包含其他所需文件(DLL 和其他)。我的 .gitlab-ci.yml 文件如下所示:
releasebuild:
script:
- chcp 65001
- build.cmd
stage: build
artifacts:
paths:
- artifacts/bin/TestTool/
systemtests:
script:
- chcp 65001
- WHAT TO WRITE HERE?
stage: test
如果相关,构建和测试在 Windows 上运行。
【问题讨论】:
【参考方案1】:使用dependencies
。使用此配置测试阶段将下载在构建阶段创建的未跟踪文件:
build:
stage: build
artifacts:
untracked: true
script:
- ./Build.ps1
test:
stage: test
dependencies:
- build
script:
- ./Test.ps1
【讨论】:
终于让它工作了!这里的关键点是依赖项应该与工件一起使用。只有包含的工件才能在后续阶段使用。不用说,对上传的内容要保守。我会说使用 expire_in。否则我们最终可能会浪费大量存储空间。这些工件在构建作业/阶段/步骤中上传到 gitlab,并在测试中下载。 真的要使用依赖吗? Gitlab 文档状态为Note that artifacts from all previous stages are passed by default.
。问题是什么时候需要使用依赖。
文档很好地清除了这一点:docs.gitlab.com/ee/ci/yaml/#dependencies
@Josef 以前所有阶段的工件默认通过(不是来自以前的作业)
文档令人困惑 - 正在传递“所有先前阶段”的工件是什么意思?如果我理解正确,如果所有先前的阶段总是通过,那么所有作业的所有数据都将可用,我不需要使用“依赖项”标签。我能想到的唯一情况是,如果我不想要这种行为并且只传递一个或几个选定工作的工件。【参考方案2】:
由于默认情况下会传递所有先前阶段的工件,因此我们只需要以正确的顺序定义阶段即可。请尝试下面的示例,这有助于理解。
image: ubuntu:18.04
stages:
- build_stage
- test_stage
- deploy_stage
build:
stage: build_stage
script:
- echo "building..." >> ./build_result.txt
artifacts:
paths:
- build_result.txt
expire_in: 1 week
unit_test:
stage: test_stage
script:
- ls
- cat build_result.txt
- cp build_result.txt unittest_result.txt
- echo "unit testing..." >> ./unittest_result.txt
artifacts:
paths:
- unittest_result.txt
expire_in: 1 week
integration_test:
stage: test_stage
script:
- ls
- cat build_result.txt
- cp build_result.txt integration_test_result.txt
- echo "integration testing..." >> ./integration_test_result.txt
artifacts:
paths:
- integration_test_result.txt
expire_in: 1 week
deploy:
stage: deploy_stage
script:
- ls
- cat build_result.txt
- cat unittest_result.txt
- cat integration_test_result.txt
如果要在不同阶段的作业之间传递工件,我们可以使用 dependencies 和 artifacts 来传递工件,如 document 中所述。
还有一个更简单的例子:
image: ubuntu:18.04
build:
stage: build
script:
- echo "building..." >> ./result.txt
artifacts:
paths:
- result.txt
expire_in: 1 week
unit_test:
stage: test
script:
- ls
- cat result.txt
- echo "unit testing..." >> ./result.txt
artifacts:
paths:
- result.txt
expire_in: 1 week
deploy:
stage: deploy
script:
- ls
- cat result.txt
【讨论】:
解释得很清楚,谢谢。如果一个阶段用与前一个阶段的工件同名的名称命名工件,是否会覆盖原始工件? @MichaelOsofsky 您可以用相同的名称命名工件,原始工件不会被下一个具有相同名称的工件覆盖。下一阶段只下载前一阶段的神器,它是它的副本。我在示例中命名它们的方式不同,主要是因为单元测试和集成将并行执行。如果我们删除 .e.g 集成测试作业,所有作业将按顺序执行,那么我们可以为所有工件使用相同的名称,而不会造成任何混淆。仅供参考,我再举一个例子来更新答案。 在您的示例中,我看到您正在附加到 result.txt。如果您在作业 unit_test 中覆盖了 result.txt,我假设作业部署将永远无法访问作业构建中 result.txt 的内容。我只是要求确保我不会在我的脚本中造成这种类型的错误。 根据日志,deploy阶段会同时下载build和test阶段的result.txt,但是后面的会覆盖前面的。 顺便说一句,原始工件没有被触及,始终可以从 CI/CD -> Pipelines 下载,然后单击右侧的 Artifacts 下拉按钮,您将找到所有阶段的所有工件。 【参考方案3】:如果您希望foo/
在下一阶段可用并且它在您的.gitignore
中,您需要在创建它的阶段的artifacts
中列出它,或者如here 中所述使用untracked: true
。
这对我有用(在下一阶段没有dependencies
)
artifacts:
paths:
- foo/
expire_in: 1 hour
顺便说一句,关于:expire_in: 1 hour
部分:
我在https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2133 阅读过,没有办法让工件在管道结束时自动过期,并且默认保留期出奇地长(默认为 30 天)-因此需要基于时间来摆脱它们-请参阅https://docs.gitlab.com/ee/ci/yaml/
【讨论】:
以上是关于如何将工件传递到另一个阶段?的主要内容,如果未能解决你的问题,请参考以下文章