gitlab ci 推荐使用 rules 替代已废弃的 only/except,通过 if 表达式匹配分支(如 main、develop、feature/*)并结合 $ci_pipeline_source 等变量精准控制作业触发,支持手动确认、环境隔离与变更过滤。

GitLab CI 的 only 和 except 规则(现推荐使用 rules)可用于精准控制流水线在哪些分支上触发,从而实现按分支定制发布行为——比如 main 自动部署到生产环境,develop 部署到测试环境,而 feature/* 分支只运行单元测试、不发布。
用 rules 替代已废弃的 only/except
GitLab 12.3+ 已将 only/except 标记为废弃,rules 更灵活、可读性更强,且支持条件组合与作业级控制。它基于 if 表达式匹配 ref(分支名、标签、合并请求等),并决定是否包含该作业。
- 用
if: $CI_COMMIT_BRANCH == "main"匹配主干分支 - 用
if: $CI_COMMIT_BRANCH =~ /^develop$/精确匹配 develop - 用
if: $CI_COMMIT_BRANCH =~ /^feature\/.*/匹配所有 feature 分支 - 可用
- when: never显式跳过特定情况,比except更可控
按分支执行不同发布目标
一个典型的多环境发布配置,可在单个 .gitlab-ci.yml 中定义多个部署作业,各自通过 rules 绑定对应分支:
-
生产发布作业:仅当推送至
main且非合并请求时运行,并要求手动确认 -
测试环境部署作业:对
develop分支自动部署,跳过 MR 合并流程 -
预发验证作业:针对
release/*分支构建镜像并推送到私有仓库,但不触发部署
每个作业可调用不同脚本、设置不同环境变量(如 DEPLOY_ENV=prod),或调用不同部署工具(Ansible Playbook / kubectl apply / Terraform apply)。
避免意外触发的关键细节
仅靠分支名匹配还不够,需结合上下文排除干扰场景:
- 添加
if: $CI_PIPELINE_SOURCE == "push"排除 MR 创建、定时任务等非推送来源 - 对需要人工干预的发布作业,加上
when: manual并配合allow_failure: false,防止误点跳过 - 使用
changes:进一步限定:例如只有src/或Dockerfile变更时才触发构建,减少无关提交的开销 - 注意
rules是从上到下匹配,第一条满足即生效;如需“默认不运行”,末尾加- when: never
示例:简洁可复用的分支发布模板
以下是一个带注释的最小可行配置片段:
deploy-to-prod:
stage: deploy
script: ./scripts/deploy.sh prod
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"
when: manual
- when: never
<p>deploy-to-staging:
stage: deploy
script: ./scripts/deploy.sh staging
rules:</p>
- if: $CI_COMMIT_BRANCH == "develop" && $CI_PIPELINE_SOURCE == "push"
- when: never
test-only: stage: test script: pytest tests/ rules:
- if: $CI_COMMIT_BRANCH =~ /^feature\/.*/
- if: $CI_COMMIT_TAG when: never
- when: on_success
这个结构清晰分离了职责,既保障了 main 分支发布的严谨性,又让特性分支保持轻量高效。











