2. GitLab项目与仓库结构设计

发布治理的第一道防线不在流水线里,而在仓库结构里。如果群组、项目、分支和保护规则设计得随意,后续无论加多少审批、多少扫描、多少门禁,都会因为“结构本身没有表达发布意图”而失效。本节要解决的核心问题是:如何用 GitLab 的层级模型,把“谁在什么位置、对什么分支、做什么操作、触发什么发布结果”提前固化下来。

一、群组与子群组:把发布边界画在结构上

GitLab 的群组(Group)和子群组(Subgroup)不只是目录,它们同时是权限边界、变量继承边界和发布单元边界。面向发布治理,建议按“产品线 → 发布域 → 组件集”三层组织,而不是按人员或临时项目组织。

例如一个典型的三层结构:顶层群组 platform 代表平台产品线;其下子群组 platform/payment、platform/identity 代表发布域;再下一层 platform/payment/gateway、platform/payment/settlement 代表可独立发布的组件集。这样做的直接好处是:CI/CD 变量、Runner 标签、保护规则、发布审批人可以按层级继承,子项目只覆盖差异部分,避免每个项目重复配置。

需要特别注意的是,子群组会继承父群组的成员权限和 CI/CD 变量。因此不要把“临时实验项目”和“生产发布项目”放在同一父群组下,否则一次变量覆盖就可能把生产凭据暴露给实验项目。发布治理中常见的做法是:生产发布域单独建子群组,实验和沙箱放在 sandbox 子群组,两者不共享受保护变量。

二、项目:按“可独立发布单元”划分

项目(Project)是 GitLab 中仓库、Issue、MR、流水线、制品和环境的载体。划分项目时,判断标准不是代码量,而是“是否作为一个整体被发布”。如果一个模块的版本号、发布节奏、回滚动作必须和另一个模块绑定,它们应放在同一个项目;如果它们可以独立打标签、独立回滚,就应拆成不同项目。

常见的错误是把整个产品塞进一个巨型仓库,导致任何一次小改动都要走完整发布流程;另一种错误是按文件类型拆项目,导致一次发布要跨十几个仓库协调。面向发布治理,推荐“一个可独立发布单元 = 一个项目”,并在项目描述中明确:制品名、版本规则、目标环境、负责人。

三、分支模型:让分支名表达发布阶段

分支模型是发布治理的骨架。推荐采用“主干 + 发布分支 + 短生命周期特性分支”的模型:

  • main:始终可发布,代表下一个版本的集成状态,禁止直接推送。
  • release/x.y:从 main 切出,用于稳定版本,只接受修复类合并。
  • feature/*、fix/*:短生命周期分支,合并后删除。
  • hotfix/*:从 release/x.y 切出,修复后同时回合 main 和发布分支。

分支命名必须可被流水线规则识别。例如流水线中用 $CI_COMMIT_BRANCH =~ /^release\/\d+\.\d+$/ 判断是否进入发布构建,用 $CI_COMMIT_TAG 判断是否触发正式制品归档。这样分支名本身就是发布信号,不需要人工在流水线里再选一次。

四、保护规则:把“谁能动什么”写成可执行约束

保护规则(Protected Branch / Protected Tag)是发布治理从“约定”变成“强制”的关键。建议至少配置以下规则:

对象允许合并允许推送允许强制推送
mainMaintainerNo one否
release/*MaintainerNo one否
v* 标签—Maintainer否

保护规则要与合并请求审批、流水线状态检查配合使用。例如在 main 上开启“合并前必须通过流水线”和“至少 1 名审批人”,在 release/* 上开启“仅允许合并修复类 MR”。这样即使有人误操作,也会被规则拦截,而不是靠事后审计发现。

五、结构落地示例

下面给出一个可直接参考的群组与项目结构示例,用于说明层级、分支和保护规则的对应关系:

platform/                          # 顶层群组:平台产品线
├── payment/                       # 子群组:支付发布域
│   ├── gateway/                   # 项目:支付网关(可独立发布)
│   │   ├── main                   # 保护:Maintainer 合并,禁止推送
│   │   ├── release/1.4            # 保护:仅修复类 MR
│   │   └── v1.4.0                 # 保护标签:Maintainer 创建
│   └── settlement/                # 项目:结算服务
│       ├── main
│       └── release/2.1
└── identity/                      # 子群组:身份发布域
    └── auth/                      # 项目:认证服务
        ├── main
        └── release/3.0

在这个结构中,platform/payment 子群组可以统一配置支付域的 Runner 标签和发布审批人,gateway 和 settlement 各自维护自己的版本分支。发布时,流水线根据分支名自动判断是集成构建还是发布构建,保护规则确保只有 Maintainer 能合并到 main 和 release/*。

面向发布治理的 GitLab 群组、项目与分支保护结构 顶层群组 platform 继承:Runner 标签、发布审批人、受保护变量 子群组 platform/payment 发布域:支付 项目 gateway main:Maintainer 合并,禁止推送 release/1.4:仅修复类 MR 标签 v1.4.0:Maintainer 创建 项目 settlement main:Maintainer 合并,禁止推送 release/2.1:仅修复类 MR 标签 v2.1.0:Maintainer 创建 子群组 platform/identity 发布域:身份 项目 auth main:Maintainer 合并,禁止推送 release/3.0:仅修复类 MR 标签 v3.0.0:Maintainer 创建 子群组 sandbox 实验项目,不共享生产变量 无保护分支,无发布权限 顶层群组 发布域子群组 可独立发布项目 沙箱隔离区

最后需要强调:结构设计不是一次性的。每当出现新的发布域、新的独立发布单元或新的合规要求时,都应回到群组层级、项目边界和保护规则上重新审视。发布治理的稳定性,来自结构对发布意图的持续表达,而不是来自某一次配置的完整。