面临的问题

  1. 测试环境杂乱导致的问题

    每个任务都要搭建测试环境,或者把闲置的测试环境切换到待测试分支。麻烦,而且容易出问题。

  2. 抢占beta环境的问题

    每个任务部署到beta环境时都要和别人确认,同时其它任务都要等待。

  3. 上线任务A把尚在测试中的任务B的部分代码部署上线的问题

    先把feature分支合并到master分支,再部署到beta环境。

  4. 任务A和B在逻辑上互斥或者代码有冲突,导致问题在上线后才发现

    测试阶段是针对每个feature分支测试,而不是针对一个集成的分支。

  5. 不能保证所有上线的代码都经过测试

    直接把feature分支合并到master分支,不能保证所有代码都经过测试。

原因分析

直接原因:

  • 用feature分支部署测试,导致有多套测试环境。
  • 只有一个beta环境,导致抢占。
  • 部署到beta环境前先把feature分支和master合并,导致上线时把尚在beta环境测试的代码带上线。

根本原因是,一个项目同时有多个任务并行开发上线。

两种发布模式

  • 按版本发布
    • 优点
      • 可以有专门的分支跟踪测试、beta环境,这两个环境各自只部署一个实例即可。
    • 缺点
      • 存在版本发布周期,做完的任务不能马上上线。
      • 要改变我们目前的发布模式,产品部门的规划也要调整,业务部门的接受度也是个问题。
  • 持续发布
    • 优点
      • 和我们目前的发布模式一致,只需要调整内部工作流即可,产品部门和业务部门无感。
    • 缺点
      • 多任务并行开发和上线的问题很难解决。

选型的基本原则

  • 要保证所有上线的代码是经过测试的。
  • 解决上述问题。
  • 减少开发、测试、运维的负担。

调研的工作流

Git Flow

Git Flow是个基于按版本发布模型的工作流:

  1. 一方面,标准的git flow存在按版本打标签的操作,版本号冲突处理起来很麻烦。当然,也可以不用标准的git flow命令,而是用基本的git命令,但是操作会复杂很多,要求用户对git flow的原理有很强的掌握。
  2. 另一方面,develop是其它分支的上游,这意味着只有当develop分支稳定之后才可以发布上线,而这一点对于多任务并行开发的场景来说,很难保证。
  3. 需要和产品部门协商,统一规划版本发布周期,每个版本包含的所有任务统一集中上线。
  4. 能解决所有问题,但是结合我们自身的情况,再考虑到网站属于持续发布的模型,改成按版本发布不现实。

Github Flow

Github_Flow-5c5cc2b5-db48-4868-a5f8-e598155c93c5

Github Flow是基于持续发布模型的工作流。也和我们之前的方案大体一致。

Gitlab Flow

Gitlab_Flow-d0abbf6d-e4e4-4b2e-8383-a402fa458776

Gitlab Flow是在Github Flow的基础上做的扩展:增加了用于跟踪预发布环境和线上环境的分支,并约定由上游到下游的合并规则。即master分支是一切分支的上游,所有分支必须基于master分支创建,并且由上游向下游合并。

同样,Gitlab Flow也没有解决以上问题。

其它方案(一)

在现有工作流的基础上调整细节:

  • 承认master分支和线上环境一致,即合并到master分支的内容,默认立即上线。进一步地,可以实现自动化部署。
  • 用feature分支实现开发、测试、beta的整个过程,上线前合并到master。
  • 分别在提测、部署beta、上线节点前必须合并master分支的最新变更。
  • 合并时如果有冲突,解决完后必须回归测试相关功能。

存在的问题:

  1. 能解决问题1、2、3,解决不了问题4和5。

  2. 环境部署比较麻烦

    测试、beta环境的部署可以用自动化的方案减少部署的负担。

  3. 可能不能保证合并到master分支的内容都经过测试,例如feature分支和master分支合并出错,或者合并到master前追加了一部分代码。

    所以当feature分支进入beta阶段时,就应该把它保护起来,只允许改bug。如果和master分支出现了冲突,解决完冲突后要回归测试。

    • 缺点
      • 把临时分支设成被保护状态很麻烦。
  4. 每个阶段解决完与master的冲突后,都需要回归测试。

其它方案(二)

存在的问题:

  1. 能解决问题1、2、3、4,解决不了问题5。
  2. 因为在合并feature分支时,要在dev和beta中解决冲突,所以这两个分支不能被保护,存在被滥用的可能性。可能影响测试和beta环境的稳定性。
    • 也可以保护这两个分支,当feature分支和它们存在冲突时,再从feature分支检出新分支,在这个分支上合并冲突并通过MR合并到dev或beta分支。如果之后需要改bug,在原来的feature分支上开发,然后合并到新分支,再通过MR合并到dev或beta分支。
  3. 可能存在部署测试、beta、上线每个阶段都需要合并冲突的情况。

其它方案(三)

其它方案(三)

存在的问题:

  1. 本质上和前一种方案没有区别。
  2. 能解决问题1、2、3、4,解决不了问题5。
  3. 能解决dev和beta分支没有被保护导致滥用的问题。
  4. 同样可能存在个人仓库的永久分支被滥用的问题。
  5. 操作比较复杂。

思考

  • 我们的beta环境其实是第二个测试环境,是否真有必要?

总结

保证所有代码都经过测试的原则和多任务并行开发上线的模式是一对矛盾。要保证前者,就必须使代码在各分支间单向流动,比如feature分支合并到dev分支、dev合并到beta分支、beta分支再合并到master分支。要实现后者,单向流动就不可取,否则就会出现问题2和3。

Git Flow是最大程度能解决以上所有问题的方案,不过结合我们自身的情况很难实施。

“其它方案(二)”是个各方面比较均衡的方案,能解决大部分问题。前提是假设开发者会遵循提交标准:

  • 只在feature开发完成才合并到dev或beta分支
  • 不直接在dev或beta分支上做提交
  • 不对dev或beta分支做改变提交历史等危险操作
  • 不在上线前夹带私货(把未经测试的代码合并到master分支)

没有哪个工作流能完全解决我们的问题,最终还是要和团队协作模式的调整配合。