Gitlab CI:仅为受保护分支上存在的标记提交运行管道作业 [英] Gitlab CI: Run Pipeline job only for tagged commits that exist on protected branches

查看:11
本文介绍了Gitlab CI:仅为受保护分支上存在的标记提交运行管道作业的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个仅在满足两个以下条件时运行的管道:

I would like to create a pipeline that is only run if both of the following conditions are met:

  • 标签引用给定的提交
  • 提交存在于任何受保护的分支(即主分支)上
  • 可选:只要将标记的未受保护的分支合并(通过合并请求)到受保护的分支或将标记添加到受保护的分支,就应该运行该作业.

我试过了:

publish:
  stage: publish
  script:
    - echo "Publish!"
  rules:
    # Only publish if tag given and commit is present on a protected branch
    - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"'

$CI_COMMIT_TAG 设置为 $CI_COMMIT_REF_PROTECTED 设置为 true 时,这不起作用.

Which does not work as either the $CI_COMMIT_TAG is set or the $CI_COMMIT_REF_PROTECTED is set to true.

我知道类似的问题:Gitlabci 仅使用发布标签在 master 上运行作业如何只在标记的分支上运行 gitlab-ci.yml 作业?.

I am aware of the similar Questions: Gitlab ci run job on master with release tag only and How to run a gitlab-ci.yml job only on a tagged branch?.

我也知道 gitlab 的问题已经/曾经进行过广泛的讨论,并提供了一些解决方案(或类似的解决方案),例如 这个.

Also I know there is/was a wide discussion in the issues from gitlab, with some solution (or something close to this) like this.

一般的问题似乎是在 gitlab 中无法确定在给定分支上提交是否可靠,因为没有给出相关信息(git 历史记录).

The general problem seems to be that it is not possible in gitlab to determine reliable if a commit if on a given branch as the information (git history) for this is not given.

这个问题是为了在 gitlab CI 中为这个常见用例跟踪一个适当的解决方案.

This question is to keep track of a proper solution within gitlab CI for this common use case.

推荐答案

结合解决方法 在问题中提到了新的 gitlab 规则工作流 功能我想出了一个令我满意的答案.

Combining the workaround mentioned in the question with the new gitlab rule and workflow features I came up with an answer that seem satisfying for me.

最初发布解决方法的人提到在某些情况下 git branch contains 没有给出正确的结果.因此,请确保 git fetch 不会进行浅拷贝(请注意,开始时将 GIT_STRATEGY 更改为 clone 可能很有用,以便删除旧的可能较浅的副本).

The person originally posting the workaround mentioned that there are cases in which git branch contains does not give the correct results. So made sure, that git fetch does not make a shallow copy (note for the beginning it could be useful to change the GIT_STRATEGY to clone, so that old possibly shallow copies are removed).

我没有使用 CI_COMMIT_REF_PROTECTED 这也适用于受保护的标签,而是将主分支硬编码为受保护的.

Instead of using CI_COMMIT_REF_PROTECTED which could be true also for protected tags, I hardcoded the master branch as protected.

# Be quite strict in what can trigger a pipeline, actually only pushes of
# branches or version tags should trigger anything - otherwise we need to catch
# too many edge cases.
workflow:
  rules:
    # Do no allow manually triggered pipelines to prevent duplicates!
    # Instead rerun the pipeline created with the last push
    - if: $CI_PIPELINE_SOURCE != "push"
      when: never
    # Only execute when a valid version tag like v1.0, 2.3 or similar is given
    # Required is always one point like 1.0
    - if: $CI_COMMIT_TAG =~ /^v?[0-9]+[.][0-9]+([.][0-9]+)?$/
    - if: $CI_COMMIT_BRANCH
variables:
  # Make sure we don't get a shallow copy
  GIT_DEPTH: 0
  # Fetch is default just to make clear what is used
  GIT_STRATEGY: fetch
  # make sure we fetch everything and also see what is happening
  GIT_FETCH_EXTRA_FLAGS: -f --tags --prune --update-head-ok

default:
  before_script:
    - export CI_LOG_LINE=$(git log --decorate=full| grep "^commit $CI_COMMIT_SHA[ ]")
    # var = 1 if the current commit is the **latest** on master
    - export IS_ON_MASTER=$(echo $CI_LOG_LINE | grep -qso "origin/master, " && echo 1 || echo 0)
    # var = 1 if current commit is on any remote commit that is part of masters history
    - export COMMIT_ON_MASTER=$(git branch -r --contains $CI_COMMIT_SHA | grep -Eq '^[ ]+origin/master$'  && echo 1 || echo 0)


stages:
  - check_update_environment

check_update_environment:
  stage: check_update_environment
  script:
    # Lets print some debug stuff
    - echo $CI_JOB_TRIGGERED
    - echo $CI_PIPELINE_SOURCE
    - echo $CI_COMMIT_SHA
    - echo $CI_COMMIT_REF_NAME
    - echo $CI_BUILD_REF
    - echo $CI_COMMIT_BRANCH
    - echo $CI_COMMIT_TAG
    # Get the information about the state of the current commit
    - git log --decorate=full| grep "^commit $CI_COMMIT_SHA[ ]" || echo "Failed???"
    - git status
    - git remote show
    # Show current branch --> normally fails - only for kept for reference
    - git symbolic-ref --short HEAD || echo "Doesn't work"
    # Some more possible debug information
    - git branch --contains $CI_BUILD_REF
    - git tag --contains $CI_BUILD_REF
    - env
    # **Finally the important part**
    # Exit if tag is given on none master branch early
    - if [[ ! -z "$CI_COMMIT_TAG" && $COMMIT_ON_MASTER != 1 ]]; then
         echo "Tags should never be applied to non master branches!" >&2;
         echo "We quit early! Please delete the tag, merge the branch to master and recreate the tag to continue" >&2;
         exit 1;
      fi

test:
  stage: test
  script:
    - echo "Doing testing..."
  dependencies:
    - check_update_environment

publish:
  stage: publish
  script:
    - echo "Publishing..."
  rules:
    # Run always if there is version tag. The version tag is defined
    #   in the workflow rules
    # Due to the fail early in the environment check this is never done for
    # branches that aren't master
    - if: $CI_COMMIT_TAG
  dependencies:
    - test

这篇关于Gitlab CI:仅为受保护分支上存在的标记提交运行管道作业的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆