我想创建一个仅在满足以下条件两个时才运行的管道:
我已经尝试过:
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。
我知道类似的问题:Gitlab ci run job on master only withrelease tag和How to run a gitlab-ci.yml job only on a taggedbranch?.
我还知道 gitlab 对问题进行了广泛的讨论,有一些解决方案(或类似的解决方案),例如this。
一般的问题似乎是,在 gitlab 中不可能确定给定分支上的提交是否可靠,因为未给出此信息(git 历史记录)。
这个问题是为了在 gitlab CI 中跟踪这个常见用例的正确解决方案。
将问题中提到的解决方法与新的gitlab规则和工作流程功能相结合,我想出了一个令我满意的答案。
最初发布解决方法的人提到,在某些情况下
git branch contains
不会给出正确的结果。
所以我确保 git fetch
不会进行浅拷贝(请注意,一开始将 GIT_STRATEGY
更改为 clone 可能很有用,以便删除旧的可能的浅拷贝)。
我没有使用
CI_COMMIT_REF_PROTECTED
(这也适用于受保护的标签),而是将 $CI_DEFAULT_BRANCH
(感谢 [Gostega)硬编码为受保护。
# 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 the default branch
- export IS_ON_MAIN=$(echo $CI_LOG_LINE | grep -qso "origin/${CI_DEFAULT_BRANCH}, " && echo 1 || echo 0)
# var = 1 if current commit is on any remote commit that is part of default branchs history
- export COMMIT_ON_MAIN=$(git branch -r --contains $CI_COMMIT_SHA | grep -Eq "^[ ]+origin/${CI_DEFAULT_BRANCH}$" && echo 1 || echo 0)
stages:
- check_update_environment
- test
- publish
check_update_environment:
stage: check_update_environment
script:
# Exit if tag is given on none main branch early
# Check for
- if [[ ! -z "$CI_COMMIT_TAG" && $COMMIT_ON_MAIN != 1 ]]; then
echo "Tags should never be applied to non main branches!" >&2;
echo "We quit early! Please delete the tag, merge the branch to main 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 the default branch
- if: $CI_COMMIT_TAG
dependencies:
- test