在 GitLab CI 中,合并请求的目标分支是不是有变量?

Posted

技术标签:

【中文标题】在 GitLab CI 中,合并请求的目标分支是不是有变量?【英文标题】:In GitLab CI, is there a variable for a Merge Request's target branch?在 GitLab CI 中,合并请求的目标分支是否有变量? 【发布时间】:2019-03-15 17:25:32 【问题描述】:

在我的管道中,我希望仅当合并请求目标分支是某个分支(例如 master 或 release)时才运行作业。

这可能吗?

我已经阅读了https://docs.gitlab.com/ee/ci/variables/,除非我遗漏了什么,否则我看不到任何有用的东西。

【问题讨论】:

【参考方案1】:

更新:2019-03-21

GitLab 从 11.6 版开始就有用于合并请求信息的变量(https://docs.gitlab.com/ce/ci/variables/ 请参阅以 CI_MERGE_REQUEST_ 开头的变量)。但是,这些变量仅在 merge request pipelines 中可用。(https://docs.gitlab.com/ce/ci/merge_request_pipelines/index.html)

要为合并请求配置 CI 作业,我们必须设置:

only: 
  - merge_requests

然后我们可以在这些作业中使用CI_MERGE_REQUEST_* 变量。

这里最大的缺陷是 only: merge_request 的行为与正常的 only/except 参数完全不同。

常用only/except参数: (https://docs.gitlab.com/ce/ci/yaml/README.html#onlyexcept-basic)

    only 定义了作业将运行的分支和标签的名称。 except 定义了作业不会运行的分支和标签的名称。

only: merge_request: (https://docs.gitlab.com/ce/ci/merge_request_pipelines/index.html#excluding-certain-jobs)

only: merge_requests 参数的行为是,只有带有该参数的作业才会在合并请求的上下文中运行;不会运行其他作业。

我觉得很难重组工作以使它们像以前一样工作,only: merge_request 存在于任何工作中。因此,我仍然在原始答案中使用单线来获取 CI 工作中的 MR 信息。


原答案:

没有。

但 GitLab 在 2019 年 Q2 有此功能的计划:https://gitlab.com/gitlab-org/gitlab-ce/issues/23902#final-assumptions

目前,我们可以使用一种解决方法来实现这一点。该方法如 Rekovni 的回答所述,并且确实有效。

有一个简单的单行,从当前分支获取一个MR的目标分支:

script: # in any script section of gitlab-ci.yml
  - 'CI_TARGET_BRANCH_NAME=$(curl -LsS -H "PRIVATE-TOKEN: $AWESOME_GITLAB_API_TOKEN" "https://my.gitlab-instance.com/api/v4/projects/$CI_PROJECT_ID/merge_requests?source_branch=$CI_COMMIT_REF_NAME" | jq --raw-output ".[0].target_branch")'

解释:

CI_TARGET_BRANCH_NAME 是一个新定义的变量,用于存储已解析的目标分支名称。各种用途都不需要定义变量。

AWESOME_GITLAB_API_TOKEN 是存储库的 CI/CD 变量配置中配置的变量。这是一个 GitLab 个人访问令牌(在用户设置中创建),具有api 范围。

关于curl 选项:-L 使 curl 了解 HTTP 重定向。 -sS 使 curl 静默(-s)但显示(-S)错误。 -H 指定访问 GitLab API 的权限信息。

使用的 API 可以建立在https://docs.gitlab.com/ce/api/merge_requests.html#list-project-merge-requests。我们使用source_branch 属性来确定哪个 MR 当前管道正在运行。因此,如果一个源分支对不同的目标分支有多个 MR,您可能需要更改| 之后的部分并执行您自己的逻辑。

关于jq(https://stedolan.github.io/jq/),它是一个简单的 CLI 工具来处理 JSON 内容(GitLab API 返回的内容)。您可以使用node -p 或任何您想要的方法。

【讨论】:

【参考方案2】:

Gitlab CI 与合并请求无关(目前)。由于管道在源分支上运行,您将无法检索目标。

【讨论】:

【参考方案3】:

由于 11.6 中的 new env variables $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME$CI_MERGE_REQUEST_TARGET_BRANCH_NAME 作业可以根据源或目标分支包含或排除。

使用only and except (complex) 表达式,我们可以构建一个规则来过滤合并请求。举几个例子:

目标分支为master的合并请求:
only:
    refs:
        - merge_requests
    variables:
        - $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
合并请求除非源分支是master release:
only:
    - merge_requests
except:
    variables:
        - $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "master"
        - $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "release"

如果你想使用多个引用(比如 merge_requests 和标签)和多个变量,引用将是 OR'd、the variables will be OR'd 和 the result will be AND'd:

如果仅使用时变量中的任何条件评估为真,则将创建一个新工作。如果在使用 except 时任何表达式的计算结果为真,则不会创建作业。

如果您在 only 或 except 下使用多个键,它们将充当 AND。逻辑是:

(any of refs) AND (any of variables) AND (any of changes) AND (if kubernetes is active)

变量表达式也很原始,只支持相等和(基本)正则表达式。因为变量将是 OR'd,所以从 gitlab 11.6 开始,您不能同时指定源分支和目标分支,只能指定一个。

【讨论】:

【参考方案4】:

从 GitLab 11.6 开始,有 CI_MERGE_REQUEST_TARGET_BRANCH_NAME

【讨论】:

【参考方案5】:

如果这是您真正想要的,可能有一种极其复杂的方式(未经测试),您可以使用merge request API 和CI variables 实现此目的。

使用类似的工作流/构建步骤:

    创建从feature/testmaster 的合并请求 开始构建 使用 API(在脚本中),使用 CI_PROJECT_ID 变量从当前项目中获取所有打开的合并请求,并按 source_branchtarget_branch 过滤。 如果有一个合并请求打开,source_branchtarget_branch 分别是 feature/testmaster,请继续构建,否则跳过其余的构建。

对于使用 API,我不相信您可以使用 CI_JOB_TOKEN 变量进行身份验证,因此您可能需要创建自己的 personal access token 并将其存储为 CI variable 以在构建中使用工作。

希望这会有所帮助!

【讨论】:

以上是关于在 GitLab CI 中,合并请求的目标分支是不是有变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Gitlab CI 管道始终运行一些作业,而其他作业仅在合并请求上运行?

在 GitLab Pipelines 中,有没有办法在分离合并请求时运行管道?

来自 gitlab-ci 的状态不再显示在 gitlab 合并请求中

不同 GitLab CI 合并请求规则之间的区别

为合并请求触发的管道运行应用 GitLab CI/CD 管道更改

使用gitlab cicd自动合并分支