如何让 Gitlab CI Pipeline 始终运行某些作业而其他作业仅在合并请求时运行?

Ger*_*iks 4 continuous-integration gitlab merge-request

TL/DR: 我的目标是拥有一个 Gitlab (CE-12.4.2) 管道,它只在合并请求上执行一些作业,而其他作业始终(在合并请求和所有正常推送上)。怎么.gitlab-ci.yml看才能做到这一点?

我的用例: 我有一个运行大量作业的大管道(测试、验证、dep、构建、doc 等)。现在我已经添加了一个登台环境(使用 kubernetes)并让管道构建一个新的映像并将其部署在登台环境中。这使我可以立即打开更改后的(网络)应用程序并查看更改的行为和外观,而无需在本地检查它们。现在构建映像并将其部署到登台对于每次推送都会占用大量资源,因此我只希望在有人创建合并请求供我查看时部署到登台。

一个非常简单的例子:

install:
  script: ...

test:
  script: ...

build-image:
  script: ...
  only: [merge_requests]

deploy-staging:
  script: ...
  only: [merge_requests]
Run Code Online (Sandbox Code Playgroud)

对于所有正常推送,应执行作业installtest

对于合并-要求,工作installtestbuild-imagedeploy-staging应执行。

我尝试过的: Gitlab 具有only: [merge_requests]在作业上定义的此功能,这会导致仅在为合并请求执行管道时才执行该作业。听起来正是我正在寻找的,但有一个很大的问题。一旦将该属性应用于管道中的一个作业,该管道中没有该属性的所有其他作业将在合并请求中执行时从管道中删除。起初对我来说这似乎是一个错误,但实际上是记录在案的行为

In the above example, the pipeline contains only a test job. Since the build and deploy jobs don’t have the only: [merge_requests] parameter, they will not run in the merge request.
Run Code Online (Sandbox Code Playgroud)

为了将所有其他工作重新引入合并请求的管道,我必须申请only: [merge_requests]所有其他工作。这种方法的问题在于,现在这些常规作业不再为正常的 git-push 执行。而且我无法将这些常规作业重新引入管道以进行常规推送,因为 Gitlab 不支持only: [always]或类似的东西。

现在我也注意到only语法是弃用的候选者,人们应该更喜欢rules语法,所以我看了一下。这种方法存在多个问题:

  • 检测rules管道是否为合并请求执行的唯一方法是评估与合并请求相关的变量,例如$CI_MERGE_REQUEST_ID. 不幸的是,这些变量只有在only: [merge_requests]使用时才存在,这会重新引入上述问题。
  • 规则只允许有条件地应用其他属性,所以我仍然必须使用only,exceptwhen属性来实际从管道中删除或添加作业。不幸的是,Gitlab 不支持类似only: [never]或 的任何内容when: never,因此我无法实际删除或添加作业。

我还尝试让作业依赖于其他用途needdependencies属性,这似乎对作业是否包含在管道中没有影响。

我拼命尝试的最后一件事是始终包含所有作业,只需将它们标记为when: manual通过按下按钮手动触发。这在某种程度上有效,但非常乏味,因为部署到暂存是一个多作业过程,每个作业都需要相当长的时间才能完成。所以我会看到一个合并请求,按下第一个作业的按钮,等待 5 分钟,按下下一个按钮,再等待 5 分钟,然后才能使用暂存。对于许多小的合并请求,这会占用我很多时间,并且不是一个有效的解决方案。我也不能仅仅标记第一这些工作为手动的,因为Gitlab随后将只是跳过该作业并执行后来的乱序(再次,needs并且dependencies似乎与手动触发工作打交道时,有没有这方面的影响)。

我有点困惑的是,在网上搜索后,我发现没有人遇到同样的问题。要么我是唯一一个只想为合并请求执行某些作业而不排除所有其他作业(这似乎不太可能)的 Gitlab 用户,要么我遗漏了一些明显的东西(这似乎更有可能)。我是不是遗漏了什么,还是 Gitlab 真的不支持这个用例?

Von*_*onC 5

以前的答案

但有一个问题。此示例在创建 MR 后为每次推送启动两个管道。一为only: [branch],一为only: [merge_requests]

检查上一个GitLab 13.8(2021 年 1 月)是否有帮助:

同时使用分支和 MR 管道而不重复

以前不可能先为分支运行管道,然后在创建 MR 时切换到合并请求管道

因此,对于某些配置,如果合并请求已在分支上打开,则推送到分支可能会导致重复的管道:分支上的一个管道和合并请求的另一个管道。

现在,您可以$CI_OPEN_MERGE_REQUESTS在 CI 配置中使用新的预定义环境变量在正确的时间从分支管道切换到 MR 管道,并防止冗余管道。

https://about.gitlab.com/images/13_8/yaml_example_avoid_duplicate_pipelines.png -- 同时使用分支和 MR 管道而不重复

请参阅文档问题


rai*_*ine 2

可以向 MR 管道添加一些作业。我从这里得到了示例: https://docs.gitlab.com/ee/ci/merge_request_pipelines/index.html#exclusion-certain-jobs

总体思路:您only: [branch, merge_requests]为每个作业定义,并为部署作业用only: [merge_requests].

.only-default: &only-default
  only:
    - branches
    - merge_requests

build:
  stage: build
  tags:
    - build
  <<: *only-default
  script:
    - echo build

deploy mr:
  stage: deploy
  tags:
    - build
  only:
    - merge_requests
  script:
    - echo "deploy on MR"
Run Code Online (Sandbox Code Playgroud)

但有一个问题。此示例在创建 MR 后为每次推送启动两个管道。一为only: [branch],一为only: [merge_requests]。这就是only: [merge_requests]工作方式,它会在每次 MR 更改时启动工作。新的提交肯定是一个改变。

似乎没有解决方案可以仅针对某些事件(例如 MR 创建)启动管道。

但我认为一些解决方法是可能的:

  1. 每个管道都存在部署暂存作业
  2. 作业脚本检查是否为当前分支创建了 MR
  3. 如果创建了 MR,脚本会为此 MR 设置标签,例如“暂存部署”
  4. 如果这个标签已经存在,或者MR没有创建,则什么都不做。

GitLab API、curl 和 jq 可以帮助解决这个问题。如果我有空闲时间,我一定会尝试写它:)。