如何将工件传递到另一个阶段?

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

如果要在不同阶段的作业之间传递工件,我们可以使用 dependenciesartifacts 来传递工件,如 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/

【讨论】:

以上是关于如何将工件传递到另一个阶段?的主要内容,如果未能解决你的问题,请参考以下文章

将工件从一个 Ivy 存储库发布/复制到另一个存储库

如何将时间戳信息添加到 Maven 工件?

AWS CodePipeline:如何使 CodeBuild 构建的 ECR 映像作为剩余阶段的工件?

如何停止 Maven 的验证阶段重建工件?

Gitlab:构建后如何在后续作业中使用工件

如何在 gitlab 中的作业之间移动 jar 文件?