Gitlab-CI:指定如果作业A失败,则作业C应该在作业B之后运行

时间:2020-10-05 08:53:53

标签: gitlab gitlab-ci

假设您有以下管道:

Job A (deploy) -> Job B (test) -> Job C (remove test deployment)

管道应部署测试映像,并在成功部署后对其进行测试。测试结束后,无论测试输出如何,我都希望运行清理脚本,但前提是部署了测试映像(作业A)。

总结一下:我希望Gitlab仅在作业A成功的情况下执行作业C,但在作业B之后

不起作用的东西:

  • when: on-failure(作业A或作业B可能失败,但只有作业A很重要)
  • when: always(也许作业A失败导致作业C失败)
  • when: on-success(需要所有工作才能成功)

我知道GitLab具有一个称为DAG Pipelines的功能,该功能允许您使用needs关键字指定对其他作业的多个依赖关系,但是遗憾的是when关键字的作用域始终是所有先前的作业。因此,您无法说出类似的内容:

when:
    on-success: job-a
    always: job-b

我会错过某些东西吗,还是没有办法实现这种行为?

3 个答案:

答案 0 :(得分:1)

如果作业B失败或成功,则needs DAG字段可用于有条件地执行清理(作业C),但由于作业A失败而跳过时,则不能使用它。 / p>

创建2个符合以下布尔条件的清理作业:

  • (Job A succeeds and Job B succeeds):如果先前的所有任务都成功完成(作业A和作业B),我们可以使用when: on_success运行清理。但是,如果作业A成功而作业B失败,这将不会触发。
  • (Job A succeeds and Job B fails):为了通过未触发的清除(作业C)来规避先前的情况,我们利用了以下事实:如果作业B失败,则意味着作业A在管道中成功。通过创建重复的清除任务并在作业B和needs上指定when: on_failure标签,清除任务将仅在作业A成功且作业B失败时运行。

重申一下:如果(Job A succeeds and Job B succeeds)(Job A succeeds and Job B fails)(通过布尔表达式减少等于(Job A succeeds))将运行清理作业。

一个明显的警告是,管道中现在显示2个清理作业。但是,它们是互斥的,只能执行其中一个。

这是一个示例配置:

stages:
  - deploy
  - test
  - cleanup

deploy_job:
  stage: deploy
  script:
    - echo Deployed
    - "true"
  when: always

test_job:
  stage: test
  script:
    - echo Executing tests
    - "true"
  when: on_success

# a YAML anchor reduces repetition
.cleanup_job: &cleanup_job
  stage: cleanup
  script:
    - echo Cleaned up deployment

cleanup_deployment_success:
  when: on_success
  <<: *cleanup_job

cleanup_deployment_failure:
  needs: ["test_job"]
  when: on_failure
  <<: *cleanup_job

在各种故意的失败条件下,会产生以下管道状态:

  • 管道失败Job A succeeds and Job B fails
  • 管道失败Job A fails and Job B is skipped
  • 已通过管道Job A succeeds and Job B succeeds

从逻辑上讲,这表明无论作业B成功还是失败,如果作业A成功,作业C都会运行。此外,故障状态保留在整个管道中。

答案 1 :(得分:1)

<块引用>

需要 DAG 字段可用于有条件地执行清理(作业 C),如果作业 B 失败或成功,但不会因为作业 A 失败而被跳过。

这可能会随着 GitLab 13.11(2021 年 4 月)发生变化

<块引用>

CI/CD 管道中的可选 DAG(“需要:”)作业

GitLab CI/CD 中的有向无环图 (DAG) 允许您使用 needs 语法将作业配置为早于其阶段开始(一旦相关作业完成)。 > 我们还有 rulesonlyexcept 关键字,用于确定是否将作业添加到管道中。

遗憾的是,如果您将 needs 与这些其他关键字结合使用,当依赖作业未添加到管道时,您的管道可能会失败。

在此版本中,我们将 optional 关键字添加到 DAG 作业的 needs 语法中。

  • 如果依赖作业被标记为 optional存在于管道中,则 needs 作业将忽略它。
  • 如果作业是 optional 并且存在于管道中,则 needs 作业会在开始之前等待它完成。

这使得将 rulesonlyexcept 与 DAG 日益流行的安全结合起来变得更加容易。

https://about.gitlab.com/images/13_11/optional.png -- Optional DAG ('needs:') jobs in CI/CD pipelines

参见 DocumentationIssue

答案 2 :(得分:0)

我想添加另一种选择。我目前正在寻求为 e2e-tests 实现这个确切的用例,我的偏好可能是通过使用工件来延迟测试结果的报告。设置将是这样的:

Invoke()

作业 B 将被配置为始终成功,并且仅将其发现保存为工件(例如 JUnit xml)。然后,作业 D 将发布结果,如果测试不成功,管道将在此处失败。这应该保留管道故障状态,即使作业 C 和作业 D 使用前面提到的复制具有多个 Job A (deploy) -> Job B (run test, collect results into artifact) -> Job C (undeploy) -> Job D (publish test results from artifact) 条件的作业的技术无条件运行。