如何在 Gitlab 中成功的管道结束时创建合并请求?

Posted

技术标签:

【中文标题】如何在 Gitlab 中成功的管道结束时创建合并请求?【英文标题】:How to create a merge request at the end of a successful pipeline in Gitlab? 【发布时间】:2018-12-08 19:39:40 【问题描述】:

我对 gitlab 和 gitlab CI 非常陌生,我已经建立了一个成功完成的管道。 我的主分支和开发分支受到保护,因此需要合并请求,以便组中的另一个开发人员可以在合并之前查看代码和评论。 我想知道是否可以在此管道的末尾生成此合并请求。 gitlab 存储库中是否有此设置,或者我是否必须创建一个脚本才能实现此目的? 旁注: 就在发布此之前,我遇到了this section of the gitlab docs 我在 ubuntu 18.04 上使用 gitlab-runner 11.0.0

【问题讨论】:

【参考方案1】:

为了满足我的简单需求,我只是在我的管道中添加了一个最后阶段,它基本上执行一个改编自 this post 的 bash 脚本。

编辑: 根据@Yuva 的要求

# Create a pull request on pipeline success
create_merge_request:
  stage: createMR
  tags:
    - autoMR
  script:
    - 'echo Merge request opened by $GITLAB_USER_NAME '
    - ~/commit.sh

在 commit.sh 中

#!/bin/bash
# This script was adapted from:
# https://about.gitlab.com/2017/09/05/how-to-automatically-create-a-new-mr-on-gitlab-with-gitlab-ci/

# TODO determine URL from git repository URL
[[ $HOST =~ ^https?://[^/]+ ]] && HOST="$BASH_REMATCH[0]/api/v4/projects/"

# The branch which we wish to merge into
TARGET_BRANCH=develop;

# The user's token name so that we can open the merge request as the user
TOKEN_NAME=`echo $GITLAB_USER_LOGIN_COMMIT_TOKEN | tr "[a-z]" "[A-Z]"`

# See: http://www.tldp.org/LDP/abs/html/parameter-substitution.html search $!varprefix*, $!varprefix@ section
PRIVATE_TOKEN=`echo $!TOKEN_NAME`

# The description of our new MR, we want to remove the branch after the MR has
# been closed
BODY="
\"project_id\": $CI_PROJECT_ID,
\"source_branch\": \"$CI_COMMIT_REF_NAME\",
\"target_branch\": \"$TARGET_BRANCH\",
\"remove_source_branch\": false,
\"force_remove_source_branch\": false,
\"allow_collaboration\": true,
\"subscribed\" : true,
\"title\": \"$GITLAB_USER_NAME merge request for: $CI_COMMIT_REF_SLUG\"
";

# Require a list of all the merge request and take a look if there is already
# one with the same source branch
 LISTMR=`curl --silent "$HOST$CI_PROJECT_ID/merge_requests?state=opened" --header "PRIVATE-TOKEN:$PRIVATE_TOKEN"`;
 COUNTBRANCHES=`echo $LISTMR | grep -o "\"source_branch\":\"$CI_COMMIT_REF_NAME\"" | wc -l`;

# No MR found, let's create a new one
if [ $COUNTBRANCHES -eq "0" ]; then
    curl -X POST "$HOST$CI_PROJECT_ID/merge_requests" \
    --header "PRIVATE-TOKEN:$PRIVATE_TOKEN" \
    --header "Content-Type: application/json" \
    --data "$BODY";

    echo "Opened a new merge request: WIP: $CI_COMMIT_REF_SLUG for user $GITLAB_USER_LOGIN";
    exit;
fi
    echo "No new merge request opened"

【讨论】:

能否请您分享 gitlab-ci.yml 代码 sn-p 用于自动创建 MR。 @Yuva 恐怕我已经将项目交给了那些已经接管了运营方面的运营商,这在当时是一个概念证明,所以这是不再使用。 没问题,谢谢,我可以使用 git api 命令“git push origin HEAD:dev -o merge_request.create -o merge_request.target=master -o merge_when_pipeline_succeeds。请参考这里是 Murali 的解决方案:***.com/questions/58322235/… @Yuva 感谢您的链接,虽然在发布时,我认为 API 功能不存在。【参考方案2】:

简短回答:当然 - 一切皆有可能。 GitLab 有一个很棒的 AP​​I (including creating an MR)。但我认为走那条路是不好的形式。您应该按照设计使用 GitLab。您开始合并请求太晚了。在您开始任何工作之前启动它,您的合并请求将在您的分支的整个持续时间中保持打开状态。

长答案: 这是理想的 GitLab 工作流程:

    有人针对存储库创建了ISSUE也许是一个功能请求,也许是一个实际问题,无论如何——有人想要改变一些东西,所以这是一个“问题” 开发者打开问题并点击CREATE MERGE REQUEST生成一个合并请求 (MR),一个匹配的分支,并将其与问题联系起来 开发人员在分支上工作,随时推送更改 当开发人员准备好让客户预览工作和/或其他开发人员进行代码审查时,开发人员会获得一个通过管道并在该合并请求页面上点击“解决 WIP”。 从这里,让该审阅者在完成审阅后单击 MERGE,甚至更好,在存储库设置中打开 APPROVALS设置人员或您想要评论的人群。 在合并按钮旁边,一定要删除源分支(为了安全起见),合并后的代码将自动关闭问题 - 并将所有 3 个元素链接在一起。

这从根本上落后于 GitHub 的工作方式(我来自该方式),你没有告诉人们你在做什么。

GitHub 上的 Pull Requests 是在工作完成并且您想要合并到 master 时创建的。 GitLab 上的合并请求是在工作开始时创建的.这允许人们在不需要时快速关闭,或防止多个开发人员重复工作。

编辑:听起来您对利用 API 很感兴趣。有一个名为“python-gitlab”的python包实际上工作得很好http://python-gitlab.readthedocs.io/en/stable/gl_objects/mrs.html

import gitlab
import os

origin = "https://gitlab.example.com"
# Private token is set as an env var
gl = gitlab.Gitlab(origin, private_token, api_version='4')
gl.auth()

def create_merge_request(origin, private_token):
    mr = project.mergerequests.create('source_branch': 'cool_feature',
                               'target_branch': 'master',
                               'title': 'merge cool feature',
                               'labels': ['label1', 'label2'])
    mr.assignee_id = gl.users.get(2).id # Assign it to coworker

def lookup_last_pipeline(origin, private_token):
    current_pipeline_id = os.environ['CI_PIPELINE_ID']
    pipelines = gl.projects.get(os.environ['CI_PROJECT_ID']).pipelines.list()
    for pipeline in pipelines:
        if pipeline.status == 'success' and pipeline.id == current_pipeline_id:
            create_merge_request()

这当然是一个示例,您必须根据自己的具体需求对其进行调整。

【讨论】:

感谢您的洞察,但我们的工作流程要求在成功进行下游合并和功能分支测试后发出合并请求。所以我希望能够创建合并请求,自动发布管道成功,并可能自动向其他成员发送电子邮件,以便有人可以接手并查看任务。 是的,我对利用 API 很感兴趣,并且找到了一种方法。感谢您的帮助。【参考方案3】:

另一种方法:

不使用 GitLab API 获取管道签出的代码所代表的补丁 使用电子邮件(!),因为 GitLab 11.5(2018 年 11 月)

Open a merge request with a patch via email

GitLab 长期以来一直支持通过电子邮件打开合并请求,但在发送电子邮件之前,分支必须已经存在于服务器上。现在,您可以通过附加一个或多个补丁文件 (.patch) 来打开仅包含电子邮件的合并请求。

补丁文件是系统之间共享和传输更改的标准。在 GitLab 的未来版本中,我们将在此基础上构建 distributed merge requests,这将允许 GitLab 实例和其他 Git 托管工具之间的合并请求。

参见documentation 和issue。

【讨论】:

谢谢。稍后我会对此进行调查并发表评论。

以上是关于如何在 Gitlab 中成功的管道结束时创建合并请求?的主要内容,如果未能解决你的问题,请参考以下文章

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

Gitlab CI/CD 如何在管道中捕获 curl 响应

Gitlab双管道触发问题

为啥我在 Gitlab 合并请求中收到“由于未验证用户而导致管道失败”和“分离的合并请求管道”?

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

使用gitlab cicd自动合并分支