GitLab CI:在合并请求被接受后获取源分支

16
我有一个主分支,应该只能通过合并“release / xxxxx” 分支或合并“hotfix / xxxxx” 分支而获得提交。
发布分支的流水线构建了一个 docker 镜像,并使用“beta” 标签发布它。 发布分支的流水线构建了一个 docker 镜像,并使用“hotfix” 标签发布它。
主分支的流水线仅将“beta” 重新标记为“stable”(当发布分支合并到主分支时)或将“hotfix” 重新标记为“stable”(当热修复分支合并到主分支时)。然后还为该版本创建一个新的 git tag 和 gitlab 发布。最后,docker 映像被部署。
当前发生以下情况:
- 创建合并请求将“release / xxxxx” 合并到“master” 中。 - 流水线会在自动开始(在接受和合并合并请求之前)。 - Docker 作业解析 CI_MERGE_REQUEST_SOURCE_BRANCH_NAME 变量,以确定合并请求的源分支是否为发布分支。 - 然后,Docker 作业将“beta” 重新标记为“latest”。 - Git 标记作业将版本标记添加到项目中的 gitlab 发布中。 - 部署作业部署 Docker 映像。
当合并请求最终被接受时,将执行以下操作:
- 流水线再次启动。
  • Docker作业解析了CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,但现在该值为空,因此无法确定此合并的源分支。
  • Docker作业失败。
  • 我认为很明显,在合并请求被接受之前,我不想运行所有这些作业(特别是部署作业)。

    但我无法想到一种好的方法,在合并请求被接受后仅在主分支上运行管道,并仍然能够确定源分支。


    请问您能分享一下您的 gitlab-ci.yml 文件吗? - Hardik Upadhyay
    1
    我的实际.gitlab-ci.yml文件非常混乱,每个分支最多处理13个作业,并且远远超过我问题中提到的3个分支。更不用说它包括来自其他非公共项目的一堆文件,使用自定义的非公共docker镜像,并且严重依赖于在组和项目级别设置的环境变量。我无法分享所有这些内容,仅凭.gitlab-ci.yml文件也无法帮助任何人。 - Forivin
    我理解你的情况,但是我们很难假设你的配置是管道和部署都高度依赖于yml文件。 - Hardik Upadhyay
    你找到解决方案了吗? - BastienSander
    4个回答

    8
    仅使用存储在git中的信息:
    当运行合并请求已被接受后,HEAD提交应该是合并的结果,因此HEAD^2应该是被合并的分支的头提交。
    您可以获取以下信息:
    • the tags that point directly at this commit :

       git tag --points-at HEAD^2
      
    • the branches that point directly at this commit :

       git branch --points-at HEAD^2    # for local branches
       git branch -r --points-at HEAD^2 # for remote branches
      
    • the branches that contain this commit :

       git branch --contains HEAD^2    # for local branches
       git branch -r --contains HEAD^2 # for remote branches
      
    使用由 GitLab 设置的环境变量:
    读完预定义变量文档页后,我很惊讶没有找到可以指示作业是在合并请求被接受后触发的变量。
    您可以查看 GitLab 的 Webhooks:Merge request events。这些应该提供足够的信息来识别在合并请求被接受后涉及哪些分支。
    [更新] 您也可以使用 GitLab 的 API,请参见@BastienSander's answer

    当我尝试使用您的命令时,出现了“错误:对象名称格式不正确 'HEAD^2'”。 - BastienSander
    1
    @BastienSander:这意味着你当前的活动提交不是合并提交(HEAD^2表示“HEAD的第二个父级”,只有在HEAD是合并提交时才有效)。 - LeGEC
    这对我没有起作用,所以我改成了 git log --skip=1 -1 - Christian

    6

    似乎可以通过GitLab的API实现。

    这里是一个curl示例。

      - MR_BRANCH_LAST_COMMIT_SHA=$(
          curl -s \
            --header "PRIVATE-TOKEN: $CI_PRIVATE_TOKEN" \
            "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA" |\
            jq -r '.parent_ids | del(.[] | select(. == "'$CI_COMMIT_BEFORE_SHA'")) | .[-1]'
        )
      - MR_BRANCH_NAME=$(
          curl -s \
            --header "PRIVATE-TOKEN: $CI_PRIVATE_TOKEN" \
            "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$MR_BRANCH_LAST_COMMIT_SHA/merge_requests" |\
            jq -r '.[0].source_branch'
        )
    

    我在这里找到了解决方法: https://forum.gitlab.com/t/run-job-in-ci-pipeline-only-on-merge-branch-into-the-master-and-get-merged-branch-name/24195/5

    请注意,在PRIVATE-TOKEN:后面必须省略空格,如下所示:--header "PRIVATE-TOKEN:$CI_PRIVATE_TOKEN" - 请参见:https://gitlab.com/gitlab-org/gitlab/-/issues/4781#note_88220042 - InsOp

    0

    我运行了export命令,并发现只有两个预定义变量包含源分支(作为字符串的一部分),其中之一是$CI_COMMIT_TITLE。它返回:

    declare -x CI_COMMIT_TITLE="Merge branch 'source-branch-name' into 'master'"
    

    我和 @boombar 有着相同的思路 - 使用 CI_COMMIT_TITLE 字符串来获取源分支名称。我将字符串拆分并将源分支子字符串设置为变量,如下所示:

    - SOURCE_BRANCH_NAME=`echo $CI_COMMIT_TITLE | cut -d"'" -f 2`
    

    我也同意这不是最优雅的方法,但只要默认消息不改变,你就可以放心使用。


    0
    我们曾经遇到过类似的情况。如果有一个名为hotfix/xxxxx的分支,当推送时,它可以通过完整的流水线,但在合并请求到master被批准后,只有builddeploy作业应该运行,跳过所有测试以尽快将更改推向生产环境。如果任何其他分支合并到master,则应运行完整的流水线。
    我们的解决方案是使用已批准合并请求的提交消息标题:
    .merged_hotfix_to_master: &merged_hotfix_to_master
                         "$CI_COMMIT_TITLE =~ /^Merge branch 'hotfix\\// 
                            && $CI_COMMIT_REF_SLUG == 'master'"
        
    .skip-for-hotfix-merge-to-master-rule:
      rules:
        - if: *merged_hotfix_to_master
          when: never
    

    因此,如果提交信息标题以Merge branch 'hotfix/开头,并且目标分支为master,则可以跳过作业。规则已在适当位置添加:

    some-test:
      extends: .tests-common
      stage: test
        - !reference [.skip-for-hotfix-merge-to-master-rule, rules]
        - if: *only-master-branch
    

    这不是最优雅的解决方案,但我也看不出为什么要改变合并请求的默认消息。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接