[[_TOC_]]
# 1. 生产环境,代码版本原则
### 1.1.保证Master不做代码开发
- 保证Master在任何情况下可以分支打包
- 保证Master在任何情况下可以分支开发
- Master是稳定代码分支
### 1.2.一定要先pull(获取)代码后,再做冲突解决,再合并提交,再推送到远端
- 拉取代码避免覆盖提交。
- 在分支推送前,一般需要先将远端Master或者远端修改分支合并到自己分支,解决冲突再提交,下面【规范】会提及
- 独立代码仓库的Dll模块,一般是单人独立开发,更简单,后面提及
- 本地获取了代码,解决冲突了,本地测试,跑单元测试都检查一遍了,再推送远端
### 1.3.Master必须打Tag,每次发布测试成功后,可上线前,先合并到Master并打Tag,再上线
- Master是稳定的代码基线,一般不成功的代码不能推送到此分支
- Master默认都需要加入pull request权限和推送权限,增加了review流程和责任人管理
- Tag作用是能够追踪代码,和紧急情况hotfix,是所有分支的起点
### 1.4. Release由专门管理发布人员管理,发布人对当天产品发布要求了解,能够选择性要求发布。
# 2. 生产环境,分支管理的规范
>实际的分支管理有很多模式,如:MainLine、TBD、Gitflow、githubflow、gitlabflow、Aoneflow
其中TBD、githubflow和Aoneflow最适合我们
  按照上面的原则,我们实际生产是以下实现方案。
### 2.1. 两人以上开发的单服务应用,初期推荐使用的是Githubflow的分支策略
>官网:[gitHubFlow](https://guides.github.com/introduction/flow/)
  这里前提主要说明的是微服务的**单个服务应用,并且偏功能大的2人以上开发的服务,特别是单体**,一般单个服务应用都会在一个代码仓库中开发。
**整体图**

**注意说明:**
- 长时分支不推荐,尽可能的小版本提交更新,以发布的角度出发,每天更新发布几个版本
- 正常情况,是feature1.1.x, 到 hotfix补丁更新,到feature1.3.x ,持续一个迭代一个迭代进行
- **极端实际**,是feature1.2.x,和上面的1.1.x好hotfix并行,**尽量在feature管理中,将同时期上线功能归在一个feature版本内开发,开发人员之间分模块,不冲突**,大家同在一个feature分支开发,通过自己本地git分支管理
- **feature分支的修改内容,一般是同一时期同一版本号更新的功能归在一个版本**。</br>比如:`feature/计费流程-1.1.0` 包含下面代码功能
| 服务 | 模块 | 功能 | 人员 |
| -- |-- | -- | -- |
| 仪表 | 仪表档案 | 加入计费标准属性设置 | 张三 |
| 仪表 | 抄表计划 | 加入计费抄表、费用计算 | 李四 |
| 合同 | 合同档案 | 加入计费标准选择 | 老王 |
| 付款 | 支付方式 | 加入支付宝、微信付费 | 爱莎 |
| 付款 | sagas模块 | 加入计费saga模型 | 爱莎 |
以上功能都应该安排在一个feature/1.1.0版本,各模块有专人负责开发,单体同一代码仓库,微服务是不同仓库
- Release和PR评审有专门负责人,负责人有权了解管理当天产品版本发布情况和要求
- PR是Pull Request,严格来说,参与并行开发此模块的人都应该一起评审代码,团队可灵活配合让有经验的带实习,有经验评审即可,**合并默认会有自动合并功能,有冲突不能合并**,很有可能是之前有人先一步更新了Master,这时候应该要求分支开发人员做一次Rebase后再Merge,把主干合并到他的分支进行测试和修改冲突,ok了再提交请求进行完成。
### 2.2. 独立仓库的模块开发,单人开发的单服务应用,推荐TBD
  这里前提说明的是:独立仓库的公共模块等DLL,比如NServiceBus模块,日志模块等独立开发的组件模块等。因为,独立组件模块,一般是由单人开发,属于代码持续集成,所以不需要太复杂的分支模型,但是需要有版本管理,并发布到Nuget包管理仓库中。
  **分支策略推荐TBD,类似上面gitflow去掉PR,并要Dll保证两个要求:**
- 未稳定版本,还在测试的版本,要按照下面的nuget标签说明,打标记
- 稳定版本可以不断升级,这需要每一次稳定版本发布时候,代码Master打上Tag
**Nuget打包标签说明:**
α(Alpha)版:内测版,内部交流或者专业测试人员测试用。Bug较多,普通用户最好不要安装。
`版本标签:版本号-Alpha ,如:1.1.0-Alpha,以下雷同`
β(Beta)版:公测版,专业爱好者大规模测试用,存在一些缺陷,该版本也不适合一般用户安装。
`版本标签:版本号-Bet`
RC版:是 Release Candidate 的缩写,意思是发布倒计时,候选版本,处于Gamma阶段,该版本已经完成全部功能并清除大部分的BUG。到了这个阶段只会除BUG,不会对软件做任何大的更改。
版本号:就是正式版
##### TBD模式
  dll模块,单人开发的简单服务应用可应用此模式。
  另外,**hotfix 和 补丁Tag都在分支上加,并且Release分支在下一个分支没有发布前,不能被删除,不熟悉的时候,减少挑拣方式到分支。**

### 2.3.后期上线后,成熟的团队,多人开发的服务应用,Aoneflow模式
  Aoneflow是阿里内部规范,前面的分支部分和上面的方案都一样,主要是改进了CD的流程,让发布更灵活,特别是遇到1.1.x feature版本用户已经测试成功,代码都提交了,准备发布生产,此时市场原因客户临时不要了直接上线其他1.2.x功能,不需要手工剔除代码,直接重新启一个发布分支重新选择需要合并的1.2.x分支即可发布。
**feature分支图**

**发布分支图**

**合并主干图**

# 3. 持续部署阶段
### 原则
- 部署和持续集成是分离的,无论前面CI、版本分支管理使用什么模式,**发布和部署阶段,只认Release分支即可**。</br>所有的pipeline中的触发器,只认发布的分支,这是前期约定好的。**下面5. 分支和pipeline的结合流程说明**有说明具体流程。
- **在项目开始后,发布人员和开发经理就应该开始着手确定哪些Release分支或者master是持续部署触发的**。
- **可测试部署前,就按照Release的分支在pipeline创建完成**。</br>后面,在讲到开发流程的时候,主要思路会以持续部署为首要目的,通过分支的触发规则,不同分支的触发,走相同的持续部署流程,但产出不同的版本和操作。
### 推荐方法
- 持续集成的Build pipeline作为YAML文件跟着对应的代码仓库
- Dockerfile文件也应该跟着代码仓库
- 为开发、测试环境创建Release Pipeline
  具体方法在[5.1. 开发流程Demo](/Devops说明/5.版本分支管理和开发流程介绍/5.1.-开发流程Demo)演示中说明。下面是开发流程的整体demo介绍。
# 4. 分支和pipeline的工作流程说明
  大致流程如下:
  buildpipeline 做持续集成,和单元测试过程,单元测试用的是mock和内存数据库测试,再到Release pipeline,Release pipeline会将前端和服务主工程编译后端文件集成在一起,发到开发测试环境或者其他测试环境,并做集成测试,集成测试用的是数据库测试,不同测试环境不同的数据库,不同环境变量等。
### TBD 图示
工作流程:

  模块化dll,在使用alpha,beta,rc标签的时候,分支的玩法可以设置 master也进入持续集成,持续部署, 可以设置build pipeline中,触发器不响应Master, 利用手动触发,而部署的Release pipeline设置Master触发编译。
目的是能够Release编译出生产的1.0.0版本使用,也同时能够做feature1.1.0的 内部测试版本供内存测试。
pipeline的自动化流程:

### Githubflow图示
工作流程:

  流程其实和TBD类似,**不同的是多了PR请求做主干合并,不是自己做合并,这个需要azure设置权限即可**;另外,TBD的Release分支是待主干成熟了再分支,而Githubflow是一开始就按照产品线的feature继续划分,但其实区别不大。
pipeline的自动化流程:

### Aoneflow图示
  免图示,原理和上面的两个模式差不多,不同的是,在发布前,会先为不同的打包需求,创建多个Release分支,并在pipeline上设置好,
那么开发人员只要按照要求合并到对应的Releas分支,即可完成持续集成持续部署。
# 6. 总结
  整体而言,最核心的是按需求设置好Releas分支的pipeline,开发按照不同要求合并到不同的Releas就全部关键。
### 关键点
- Build Pipeline是交付编译后的代码,Releas Pipeline将这些编译后的代码集成一起,交付到开发测试环境,到测试环境,再到生产环境
- Build pipeline期间,主要做检测单元测试,单元测试主要编写各模块的模拟内存数据的测试
- Releas pipeline期间,主要将编译后的程序放到不同的环境进行,不同的数据库做集成测试,集成测试即是可以通过后端的单元测试直接按逻辑调Application应用层接口,或者前端的api自动请求实现
- 持续集成,持续部署是分离的,不应该互相影响,**因此部署只认Releas的分支进行**
- **build pipeline 和 Releas pipeline能够达到持续集成主要是靠Trigger,pipeline的触发器**,即是分支的触发器进行的,同一条pipeline,不同的分支策略合并到不同的Releas分支就产生不同版本交付。
当然有更多高级玩法,比如设置pipeline的全局变量判断等,但都是基于分支触发器的。
- 比较高级的玩法,还是Aoneflow分支的方便,在发布测试预演期间,pipeline预先设置好要测试发布的多条Release的分支名称,即可通过合并分支的策略和手动操作等查出不同版本的程序。
比如:
可以创建Release/1.1.0分支,和Release/1.2.0两条分支, 要上线1.1.0时候,即合并到Release就自动触发持续集成和部署,同时要测试1.1.0上线后1.2.0也上线测试,就将1.1.0和1.2.0都合并到Release1.2.0分支,就可以测试1.2.0版本上线的预演。
如果这时候,市场觉得1.2.0不需要了,直接升到1.3.0版本,可以另外再开一个Release分支,将1.1.0和1.3.0合并到Releas分支即可。
**待技术验证:**
- 集成测试,目前思路是利用.net core的Testing Server,pipeline的脚步用dotnet vstest调用单元测试dll进行测试执行,不同的测试环境不同测试数据库。
- 集成测试,在编译后调用application应用层的测试。
网友评论