触发器分支属性的可变扩展防止创建下游管道

Posted

技术标签:

【中文标题】触发器分支属性的可变扩展防止创建下游管道【英文标题】:Variable expansion of trigger branch property prevents downstream pipeline from being created 【发布时间】:2020-10-07 13:38:30 【问题描述】:

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

重现步骤

    像往常一样使用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 版本)。也欢迎替代解决方案,但这个似乎应该可以工作。

出现错误的 GitLab 版本

自托管 GitLab 社区版 12.10.7

当前的错误行为是什么?

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

预期的正确行为是什么?

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

更多详情

在 v12.4 和 it's explicitly mentioned in the docs 中添加了在触发器分支属性中使用变量扩展的功能。 我搜索了其他 .gitlab-ci.yml / GitLab 配置文件。每个尝试在分支属性中使用变量扩展的人都将其注释掉,称其因未知原因而被窃听 (example. 我无法找到有人声称对触发器属性的branch 属性具有工作变量扩展的存储库。 不幸的是,替代解决方案是 (a) 将每个下游分支名称硬编码到上游项目的 GitLab CI 配置中,或者 (b) 无法测试对下游 GitLab CI 配置的更改而不先将它们提交到 @ 987654335@/main,或不得不use only/except

TL;DR:如何将变量的值用于桥接作业的分支属性?我目前的解决方案是这样的,所以作业失败并且没有创建下游管道。

【问题讨论】:

【参考方案1】:

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

触发作业将非常弱 b/c 它不是在跑步者上运行的完整作业。因此大部分触发器配置都需要硬编码。

我使用直接 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"

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

此外,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

【讨论】:

还有更多信息吗?现在有合法的方式在 CI 文件中触发这个吗? 我不能在子管道中使用父管道变量。在您的示例中,传入了variables[STAGE]=$STAGE。但是,在子管道中,echo STAGE='$STAGE' 产生STAGE='' ....有什么想法吗?

以上是关于触发器分支属性的可变扩展防止创建下游管道的主要内容,如果未能解决你的问题,请参考以下文章

Gitlab ci问题将工件传递到带有触发器和需要关键字的下游管道

从git中的现有分支创建新分支时如何不触发管道?

如何使用不同的 yml 文件在 gitlab ci 中触发下游管道?

仅针对特定分支的 gitlab 触发管道

如何让通用 Webhook 触发器插件与 Jenkins 中的多分支管道一起使用?

Gitlab-ci:如果 MR 存在则触发 merge_request 分离管道,如果不存在则触发源分支管道。这两条管道不应同时运行