规则中无法识别 GitLab CI 自定义变量

Posted

技术标签:

【中文标题】规则中无法识别 GitLab CI 自定义变量【英文标题】:GitLab CI custom variable not recognized in rules 【发布时间】:2021-05-18 11:46:52 【问题描述】:

在使用预定义 CI 变量的 variables 块中定义变量时,不能在 rules 块中引用它。在这里,只有 job_1 被执行:

variables:
  PRODUCTION_BRANCH: $CI_DEFAULT_BRANCH

stages:
  - stage_1

job_1:
  stage: stage_1
  script:
    - export
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'

job_2:
  stage: stage_1
  script:
    - export
  rules:
    - if: '$CI_COMMIT_BRANCH == $PRODUCTION_BRANCH'

但是当对PRODUCTION_BRANCH 的值进行硬编码时,它会按预期工作。在这里,两个作业都被执行:

variables:
  PRODUCTION_BRANCH: "master"

stages:
  - stage_1

job_1:
  stage: stage_1
  script:
    - export
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'

job_2:
  stage: stage_1
  script:
    - export
  rules:
    - if: '$CI_COMMIT_BRANCH == $PRODUCTION_BRANCH'

查看作业的输出时(因为export 记录了环境变量),在这两种情况下,变量PRODUCTION_BRANCH 的值都正确为master。 为什么会有这样的行为,是否有修复/解决方法?

【问题讨论】:

你用的是什么版本?从 13.6 开始,类似的问题似乎已得到解决:gitlab.com/gitlab-org/gitlab/-/issues/206929 & gitlab.com/gitlab-org/gitlab/-/issues/34272 和 13.7:gitlab.com/gitlab-org/gitlab/-/issues/209864。这个仍然开放:gitlab.com/gitlab-org/gitlab/-/issues/35315 @Arty-chan 我正在运行 13.5.3 版。似乎最后一个问题与我有关 user1452736 发布了一个 Answer 说“这可能是因为在您的 gitlab 实例上禁用了此功能 https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html#enabling-the-nested-variable-expansion-feature” 【参考方案1】:

gitlab 在评估 yaml 并确定要运行的内容时,不会对 variables 部分进行变量扩展。不过,变量插值在跑步者中确实有效。

因此,如果在定义自定义变量时使用变量插值,则必须小心。它们是用于 gitlab 条件(不起作用)还是仅用于运行器(在 gitlab 决定运行作业之后......这有效)?

这令人困惑,我在文档中找不到任何关于这种高概率陷阱的警告/参考......但也许我错过了。

所以在你的if: 中你可以使用

$CI_* 变量 (except for a few ENVIRONMENT ones ...请参阅链接的可使用变量表中rules 的描述列。) 您已在全局或作业中定义的自定义变量
variables:
    PRODUCTION_BRANCH: "main"

但是如果你的if: 依赖于自定义变量(即$PRODUCTION_BRANCH),它们本身需要变量插值......

variables:
    PRODUCTION_BRANCH: $CI_DEFAULT_BRANCH

...它不会工作。 $PRODUCTION_BRANCH 将在 RUNNER 中具有您期望的值(一旦作业开始),但 gitlab 在解析 yaml 并决定运行哪些作业时不会进行插值。

在您的情况下,最简单的方法就是直接在您的if: 中使用$CI_DEFAULT_BRANCH 变量。

示例.gitlab-ci.yml 演示此...

你可以把它放到一个新的空仓库中。只需更新 REPO_NAMESPACEREPO_NAMEONLY_DEPLOY_BRANCH 以匹配当前的 repo/branch。

工作:

debug - 运行并输出显示您期望的所有值的变量(在运行器上下文中) deploy1 - 运行 deploy2 - 运行 deploy3 - 运行(显示变量绝对没有在 gitlab 端插值)。
variables:
  REPO_NAMESPACE: "my-group/my-subgroup"
  REPO_NAME: "my-project"
  ONLY_DEPLOY_BRANCH: "main"
  ONLY_DEPLOY_FROM: "$REPO_NAMESPACE/$REPO_NAME"
  ONLY_DEPLOY_FROM2: "my-group/my-subgroup/my-project"



stages:
  - debug
  - deploy

# this runs
# variables all have expected values (in runner scope) and you would expect both deploy* jobs to run
debug:
  stage: debug
  script:
    - export  

# this runs
deploy1:
  stage: deploy
  image: alpine:latest
  rules:
    - if: $CI_PROJECT_PATH == $ONLY_DEPLOY_FROM2 && $CI_COMMIT_REF_SLUG == $ONLY_DEPLOY_BRANCH
      when: always
  script:
    - echo "Hello world!"

# this doesn't run.  
# Only difference to deploy1 job is using $ONLY_DEPLOY_FROM instead of $ONLY_DEPLOY_FROM2
# conclusion... gitlab must not do variable expansion of the variables section when determining which jobs run.
deploy2:
  stage: deploy
  image: alpine:latest
  rules:
    - if: $CI_PROJECT_PATH == $ONLY_DEPLOY_FROM && $CI_COMMIT_REF_SLUG == $ONLY_DEPLOY_BRANCH
      when: always
  script:
    - echo "Hello world!"

# this runs which confirms that $ONLY_DEPLOY_FROM has not had CI variables replaced.
deploy3:
  stage: deploy
  image: alpine:latest
  rules:
    - if: $ONLY_DEPLOY_FROM == "$REPO_NAMESPACE/$REPO_NAME" && $CI_COMMIT_REF_SLUG == $ONLY_DEPLOY_BRANCH
      when: always
  script:
    - echo "Hello world!"
    
    

您可以使用 ci linter (https://gitlab.com/$CI_PROJECT_PATH/-/ci/lint) 来玩这个。一般来说,它是一个很好的解决问题的工具,无需连续提交一千次到 .gitlab-ci.yml 并消耗共享运行时间。

未解决的问题

Gitlab 有大约 4 万个未解决的问题。不过这里是相关的门票......

Supporting variable expansion for runner(已解决)Supporting the gitlab side variable expansion -- 这个问题。仍然未解决的问题。

什么时候会修复(文档清晰或其他)......我不会屏住呼吸。

【讨论】:

这是一个很大的陷阱,并且极大地限制了针对仅自定义/除了作业配置的规则的使用。很好的答案!!!【参考方案2】:

只需将值放在引号中:

variables:
  PRODUCTION_BRANCH: "$CI_DEFAULT_BRANCH"

【讨论】:

以上是关于规则中无法识别 GitLab CI 自定义变量的主要内容,如果未能解决你的问题,请参考以下文章

变量 gitlab ci 中的变量

Gitlab Ci中自动生成版本号

由于禁止的秘密访问规则,无法在 gitlab-runner 中使用 helm upgrade

如何能够将变量传递给 gitlab ci 管道中的规则?

Gitlab - 无法对 CI 和 CD 构建的远程服务器进行身份验证

无法连接到 unix:///var/run/docker.sock 上的 Docker 守护程序。 docker 守护进程是不是正在运行?带有自托管运行器的 Gitlab Cloud CI/CD 错误