首页 > 解决方案 > Gitlab-CI:如果作业 A 失败,则指定作业 C 应在作业 B 之后运行

问题描述

假设您有以下管道:

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

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

总结一下:我希望 Gitlab 只有在 Job A 成功时才执行 Job C ,但在 Job B 之后

不起作用的事情:

我知道 GitLab 有一个名为 DAG Pipelines 的功能,它允许您使用needs关键字指定对其他作业的多个依赖项,但遗憾的是,该when关键字始终适用于所有先前的作业。所以你不能说这样的话:

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

我错过了什么还是没有办法实现这种行为?

标签: gitlabgitlab-ci

解决方案


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

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

  • (Job A succeeds and Job B succeeds):如果之前的所有任务都成功(作业 A 和作业 B),我们可以使用when: on_success. 但是,如果 Job A 成功而 Job B 失败,则不会触发。
  • (Job A succeeds and Job B fails):为了规避前面的未触发清理(作业 C)的场景,我们利用了一个事实,即如果作业 B 失败,这意味着作业 A 在管道中成功。通过创建重复的清理任务并needs在 Job B 和 上指定一个标签when: on_failure,清理任务将仅在 Job A 成功且 Job 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

在各种故意失败条件下,会产生以下流水线状态:

  • 失败的管道作业 A 成功,作业 B 失败
  • 失败的管道作业 A 失败,作业 B 被跳过
  • 通过管道作业 A 成功,作业 B 成功

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


推荐阅读