基于GitLab的前端Assets发布体系

以SVN+RMS为核心的发布系统,对前端开发的影响上来看,存在以下问题:

  • 覆盖式的发布,容易导致线上问题。 js一旦发布,就有可能被任意其他页面使用。被引用的越多,就越重要。一旦核心js出现故障,影响面巨大。
  • 发布的基本粒度过于细节,基本发布单位是文件。相对后端每次发布整个应用,文件粒度的发布体现出对应用复杂度缺乏深入理解。
  • 手工挑选文件发布,容易发生人为错误。SVN+RMS的模式使得前端开发在各种GUI工具间切换,使得发布环节效率低下。在前端工具逐渐命令行,一键式,自动化,集成编辑器的大趋势下,愈发显得效率低下和对前端开发者不友好。
  • 在发布与版本管理系统深度耦合的情况下,使用中心式版本系统的SVN无力高效的支持分支开发、主线发布的开发/上线模式。在版本控制领域,SVN合并分支效率低、有瑕疵的分支合并算法、基于文件而非仓库的版本管理,容易引入Bug,已经是一个过时工具。

以上问题在项目交接的场景中会更加容易犯错,以下是一个案例:
开发者甲实现特性1修改了A文件并且提交到SVN。于此同时,开发者乙为了实现特性2同时修改了A、B两个文件,也提交到了SVN。由于工作安排变化,甲交接特性1给开发者丙,开发者丙从SVN更新整个应用代码,在本地继续特性1的bug修改(在不知道特性2其实也被加入进来的情况下)。上线时,开发者丙在RMS中,观察到文件B可能也需要被发布的情况下,由于被告知特性1仅与文件A有关,为了最小影响,选择只发布文件A上线。由于文件A依赖文件B,上线后出现故障。
当然,如果使用了svn分支,这个问题也能避免。问题是,svn分支很厚重。

改进目标:

  • 让前端Assets发布过程更加安全、高效、工程化。在解决所有现状问题的基础上,发布体系还应能够达成以下目标:
  • 一旦发布出现问题,前端能够快速回滚
  • 流畅的支持beta,灰度发布( 比目前更容易的)
  • 简化发布步骤,减少犯错的环节

核心机制

1、非覆盖发布

发布的Assets永远不会覆盖线上代码。基于这个机制,给每次发布的文件/模块/应用一个版本号/时间戳,保证文件名不与线上重名。一方面,前端代码有因为其容易被引用的特点,实际上已成为一种“一旦发布即永远存在”的服务。另一方面,这样做还能够带来以下好处:

  • 不覆盖线上文件,不会影响未知的引用模块/页面。
  • 不再需要预发环境验证,简化产品发布流程,减少工作量的同时减少犯错。
  • 不用担心误发布。因为前端总是先发布。这样发布后还有一次机会做“真正的线上测试”
  • 发布工程而非文件。发布粒度从文件转换到项目。前端针对产品整体发布,每次发布都是一个项目的某个整体状态。直接效果是规避掉所有漏发js文件。其深远意义更在于,为前端提供一个工程化思考的底层环境。

2、自动化

解决此方案给前端开发效率带来的问题

  • 静态资源引用[^1]的路径变更。静态资源引用的/文件名将会携带版本/时间戳信息,一旦产生一次发布,大量的引用路径变化会引入很多手工劳动。
  • 动态资源引用[^2]的路径变更。模块加载路径也会携带版本/时间戳信息。在发布时修改大量动态资源引用路径的会引入很多手工劳动,增加引入错误的概率。

这样前端需要一套调试、构建工具,灵活高效的处理在联调、测试、预发、发布、紧急Bugfix等各种场景下,对站点、项目、模块、组件的发布问题。

3、从SVN转移到GIT

这是一个有助于全面提升效率的转变。

  • 首先这种转变对于解决问题1所提到的误发布有帮助;
  • 其次对于问题2的分支/主干式的发布方式有天然的良好适应性;
  • 最后,GIT的运行包提供了一个非常强大的命令行环境,

对于问题3所提到的效率困境也有很大帮助。

SVN的版本粒度是文件级,GIT的版本粒度是仓库级。GIT认为,版本管理的最小单位应该在仓库,项目在某个时刻的所有文件构成的“快照”体现了一个真正“版本”,因此,每个“版本”都应该保证自己是可工作的最小特性集合。这是GIT与SVN在版本管理哲学上的本质区别。这个重要的特性使得前面提到的项目交接的案例能够得以解决。

GIT中,分支操作成本极低,仅仅体现为一个本地文件指针更改。高效强大的分支特性使得合并分支,和基于分支的开发成为一件愉悦的事情。在SVN中每当启动一个分支时都小心翼翼相比,GIT可以随时随意的开启、合并分支。

在windows平台下GIT提供了全套命令行环境有助于提升前端的工具化程度,提高前端开发者为自己制造工具的可能性。


解决方案

  1. 代码直接通过GitLab发布。通过GitLab发布的内容,在SVN将不可见。 
  2. 将不影响在SVN维护的老代码,新项目启动逐步通过 GitLab做版本管理,慢慢废弃SVN。
  3. GitLab上,按照各前端团队的需求为各团队建立自己的Group。一个团队可以有多个 Group[^4]。Group是受控的,由SCM团队统一管理。需要发布的Git仓库放在团队Group下。
  4. 每个需要发布的Git仓库需要在GitLab配置中中指定一个该仓库的发布路径,鼓励将demo和Assets放到同一个库中维护。发布时只发布构建目录。 开发时候对开发人员友好,上线后对线上环境友好。基于此思想,前端代码必然会存在两种型式,未来前端构建会越来越流行。
  5. 在SCM的视角,重新理解“应用垂直化”的含义。前端代码有自己的仓库,构建后的ASSETS和模板成为对应用的输出,在应用的仓库中有一个路径存放或者前端代码干脆拆分出来。

发布路径

非覆盖发布
Git仓库的内容发布路径按照http://a.tbcdn.cn/g/[Group]/[Git仓库]/[Tag]/[发布路径]的规则发布。其中“发布路径”是一个Gitlab新增配置项。

覆盖发布
提供简单发布接口,不增加时间戳(Git Tag)路径,直接将组件发布到对应路径。这样做的原因是组件级开发,其发布路径也是对外接口的一部分,需要组件开发者完全掌握其最终发布路径。

发布路径为:http://a.tbcdn.cn/g/[Group]/[Git仓库]/[发布路径]

发布路径跟Git强行约定而非配置的原因如下:

在团队内基于约定大于配置的思路,能够提高效率。
通过GitLab的天然检查重复仓库的机制,保证仓库发布不会覆盖线上路径。

工作流

  • Git仓库中master分支没有权限直接push。所有的开发都在daily分支上进行。daily分支的命名为daily/x.y.z,其中x.y.z是以数字或者点符号组成的字符串,用来标记版本,如1.2.1 、20130401。
  • 每当开始一个项目,本地启动一个**daily/x.y.z**分支,在本地分支上进行开发。
  • 本地分支开发完成,需要发布到日常环境测试或者联调时,推送 dayly/x.y.z分支到gitlab。gitlab将通过hook将代码实时发布至日常环境。
  • 联调完成,通过测试,需要最终发布上线时,给 daily/x.y.z分支打标签(又叫做tag或者里程碑) publish/x.y.z。推送该标签到gitlab服务器,做一系列检查后,最后部署文件到CDN。一旦一个daily分支被发布。服务端将删除远程daily分支,并且拒绝再次被推送此版本号。这样做的目的是保证版本号不会重复发布。
  • 修改线上Bug时,需要重新拉出daily分支,并且以新的版本号发布。

影响分析

新发布方案与现有方案最大的不同有两点。

  • 时间戳由发布系统强制增加。时间戳导致的Assets路径变更引入更多的工作量。各团队需要一个自己的构建系统或者其他方案妥善解决这个问题。
  • 需要转变项目组织思路。目前的发布是单个文件粒度,可以选择发布单个文件。转变到新方案后,发布的最小粒度是项目,一次发布即发布整个仓库(和Git的版本管理思路一脉相承的)。采用新方案后,应该更加细粒度,扁平化的组织仓库结构,将真正高内聚的一些页面和组件组织到一个项目中,对项目架构有一定要求。
  • 新方案基于整个仓库的发布、以及上线后还有一次机会做真正的线上测试,这些机制能够比较好的解决本文最初提到的极端案例。

posted on 2015-11-10 10:05  Frank.LiG  阅读(1870)  评论(0编辑  收藏  举报

导航