假设您有以下管道:
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
我会错过某些东西吗,还是没有办法实现这种行为?
答案 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
在各种故意的失败条件下,会产生以下管道状态:
从逻辑上讲,这表明无论作业B成功还是失败,如果作业A成功,作业C都会运行。此外,故障状态保留在整个管道中。
答案 1 :(得分:1)
需要 DAG 字段可用于有条件地执行清理(作业 C
),如果作业 B
失败或成功,但不会因为作业 A
失败而被跳过。
这可能会随着 GitLab 13.11(2021 年 4 月)发生变化
<块引用>GitLab CI/CD 中的有向无环图 (DAG) 允许您使用 needs
语法将作业配置为早于其阶段开始(一旦相关作业完成)。 >
我们还有 rules
、only
或 except
关键字,用于确定是否将作业添加到管道中。
遗憾的是,如果您将 needs
与这些其他关键字结合使用,当依赖作业未添加到管道时,您的管道可能会失败。
在此版本中,我们将 optional
关键字添加到 DAG 作业的 needs
语法中。
optional
但不存在于管道中,则 needs
作业将忽略它。optional
并且存在于管道中,则 needs
作业会在开始之前等待它完成。这使得将 rules
、only
和 except
与 DAG 日益流行的安全结合起来变得更加容易。
参见 Documentation 和 Issue。
答案 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)
条件的作业的技术无条件运行。