You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitLab CI中If/Else条件分支不生效问题排查

问题

我配置了如下GitLab CI脚本,期望实现:

  • 当打如staging.v1这类staging开头的Git标签时,执行对应的staging构建与发布逻辑;
  • 当在develop分支打如v1.0.1这类v开头的标签时,执行生产环境的构建与发布逻辑。

但实际条件分支未触发,无报错信息,仅显示命令折叠后直接完成任务。配置脚本如下:

include:
  - project: templates/gitlab-templates
    file: sorush.gitlab-ci.yml

stages:
  - build
  - release


variables:
  OKD_REGISTRY_BALY: "registry.apps.internal.okd.eu-central-1.cloud.baly.app"
  OKD_REGISTRY_BALY_STAGING: "registry.apps.internal.okd.eu-central-1.cloud.baly.app"

  OKD_PROJECT_BALY: baly-dpn-blitz
  OKD_PROJECT_BALY_STAGING: baly-dpn-blitz
  
  CONTAINER_REGISTRY_IMAGE_TAG_API_BALY: "api_baly_latest"
  CONTAINER_REGISTRY_IMAGE_TAG_API_BALY_STAGING: "api_baly_staging"
  CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE: "feature_update_baly_latest"
  CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE_STAGING: "feature_update_baly_staging"
  
  CONTAINER_REGISTRY_USERNAME: 'gitlab-ci'
  CONTAINER_REGISTRY_PASSWORD: ${OKD_BALY_TOKEN}
  OKD_CONSOLE_URL: https://api.okd.eu-central-1.cloud.baly.app:6443

build:
  stage: build
  image: docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY 
  script: |
      if [[ $CI_COMMIT_TAG =~ ^staging.*$ ]]; then
        echo "Building staging...."
        docker build -t ${CI_REGISTRY_IMAGE}:api_baly_staging_${CI_COMMIT_REF_SLUG} --file api_baly_dockerfile.dockerfile .
        docker build -t ${CI_REGISTRY_IMAGE}:feature_update_baly_staging_${CI_COMMIT_REF_SLUG} --file api_baly_dockerfile.dockerfile .
        docker push ${CI_REGISTRY_IMAGE}:api_baly_staging_${CI_COMMIT_REF_SLUG}
        docker push ${CI_REGISTRY_IMAGE}:feature_update_baly_staging_${CI_COMMIT_REF_SLUG}
      elif [[ $CI_COMMIT_TAG =~ ^v.*$ && "$CI_COMMIT_BRANCH" == "develop" ]]; then
        echo "Building production...."
        docker build -t ${CI_REGISTRY_IMAGE}:api_baly_${CI_COMMIT_REF_SLUG} --file api_baly_dockerfile.dockerfile .
        docker build -t ${CI_REGISTRY_IMAGE}:feature_update_baly_${CI_COMMIT_REF_SLUG} --file api_baly_dockerfile.dockerfile .
        docker push ${CI_REGISTRY_IMAGE}:api_baly_${CI_COMMIT_REF_SLUG}
        docker push ${CI_REGISTRY_IMAGE}:feature_update_baly_${CI_COMMIT_REF_SLUG}
      fi
  rules:
    - if: '$CI_COMMIT_TAG =~ /staging.*$/'
      when: always 
    - if: '$CI_COMMIT_TAG =~ /v.*$/'
      when: always 



.release-cloud: &release-cloud

  rules:
    - if: '$CI_COMMIT_TAG =~ /staging.*$/'
      when: always 
    - if: '$CI_COMMIT_TAG =~ /v.*$/'
      when: always 
  image: docker:dind
  stage: release
 

  before_script: 
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - if [[ "$CI_COMMIT_TAG" =~ ^staging.*$ ]]; then docker pull ${CI_REGISTRY_IMAGE}:api_baly_staging_${CI_COMMIT_REF_SLUG}; docker pull ${CI_REGISTRY_IMAGE}:feature_update_baly_staging_${CI_COMMIT_REF_SLUG}; fi
    - if [[ "$CI_COMMIT_TAG" =~ ^v.*$ ]]; then docker pull ${CI_REGISTRY_IMAGE}:api_baly_${CI_COMMIT_REF_SLUG}; docker pull ${CI_REGISTRY_IMAGE}:feature_update_baly_${CI_COMMIT_REF_SLUG}; fi
    - docker logout $CI_REGISTRY


  script: |
    
    if [[ $CI_COMMIT_TAG =~ ^staging.*$ ]];  then
      docker login -u ${CONTAINER_REGISTRY_USERNAME} -p ${CONTAINER_REGISTRY_PASSWORD} ${OKD_REGISTRY} 
      docker tag ${CI_REGISTRY_IMAGE}:api_baly_staging_${CI_COMMIT_REF_SLUG} ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_API_BALY_STAGING}
      docker tag ${CI_REGISTRY_IMAGE}:feature_update_baly_staging_${CI_COMMIT_REF_SLUG} ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE_STAGING}
      docker push ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_API_BALY_STAGING}
      docker push ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE_STAGING}

    elif [[ $CI_COMMIT_TAG =~ ^v.*$ && "$CI_COMMIT_BRANCH" == "develop" ]]; then
      docker login -u ${CONTAINER_REGISTRY_USERNAME} -p ${CONTAINER_REGISTRY_PASSWORD} ${OKD_REGISTRY} 
      docker tag ${CI_REGISTRY_IMAGE}:api_baly_${CI_COMMIT_REF_SLUG} ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_API_BALY}
      docker tag ${CI_REGISTRY_IMAGE}:feature_update_baly${CI_COMMIT_REF_SLUG} ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE}
      docker push ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_API_BALY}
      docker push ${CONTAINER_REGISTRY_IMAGE}:${CONTAINER_REGISTRY_IMAGE_TAG_FEATURE_BALY_UPDATE}
    fi
  


Release (baly):
  variables:
    DOCKER_DRIVER: overlay2
    CONTAINER_REGISTRY_PASSWORD: ${OKD_BALY_TOKEN}
    OKD_REGISTRY: ${OKD_REGISTRY_BALY}
    CONTAINER_REGISTRY_IMAGE: "$OKD_REGISTRY_BALY/$OKD_PROJECT_BALY/$CI_PROJECT_NAME"
  <<: *release-cloud

执行日志显示:

Login Succeeded
$ if [[ $CI_COMMIT_TAG =~ ^staging.*$ ]]; then # collapsed multi-line command
Cleaning up project directory and file based variables 00:01
Job succeeded


问题排查与修复方案

1. 标签流水线中CI_COMMIT_BRANCH变量为空

GitLab在标签触发的流水线中不会设置CI_COMMIT_BRANCH变量,你脚本中用"$CI_COMMIT_BRANCH" == "develop"判断生产分支的逻辑永远不成立,导致生产构建/发布代码块从未执行。

修复:
改用Git命令检查当前标签对应的提交是否属于develop分支:

elif [[ $CI_COMMIT_TAG =~ ^v.*$ ]]; then
  # 检查标签关联的提交是否在develop分支上
  if git branch --contains $CI_COMMIT_SHA | grep -q develop; then
    echo "Building production...."
    # 原生产构建逻辑
  fi

2. 正则匹配规则不精准

你在rules中使用的正则/staging.*$/和/v.*$/没有限制开头匹配,可能导致意外匹配。同时生产标签的rules没有限制分支,会触发不必要的流水线。

修复:
更新build和.release-cloud的rules,使用更精准的正则:

# build阶段rules修改
rules:
  - if: '$CI_COMMIT_TAG =~ /^staging\..+$/'
    when: always 
  - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
    when: always 

# .release-cloud的rules同步修改
rules:
  - if: '$CI_COMMIT_TAG =~ /^staging\..+$/'
    when: always 
  - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
    when: always 

3. 镜像标签拼接错误

release阶段生产逻辑中,镜像标签少了下划线:

docker tag ${CI_REGISTRY_IMAGE}:feature_update_baly${CI_COMMIT_REF_SLUG} ...

应该改为feature_update_baly_${CI_COMMIT_REF_SLUG},和build阶段的镜像标签保持一致,否则会找不到镜像导致命令静默失败。

4. 缺少错误检查与日志输出

当前脚本没有错误终止机制,命令失败后会继续执行,且折叠命令无法看到具体错误。

修复:
在脚本开头添加set -euo pipefail,让脚本在命令失败时立即终止;同时展开折叠命令或增加关键步骤的日志输出:

script: |
  set -euo pipefail
  if [[ $CI_COMMIT_TAG =~ ^staging.*$ ]]; then
    echo "Starting staging release..."
    # 后续逻辑
  fi

5. 环境变量未区分环境

当前staging和生产的OKD_REGISTRY_BALY、OKD_PROJECT_BALY变量值完全相同,会导致两个环境发布到同一地址,需确认是否是配置失误。如果需要区分,可在release阶段根据标签类型动态设置变量:

Release (baly):
  variables:
    DOCKER_DRIVER: overlay2
    CONTAINER_REGISTRY_PASSWORD: ${OKD_BALY_TOKEN}
  <<: *release-cloud
  rules:
    - if: '$CI_COMMIT_TAG =~ /^staging\..+$/'
      variables:
        OKD_REGISTRY: ${OKD_REGISTRY_BALY_STAGING}
        CONTAINER_REGISTRY_IMAGE: "$OKD_REGISTRY_BALY_STAGING/$OKD_PROJECT_BALY_STAGING/$CI_PROJECT_NAME"
    - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
      variables:
        OKD_REGISTRY: ${OKD_REGISTRY_BALY}
        CONTAINER_REGISTRY_IMAGE: "$OKD_REGISTRY_BALY/$OKD_PROJECT_BALY/$CI_PROJECT_NAME"

内容的提问来源于stack exchange,提问作者MarziehSepehr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 00:44:54