条件与规则 #

一、条件执行概述 #

GitLab CI提供了两种条件执行机制:only/except(旧语法)和rules(新语法)。

text
┌─────────────────────────────────────────────────────────────┐
│                    条件执行机制                              │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  only/except (旧语法)        rules (新语法)                  │
│  ┌─────────────────┐        ┌─────────────────┐            │
│  │ • 简单条件      │        │ • 复杂条件      │            │
│  │ • 单一判断      │        │ • 多条件组合    │            │
│  │ • 不够灵活      │        │ • if/when/exists │            │
│  │                 │        │ • 变量设置      │            │
│  │ • 推荐迁移      │        │ • 推荐使用      │            │
│  └─────────────────┘        └─────────────────┘            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

二、only/except语法 #

基本用法 #

yaml
job_name:
  script: echo "Hello"
  only:
    - main

分支条件 #

yaml
deploy_production:
  script: echo "Deploying..."
  only:
    - main
    - release

排除分支 #

yaml
test:
  script: npm test
  except:
    - main

标签条件 #

yaml
release:
  script: echo "Creating release..."
  only:
    - tags

合并请求 #

yaml
test:
  script: npm test
  only:
    - merge_requests

触发源 #

yaml
deploy:
  script: echo "Deploying..."
  only:
    variables:
      - $CI_PIPELINE_SOURCE == "schedule"

正则表达式 #

yaml
deploy:
  script: echo "Deploying..."
  only:
    - /^release-.*$/

组合条件 #

yaml
deploy:
  script: echo "Deploying..."
  only:
    refs:
      - main
    variables:
      - $DEPLOY == "true"
    changes:
      - Dockerfile

only/except关键字 #

关键字 说明
refs 分支或标签
variables 变量条件
changes 文件变更
kubernetes Kubernetes服务

三、rules语法 #

基本用法 #

yaml
job_name:
  script: echo "Hello"
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

if条件 #

yaml
deploy_production:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
    - when: never

多条件 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_BRANCH == "develop"
    - when: never

when关键字 #

yaml
job_name:
  script: echo "Hello"
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: always
    - if: $CI_COMMIT_BRANCH == "develop"
      when: manual
    - when: never
说明
always 总是执行
never 从不执行
on_success 前面Job成功时执行(默认)
on_failure 前面Job失败时执行
manual 手动执行
delayed 延迟执行

exists条件 #

检查文件是否存在:

yaml
docker_build:
  script: docker build .
  rules:
    - exists:
        - Dockerfile

changes条件 #

检查文件是否变更:

yaml
build:
  script: npm run build
  rules:
    - changes:
        - package.json
        - package-lock.json
        - src/**/*

variables条件 #

设置变量:

yaml
deploy:
  script: echo "Deploying to $DEPLOY_ENV"
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      variables:
        DEPLOY_ENV: "production"
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        DEPLOY_ENV: "staging"

allow_failure #

yaml
lint:
  script: npm run lint
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      allow_failure: false
    - allow_failure: true

四、复杂条件组合 #

AND条件 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main" && $DEPLOY == "true"

OR条件 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"

正则匹配 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release-.*$/

正则不匹配 #

yaml
test:
  script: npm test
  rules:
    - if: $CI_COMMIT_BRANCH !~ /^docs-.*$/

组合示例 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
      allow_failure: false
      variables:
        DEPLOY_ENV: production
    - if: $CI_COMMIT_BRANCH == "develop"
      when: always
      variables:
        DEPLOY_ENV: staging
    - when: never

五、workflow规则 #

控制Pipeline创建 #

yaml
workflow:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: always
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: always
    - when: never

避免重复Pipeline #

yaml
workflow:
  rules:
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
      when: never
    - when: always

设置Pipeline变量 #

yaml
workflow:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      variables:
        DEPLOY_ENV: production
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        DEPLOY_ENV: staging

六、only/except迁移到rules #

简单迁移 #

yaml
deploy:
  script: echo "Deploying..."
  only:
    - main

迁移后:

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

复杂迁移 #

yaml
deploy:
  script: echo "Deploying..."
  only:
    refs:
      - main
    variables:
      - $DEPLOY == "true"
    changes:
      - Dockerfile

迁移后:

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: $CI_COMMIT_BRANCH == "main" && $DEPLOY == "true"
      changes:
        - Dockerfile

except迁移 #

yaml
test:
  script: npm test
  except:
    - main

迁移后:

yaml
test:
  script: npm test
  rules:
    - if: $CI_COMMIT_BRANCH != "main"

七、条件表达式 #

比较运算符 #

运算符 说明
== 等于
!= 不等于
=~ 正则匹配
!~ 正则不匹配

逻辑运算符 #

运算符 说明
&&
`
!

括号分组 #

yaml
deploy:
  script: echo "Deploying..."
  rules:
    - if: ($CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop") && $DEPLOY == "true"

八、最佳实践 #

1. 使用rules替代only/except #

yaml
deploy:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - echo "Deploying..."

2. 设置默认规则 #

yaml
default:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: always
    - when: never

3. 使用变量简化条件 #

yaml
variables:
  PRODUCTION_BRANCH: "main"
  STAGING_BRANCH: "develop"

deploy_production:
  rules:
    - if: $CI_COMMIT_BRANCH == $PRODUCTION_BRANCH
  script:
    - echo "Deploying..."

4. 组合使用多种条件 #

yaml
deploy:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      exists:
        - Dockerfile
      changes:
        - src/**/*
      when: manual
  script:
    - echo "Deploying..."

5. 使用workflow统一控制 #

yaml
workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_BRANCH == "develop"
    - when: never

九、常见场景 #

1. MR流水线 #

yaml
test:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - npm test

2. 定时任务 #

yaml
nightly_build:
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
  script:
    - npm run build

3. 手动部署 #

yaml
deploy_production:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
  script:
    - echo "Deploying..."

4. 条件部署 #

yaml
deploy:
  rules:
    - if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_MESSAGE =~ /\[deploy\]/
  script:
    - echo "Deploying..."

5. 文件变更触发 #

yaml
docker_build:
  rules:
    - changes:
        - Dockerfile
        - docker-compose.yml
  script:
    - docker build .

十、完整示例 #

多环境部署 #

yaml
stages:
  - test
  - deploy

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_BRANCH == "develop"
    - when: never

test:
  stage: test
  rules:
    - when: always
  script:
    - npm test

deploy_staging:
  stage: deploy
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"
      when: always
  script:
    - echo "Deploying to staging..."

deploy_production:
  stage: deploy
  environment:
    name: production
    url: https://example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
      allow_failure: false
  script:
    - echo "Deploying to production..."

cleanup:
  stage: deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"
      when: manual
  script:
    - echo "Cleaning up..."

下一步 #

现在你已经掌握了条件与规则的使用,接下来让我们学习 Runner基础

最后更新:2026-03-28