触发器分支属性的变量扩展会阻止创建下游管道

Eri*_*rey 5 continuous-integration continuous-delivery gitlab gitlab-ci

触发器属性的分支属性使用变量的分支作业将始终失败,原因是:无法创建下游管道。

重现步骤

  1. trigger像平常一样设置具有属性的下游管道。
  2. branch属性添加到触发器属性。写入下游存储库上现有分支的名称,例如master/main或功能分支的名称。
  3. 运行管道,观察下游管道已成功创建。
  4. 现在更改branch属性以使用变量,例如branch: $CI_TARGET_BRANCH.
  5. 手动运行 CI 管道,通过 GitLab GUI 设置变量。
  6. 该作业将立即失败,原因是:无法创建下游管道。

代码示例

目标是创建一个运行指定下游分支管道的 GitLab CI 配置。当尝试使用变量执行此操作时会出现该错误。

这有效,像平常一样创建下游管道。但分支名称是硬编码的:

stages:
  - deploy

deploy:
  variables:
    environment: dev
  stage: deploy
  trigger:
    project: group/project
    branch: foo
    strategy: depend
Run Code Online (Sandbox Code Playgroud)

这是行不通的;虽然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
Run Code Online (Sandbox Code Playgroud)

如果您知道我做错了什么,或者您有一些可以与分支属性的变量扩展一起使用的东西,请分享它(以及您的 GitLab 版本)。也欢迎其他解决方案,但这个解决方案似乎应该有效。

出现bug的GitLab版本

自托管 GitLab 社区版 12.10.7

当前的错误行为是什么?

作业总是失败,原因是:无法创建下游管道。

预期的正确行为是什么?

branch属性应设置为变量的值,并且下游管道应正常创建,就像您只是硬编码/键入分支名称一样。

更多细节

  • 在 v12.4 中添加了在触发器分支属性中使用变量扩展的功能,并且在 docs 中明确提到了这一点
  • 我搜索了其他 .gitlab-ci.yml / GitLab 配置文件。每一个尝试在分支属性中使用变量扩展的人都将其注释掉,并表示它因未知原因而被窃听(例如.
    • 我无法找到一个存储库,其中有人声称对branch触发器属性的属性有工作变量扩展。
  • master不幸的是,替代解决方案是(a)将每个下游分支名称硬编码到上游项目的 GitLab CI 配置中,或者(b)在不首先将其提交到/ 的情况下无法测试对下游 GitLab CI 配置的更改main,或者使用/onlyexcept

TL;DR:如何将变量的值用于桥接作业的分支属性?我当前的解决方案使得作业失败并且未创建下游管道。

小智 4

这是“按设计工作”,gitlab 将在即将发布的版本中进行改进。

触发作业将非常弱,因为它不是在运行器上运行的完整作业。因此,大多数触发器配置需要进行硬编码。

我使用直接 API 调用来触发传递 CI_JOB_TOKEN 的下游作业,该 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"
Run Code Online (Sandbox Code Playgroud)

现在,这不会等待和监视作业何时完成,因此如果您需要等待下游作业完成,您将需要为此编写代码,

此外,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
Run Code Online (Sandbox Code Playgroud)