GitLab CI变量存储正则表达式后规则不生效问题排查
GitLab CI 变量引用正则表达式失效问题
我正在配置GitLab CI文件,尝试用变量复用SemVer正则表达式,但配置未按预期运行:即使存在符合规则的tag,dev任务仍始终启动,而prod和staging任务从未执行。
错误的配置代码:
variables: SEMVER_REGEX: '/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/' include: - local: ci/dev.yaml rules: - if: '$CI_COMMIT_TAG !~ $SEMVER_REGEX' - local: ci/staging.yaml rules: - if: '$CI_COMMIT_TAG =~ $SEMVER_REGEX' - local: ci/prod.yaml rules: - if: '$CI_COMMIT_TAG =~ $SEMVER_REGEX'
若移除变量,直接将正则表达式写入规则中,就能正常工作(但写法不够优雅):
include: - local: ci/dev.yaml rules: - if: '$CI_COMMIT_TAG !~ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/' - local: ci/staging.yaml rules: - if: '$CI_COMMIT_TAG =~ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/' - local: ci/prod.yaml rules: - if: '$CI_COMMIT_TAG =~ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/'
使用版本:GitLab v16.9.2
问题原因
GitLab CI的if条件中,变量会被当作字符串字面量替换,而非正则表达式模式。当你写$CI_COMMIT_TAG =~ $SEMVER_REGEX时,实际执行的是判断tag是否等于变量SEMVER_REGEX的字符串值(包括前后的/符号),而非用正则去匹配tag。这就导致:
$CI_COMMIT_TAG =~ $SEMVER_REGEX永远为假,所以staging和prod任务不会执行$CI_COMMIT_TAG !~ $SEMVER_REGEX永远为真,所以dev任务始终启动
优雅的解决办法
使用YAML锚点(Anchor)来复用正则表达式,既避免重复代码,又能让GitLab正确解析正则模式:
# 定义可复用的锚点 .semver_match_rule: &semver_match_rule if: '$CI_COMMIT_TAG =~ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/' .semver_not_match_rule: &semver_not_match_rule if: '$CI_COMMIT_TAG !~ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/' include: - local: ci/dev.yaml rules: - *semver_not_match_rule - local: ci/staging.yaml rules: - *semver_match_rule - local: ci/prod.yaml rules: - *semver_match_rule
这样既保持了代码的简洁性,又能让GitLab正确解析正则表达式规则。
内容的提问来源于stack exchange,提问作者DamDam
相关产品推荐
相关产品推荐

