4. 项目初始化与代码仓库搭建:Git仓库创建、分支策略(Git Flow/Trunk Based)、项目目录结构设计
本章是实战课程的基石。一个多租户SaaS鉴权拦截链路项目,从第一天起就需要在代码仓库、分支策略和目录结构上做出正确决策。错误的仓库初始化会导致后续CI/CD流水线频繁冲突、部署混乱,甚至安全漏洞。我们将从零开始,搭建一个符合企业级标准的Git仓库,并设计一套既能支撑快速迭代、又能保障多租户隔离的目录结构。
4.1 Git仓库创建与初始化
我们采用单仓库多模块(Monorepo)策略,将鉴权核心、租户管理、网关拦截、公共库等所有组件放在同一个Git仓库中。这有利于统一版本管理、原子化提交和跨组件重构。
选型建议: 对于多租户SaaS项目,Monorepo比多仓库(Multi-Repo)更适合,因为租户上下文、鉴权策略、共享模型频繁跨模块变更,单仓库可避免“依赖地狱”和版本漂移。
4.1.1 初始化步骤
- 创建远程仓库(以GitLab为例):在GitLab上新建空白项目,命名为
saas-auth-gateway,可见性设为Private。 - 克隆到本地:
git clone git@gitlab.example.com:devops/saas-auth-gateway.git - 初始化README和.gitignore:创建标准
.gitignore(Java/Maven/Node.js混合模板),并写入项目简介。 - 创建初始提交:
git add . && git commit -m "chore: initial project scaffold" - 推送主干:
git push origin main
关键配置: 在仓库设置中开启 “仅允许通过Merge Request合并” 和 “删除源分支”,确保主干分支受保护,防止直接推送。
4.2 分支策略:Git Flow vs Trunk Based
分支策略直接影响CI/CD流水线的触发频率、部署节奏和团队协作效率。下表对比了两种主流策略在本项目中的适用性。
| 维度 | Git Flow | Trunk Based (主干开发) |
|---|---|---|
| 分支数量 | 多(develop, release, hotfix, feature) | 少(main + 短期特性分支) |
| 合并频率 | 低(按版本合并) | 高(每日多次合并到主干) |
| CI/CD触发 | 按分支类型触发不同流水线 | 每次提交到主干即触发全量流水线 |
| 多租户热修复 | 从主干拉hotfix分支,修复后合并回主干和release | 直接在主干修复,通过特性开关控制发布 |
| 推荐场景 | 固定版本发布、有长期支持分支 | 持续部署、SaaS高频迭代 |
本项目选择Trunk Based + 短期特性分支策略。原因:多租户SaaS需要每天多次部署,主干开发配合特性开关(Feature Toggle)可以快速上线租户特定功能,同时保持主干始终可发布。
4.2.1 分支命名规范
- 主干:
main(受保护,始终可部署) - 特性分支:
feat/租户ID-简短描述,例如feat/tenant-abc-oidc-support - 修复分支:
fix/issue-id-简短描述,例如fix/1234-token-expiry - 配置分支:
config/租户ID-环境,例如config/tenant-abc-staging
避坑提示: 不要将租户特定配置直接提交到
main 分支的默认配置文件中。应使用配置分支 + 环境变量注入,避免租户A的配置泄露到租户B的部署中。
4.3 项目目录结构设计
目录结构需要同时满足模块化、多租户隔离和CI/CD流水线可读性。我们采用分层+领域驱动设计(DDD)风格。
saas-auth-gateway/
├── .gitlab-ci.yml # GitLab CI/CD 主流水线定义
├── .gitignore
├── README.md
├── pom.xml # 父POM(Maven多模块聚合)
│
├── saas-auth-core/ # 鉴权核心库(JWT、OAuth2、Session管理)
│ ├── pom.xml
│ └── src/
│ ├── main/java/com/saas/auth/core/
│ │ ├── token/ # Token生成与验证
│ │ ├── tenant/ # 租户上下文解析
│ │ └── policy/ # 鉴权策略接口
│ └── test/
│
├── saas-tenant-manager/ # 租户管理服务(CRUD、配置、密钥)
│ ├── pom.xml
│ └── src/
│ ├── main/java/com/saas/tenant/
│ │ ├── controller/ # REST API
│ │ ├── service/ # 租户注册、密钥轮换
│ │ └── repository/ # 数据库访问
│ └── test/
│
├── saas-gateway/ # API网关(拦截、路由、限流)
│ ├── pom.xml
│ └── src/
│ ├── main/java/com/saas/gateway/
│ │ ├── filter/ # 鉴权过滤器链
│ │ ├── route/ # 动态路由(按租户)
│ │ └── rate-limit/ # 租户级限流
│ └── test/
│
├── saas-common/ # 公共工具库(DTO、异常、常量)
│ ├── pom.xml
│ └── src/main/java/com/saas/common/
│ ├── dto/ # 统一响应体
│ ├── exception/ # 全局异常定义
│ └── util/ # 加密、日期工具
│
├── deploy/ # 部署与配置
│ ├── docker/ # Dockerfile(每个模块一个子目录)
│ │ ├── gateway.Dockerfile
│ │ ├── tenant-manager.Dockerfile
│ │ └── ...
│ ├── k8s/ # Kubernetes 清单
│ │ ├── base/ # 基础资源(Namespace、ServiceAccount)
│ │ └── overlays/ # 环境差异(dev/staging/prod)
│ └── scripts/ # 数据库迁移、密钥初始化脚本
│
└── docs/ # 架构文档、API手册、流水线说明
├── architecture.md
└── ci-cd-pipeline.md
4.3.1 目录设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 按领域拆分模块 | 每个Maven模块对应一个独立部署单元 | saas-gateway 可独立构建镜像 |
| 租户配置外置 | 租户密钥、限流阈值不硬编码在代码中 | 通过 deploy/k8s/overlays/ 的ConfigMap注入 |
| 流水线文件根级 | .gitlab-ci.yml 放在根目录,便于CI发现 |
流水线可引用 deploy/scripts/ 下的脚本 |
| 测试与源码同级 | 每个模块内 src/test/ 与 src/main/ 并列 |
便于Maven标准构建生命周期 |
4.4 分支策略与目录结构的协同关系
下图展示了Trunk Based分支策略下,特性分支如何与目录结构交互,最终触发CI/CD流水线。
4.5 初始化后的验证清单
完成仓库搭建后,执行以下验证确保基础正确:
- 分支保护:确认
main分支已开启“不允许直接推送”、“必须通过MR合并”、“至少1名审批人”。 - CI触发测试:推送一个空特性分支,确认
.gitlab-ci.yml被解析且流水线进入pending状态。 - 目录可构建性:在根目录执行
mvn clean compile -pl saas-auth-core -am,确认模块依赖正确。 - Dockerfile可访问:确认
deploy/docker/gateway.Dockerfile能正确引用saas-gateway/target/*.jar。
最佳实践: 在仓库根目录添加
.editorconfig 和 .pre-commit-config.yaml,统一缩进、编码格式,并在提交前自动运行静态检查(如Checkstyle、ESLint),从源头减少流水线失败。
至此,项目初始化与代码仓库搭建完成。下一阶段我们将基于此仓库结构,编写多租户鉴权核心代码,并配置第一版CI流水线。