触发器分支的变量扩展 属性 阻止创建下游管道
Variable expansion of trigger branch property prevents downstream pipeline from being created
触发器 属性 的分支 属性 使用变量的分支作业将始终失败,原因是:无法创建下游管道。
重现步骤
- 像往常一样使用
trigger
属性 设置下游管道。
- 给触发器属性添加一个
branch
属性。写入下游存储库上现有分支的名称,例如 master
/main
或功能分支的名称。
- 运行管道,观察下游管道创建成功
- 现在将
branch
属性 改为使用变量,例如 branch: $CI_TARGET_BRANCH
。
- 手动 运行 CI 管道,通过 GitLab GUI 设置变量。
- 作业将立即失败,原因是:无法创建下游管道。
代码示例
目标是创建一个 GitLab CI 配置,运行 是指定下游分支的管道。尝试使用变量执行此操作时会出现此错误。
这有效,像往常一样创建下游管道。但是分支名称是硬编码的:
stages:
- deploy
deploy:
variables:
environment: dev
stage: deploy
trigger:
project: group/project
branch: foo
strategy: depend
这行不通;虽然TARGET_BRANCH
设置成功,但是由于无法创建下游管道,作业失败:
stages:
- removeme
- deploy
before_script:
- if [ -z "$TARGET_BRANCH" ]; then TARGET_BRANCH="main"; fi
- echo $TARGET_BRANCH
test_variable:
stage: removeme
script:
- echo $TARGET_BRANCH
deploy:
variables:
environment: dev
stage: deploy
trigger:
project: group/project
branch: $TARGET_BRANCH
strategy: depend
如果您知道我做错了什么,或者您有一些确实与分支属性的变量扩展一起工作的东西,请分享它(连同你的 GitLab 版本)。也欢迎其他解决方案,但这个似乎应该有效。
出现bug的GitLab版本
自托管 GitLab 社区版 12.10.7
当前的 bug 行为是什么?
作业总是失败,原因是:无法创建下游管道。
预期的正确行为是什么?
branch
属性 应该设置为变量的值,下游管道应该正常创建,就像你只是 hardcoded/typed 分支的名称一样.
更多详情
- 在触发分支属性中使用变量扩展的能力是在v12.4中添加的,并且it's explicitly mentioned in the docs。
- 我搜索了其他 .gitlab-ci.yml / GitLab 配置文件。每个试图在分支 属性 中使用变量扩展的人都将其注释掉,说它因未知原因被窃听 (example。
- 我找不到一个存储库,其中有人声称对触发器 属性 的
branch
属性 进行了工作变量扩展。
- 不幸的是,替代解决方案是 (a) 将每个下游分支名称硬编码到上游项目的 GitLab CI 配置中,或者 (b) 无法测试对下游 GitLab 的更改 CI 配置,而无需先将它们提交到
master
/main
,或者不必提交到 use only
/except
.
TL;DR: 如何将变量值用于桥接作业的分支属性?我当前的解决方案使作业失败并且未创建下游管道。
这是一个 'works as designed',gitlab 会在即将发布的版本中改进。
触发作业会很弱b/c它不是在运行器上运行的完整作业。因此大部分触发器配置需要硬编码。
我使用直接 API 调用来触发传递 CI_JOB_TOKEN 的下游作业,它像触发器一样将上游作业链接到下游
API 通话让您完全控制
curl -X POST \
-s \
-F token=${CI_JOB_TOKEN} \
-F "ref=${REF_NAME}" \
-F "variables[STAGE]=${STAGE}" \
"${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
现在这不会等待和监视作业何时完成,因此如果您需要等待下游作业完成,您将需要为此编写代码,
此外,CI_JOB_TOKEN不能用于获取下游作业的状态,因此您需要另一个令牌。
- |
DOWNSTREAM_RESULTS=$( curl --silent -X POST \
-F token=${CI_JOB_TOKEN} \
-F "ref=${DOWNSTREAM_PROJECT_REF}" \
-F "variables[STAGE]=${STAGE}" \
-F "variables[SLS_PACKAGE_PATH]=.serverless-${STAGE}" \
-F "variables[INVOKE_SLS_TESTS]=false" \
-F "variables[UPSTREAM_PROJECT_REF]=${CI_COMMIT_REF_NAME}" \
-F "variables[INSTALL_SLS_PLUGINS]=${INSTALL_SLS_PLUGINS}" \
-F "variables[PROJECT_ID]=${CI_PROJECT_ID}" \
-F "variables[PROJECT_JOB_NAME]=${PROJECT_JOB_NAME}" \
-F "variables[PROJECT_JOB_ID]=${PROJECT_JOB_ID}" \
"${CI_SERVER_URL}/api/v4/projects/${DOWNSTREAM_PROJECT_ID}/trigger/pipeline" )
echo ${DOWNSTREAM_RESULTS} | jq .
DOWNSTREAM_PIPELINE_ID=$( echo ${DOWNSTREAM_RESULTS} | jq -r .id )
echo "Monitoring Downstream pipeline ${DOWNSTREAM_PIPELINE_ID} status..."
DOWNSTREAM_STATUS='running'
COUNT=0
PIPELINE_API_URL="${CI_SERVER_URL}/api/v4/projects/${DOWNSTREAM_PROJECT_ID}/pipelines/${DOWNSTREAM_PIPELINE_ID}"
echo "Pipeline api endpoint => ${PIPELINE_API_URL}"
while [ ${DOWNSTREAM_STATUS} == "running" ]
do
if [ $COUNT -eq 0 ]
then
echo "Starting loop"
fi
if [ ${COUNT} -ge 350 ]
then
echo 'TIMEOUT!'
DOWNSTREAM_STATUS="TIMEOUT"
break
elif [ $(( ${COUNT} % 60 )) -eq 0 ]
then
echo "Downstream pipeline status => ${DOWNSTREAM_STATUS}"
echo "Count => ${COUNT}"
sleep 10
else
sleep 10
fi
DOWNSTREAM_CALL=$( curl --silent --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" ${PIPELINE_API_URL} )
if [ $COUNT -eq 0 ]
then
echo ${DOWNSTREAM_CALL} | jq .
fi
DOWNSTREAM_STATUS=$( echo ${DOWNSTREAM_CALL} | jq -r .status )
COUNT=$(( ${COUNT} + 1 ))
done
#pipeline status is running, failed, success, manual
echo "PIPELINE STATUS => ${DOWNSTREAM_STATUS}"
if [ ${DOWNSTREAM_STATUS} != "success" ]
then
exit 2
fi
触发器 属性 的分支 属性 使用变量的分支作业将始终失败,原因是:无法创建下游管道。
重现步骤
- 像往常一样使用
trigger
属性 设置下游管道。 - 给触发器属性添加一个
branch
属性。写入下游存储库上现有分支的名称,例如master
/main
或功能分支的名称。 - 运行管道,观察下游管道创建成功
- 现在将
branch
属性 改为使用变量,例如branch: $CI_TARGET_BRANCH
。 - 手动 运行 CI 管道,通过 GitLab GUI 设置变量。
- 作业将立即失败,原因是:无法创建下游管道。
代码示例
目标是创建一个 GitLab CI 配置,运行 是指定下游分支的管道。尝试使用变量执行此操作时会出现此错误。
这有效,像往常一样创建下游管道。但是分支名称是硬编码的:
stages:
- deploy
deploy:
variables:
environment: dev
stage: deploy
trigger:
project: group/project
branch: foo
strategy: depend
这行不通;虽然TARGET_BRANCH
设置成功,但是由于无法创建下游管道,作业失败:
stages:
- removeme
- deploy
before_script:
- if [ -z "$TARGET_BRANCH" ]; then TARGET_BRANCH="main"; fi
- echo $TARGET_BRANCH
test_variable:
stage: removeme
script:
- echo $TARGET_BRANCH
deploy:
variables:
environment: dev
stage: deploy
trigger:
project: group/project
branch: $TARGET_BRANCH
strategy: depend
如果您知道我做错了什么,或者您有一些确实与分支属性的变量扩展一起工作的东西,请分享它(连同你的 GitLab 版本)。也欢迎其他解决方案,但这个似乎应该有效。
出现bug的GitLab版本
自托管 GitLab 社区版 12.10.7
当前的 bug 行为是什么?
作业总是失败,原因是:无法创建下游管道。
预期的正确行为是什么?
branch
属性 应该设置为变量的值,下游管道应该正常创建,就像你只是 hardcoded/typed 分支的名称一样.
更多详情
- 在触发分支属性中使用变量扩展的能力是在v12.4中添加的,并且it's explicitly mentioned in the docs。
- 我搜索了其他 .gitlab-ci.yml / GitLab 配置文件。每个试图在分支 属性 中使用变量扩展的人都将其注释掉,说它因未知原因被窃听 (example。
- 我找不到一个存储库,其中有人声称对触发器 属性 的
branch
属性 进行了工作变量扩展。
- 我找不到一个存储库,其中有人声称对触发器 属性 的
- 不幸的是,替代解决方案是 (a) 将每个下游分支名称硬编码到上游项目的 GitLab CI 配置中,或者 (b) 无法测试对下游 GitLab 的更改 CI 配置,而无需先将它们提交到
master
/main
,或者不必提交到 useonly
/except
.
TL;DR: 如何将变量值用于桥接作业的分支属性?我当前的解决方案使作业失败并且未创建下游管道。
这是一个 'works as designed',gitlab 会在即将发布的版本中改进。
触发作业会很弱b/c它不是在运行器上运行的完整作业。因此大部分触发器配置需要硬编码。
我使用直接 API 调用来触发传递 CI_JOB_TOKEN 的下游作业,它像触发器一样将上游作业链接到下游
API 通话让您完全控制
curl -X POST \
-s \
-F token=${CI_JOB_TOKEN} \
-F "ref=${REF_NAME}" \
-F "variables[STAGE]=${STAGE}" \
"${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
现在这不会等待和监视作业何时完成,因此如果您需要等待下游作业完成,您将需要为此编写代码,
此外,CI_JOB_TOKEN不能用于获取下游作业的状态,因此您需要另一个令牌。
- |
DOWNSTREAM_RESULTS=$( curl --silent -X POST \
-F token=${CI_JOB_TOKEN} \
-F "ref=${DOWNSTREAM_PROJECT_REF}" \
-F "variables[STAGE]=${STAGE}" \
-F "variables[SLS_PACKAGE_PATH]=.serverless-${STAGE}" \
-F "variables[INVOKE_SLS_TESTS]=false" \
-F "variables[UPSTREAM_PROJECT_REF]=${CI_COMMIT_REF_NAME}" \
-F "variables[INSTALL_SLS_PLUGINS]=${INSTALL_SLS_PLUGINS}" \
-F "variables[PROJECT_ID]=${CI_PROJECT_ID}" \
-F "variables[PROJECT_JOB_NAME]=${PROJECT_JOB_NAME}" \
-F "variables[PROJECT_JOB_ID]=${PROJECT_JOB_ID}" \
"${CI_SERVER_URL}/api/v4/projects/${DOWNSTREAM_PROJECT_ID}/trigger/pipeline" )
echo ${DOWNSTREAM_RESULTS} | jq .
DOWNSTREAM_PIPELINE_ID=$( echo ${DOWNSTREAM_RESULTS} | jq -r .id )
echo "Monitoring Downstream pipeline ${DOWNSTREAM_PIPELINE_ID} status..."
DOWNSTREAM_STATUS='running'
COUNT=0
PIPELINE_API_URL="${CI_SERVER_URL}/api/v4/projects/${DOWNSTREAM_PROJECT_ID}/pipelines/${DOWNSTREAM_PIPELINE_ID}"
echo "Pipeline api endpoint => ${PIPELINE_API_URL}"
while [ ${DOWNSTREAM_STATUS} == "running" ]
do
if [ $COUNT -eq 0 ]
then
echo "Starting loop"
fi
if [ ${COUNT} -ge 350 ]
then
echo 'TIMEOUT!'
DOWNSTREAM_STATUS="TIMEOUT"
break
elif [ $(( ${COUNT} % 60 )) -eq 0 ]
then
echo "Downstream pipeline status => ${DOWNSTREAM_STATUS}"
echo "Count => ${COUNT}"
sleep 10
else
sleep 10
fi
DOWNSTREAM_CALL=$( curl --silent --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" ${PIPELINE_API_URL} )
if [ $COUNT -eq 0 ]
then
echo ${DOWNSTREAM_CALL} | jq .
fi
DOWNSTREAM_STATUS=$( echo ${DOWNSTREAM_CALL} | jq -r .status )
COUNT=$(( ${COUNT} + 1 ))
done
#pipeline status is running, failed, success, manual
echo "PIPELINE STATUS => ${DOWNSTREAM_STATUS}"
if [ ${DOWNSTREAM_STATUS} != "success" ]
then
exit 2
fi