作者:子丑
内容大纲:
1、研发规范≠流程约束
2、自动化工具→研发规范载体
3、研发规范在工具上的落地示例
4、研发规范的选型方法与常见实践
研发规范≠流程约束
这个故事特别适合研发规范的场景,我们要避免成为把猫绑在柱子上的信众。而要做到这一点,我们先要了解什么是研发规范。
当我们在谈论研发规范时,我们在谈论什么?
有些团队谈起研发规范,会列一个大纲,并制定详尽的规章制度,这些规章制度对他们而言就是研发规范。
这个大纲可能是这样的:
- 需求管理规范
- 代码管理规范
- 制品管理规范
- 测试管理规范
- 生产发布规范
- 安全研发规范
还有些团队会用如下这种图来描述需求从提出到开发到交付的整个过程,准入准出要求、会涉及到哪些人等,他们以此来描述研发规范。
显然,当我们以第 2 种方式描述研发规范的时候,我们能更好地把控研发过程,能够以终为始地去看研发规范。
研发规范的目标、执行挑战
研发规范是跟随软件工程的产生而产生的。随着软件和团队的规模逐渐扩大,软件危机随之产生,为确保软件按时、按质地交付,需要利用软件工程的思路来解决软件危机,由此产生了研发规范。
因此,研发规范的目标是保障软件按时、按质地交付。
要保证软件按时按质地交付,实现研发规范的目标,我们需要从两方面入手,即优化研发团队内外协同机制和提升研发团队工程交付水平。
在制定研发规范时,有两个常见的误区。
一,只关心协作机制,乐衷于制定各种规则。例如,部署前提交发布审批单,其需经过 ABCD 四人的审批及相关人员的签字,审批单里面需要包括 XYZ 项内容等等。
二,只关心工程交付,乐衷于优化单点实践。例如,要求做单元自动化测试,并强调新增代码单元测试覆盖率要达到 100%。
如果只关心协同机制,那么研发规范很快会变成行为约束和规章制度。但是,研发规范还有另外的作用,即通过规范提升团队的工程实践能力。例如代码评审是为了提升大家对整体领域的理解和学习,自动化测试是为了提升快速验证的能力。
如果只关心工程交付,那么研发规范容易陷入一个个具体的实践,而忽视了整个交付流程,导致一眼障目不见泰山。例如测试团队强调测试自动化的实践,但却忽视了当下测试反馈的瓶颈不在测试自动化水平,而在流程中的部署和审批效率低下。
我们的目的应是既解决了协同问题,同时有提升了团队的工程水平。
自动化工具→研发规范载体
确定了研发规范的目标,我们接下来看如何将目标落地。很多时候,在制定研发规范时,我们会编写包含各类规范的详细文档。但仅靠人力去实现这些规范是不现实的。因此,我们会需求工具的帮助,即利用工具去保障文档描述的规范被执行。
但是,文档与工具的执行之间往往存在一定的差距,这个差距该如何去解决呢?
1、案例
上世纪 60 年代,阿波罗八号飞船的事故很好地阐释了这个问题。工程师汉密尔顿在加班时不慎触发了预发射程序,但好在是在测试状态,没有引发事故。这一事件促使汉密尔顿提出在系统中引入错误检查的想法,但负责人认为这种情况不可能发生。后续正如汉密尔顿所担心的,飞船飞行过程中宇航员误触发了这个程序。幸运的是,备份机制起到了关键的作用,避免了更严重的事故发生。
2、启示
仅靠文档定义规范是行不通的,当面临某个问题时,使用者需要按照文档规定的流程将各项任务串联起来解决,且中间不能出错。因此完全依赖使用者处理问题是不可靠的。正如阿波罗八号的例子,如果系统没有备份机制,要求使用者来处理这些问题将会是非常困难的。所以,工具的组合和连接(即如何正确地使用工具完成某个任务),也应该有相应工具来实现,而不是依靠使用者记住这一系列步骤并确保没有任何错误发生。
这个问题的核心是流程的自动化。
流程是工具自动化的过程,人不是流程本身和驱动者,而是参与方之一。只有这样,我们才能保证研发规范符合设计和成功落地。
3、示例:实现按特性的持续交付
通常情况下,研发规范会如何落地?我们利用名为“按特性持续交付”的案例来进行解释。
某企业有 30 左右的研发团队,架构师希望能确保团队的灵活性和快速响应能力。团队应该能够持续交付产品特性,即将产品特性拆解成各应用的开发任务,实现独立部署,以达到灵活性和快速响应业务需求的目的。
基于此,他们的愿景是,每个产品特性可以独立且快速地开发、测试、发布。每个特性对应一个开发分支,这一分支在开发验证和测试验收阶段发挥作用。只有通过开发验证的分支才能进入测试验收,通过测试验收的分支才能进入评审并合入主干,最终进入生产部署。
上面是我们定义的研发规范的概览,在这个概览下我们做了如下几层定义。
- 产品的交付粒度是一个产品特性,部署力度是一个应用,开发力度是一个 feature 分支。
- feature 分支必须经过开发、测试,最后到达部署。
- 在 feature 的整个交付过程中,每个阶段都有准入卡点。比如,如果某个 feature 分支没有经过开发阶段的验证,那么将不能进入测试验收阶段。
4、基于代码库和流水线的解决方案
有了这些规范之后,如果基于代码库和流水线,如何落地呢?
首先,代码库与应用最好一一对应,且代码库会将 master 分支配置为保护分支,其只能被合入,而不能被推送。并且被合入时具有条件限制,其必须通过前面的验证。
其次,我们应该会有两条或三条流水线。此处为开发测试流水线和生产流水线。在开发测试流水线上,开发测试都在这个 feature 分支上。开发测试流水线包含两个部分。第一个部分是开发阶段,它只做了一些构建和单元测试。第二部分是测试阶段,它只做了测试环境的部署以及测试验证。这里,我们是把两个部分是放在 1 条流水线上,即将代码推送到 feature 分支,再进入到单元测试等阶段,如果开发自测通过,确认可以提交测试验证,那么测试可以进入到部署环境阶段,然后进入到测试验证阶段,如果验证通过,则流程结束。
若开发阶段执行频率较高,测试阶段执行频率较低,此时,开发测试可以分为两条流水线。第一条流水线在代码提交后就可触发,但由于第二条流水线是独立存在,存在多种触发条件,无法设置测试必须通过前面的验证。因此,这种情况下会出现测试流水线卡不住的问题。这里为了简单,我们将开发测试合并为一条流水线。
生产流水线比较清晰。当代码合入到 master 分支后,流水线依次经过构建、发布准入和部署到生产环境等阶段。
我们以云效为例对上面的方案做一个演示。
首先,我们在代码库的分支设置中配一个保护分支,它的作用是通过关掉推送,使得任何人不能直接推送到 master 分支上,并且只能通过特定人的权限后才能合入到分支上。此时,可以给合并设置限制条件。例如,将通过代码评审以及通过开发测试流水线作为限制条件。
我们再配置两条流水线。分别为开发测试流水线和生产部署流水线。
开发测试流水线,对应 feature 分支,包含单元测试、源码的漏洞检测、构建、部署测试环境等步骤。同时,也可以按需在其中加入测试准入等步骤。
生产测试流水线,对应 master 分支,包含构建、审核、部署生产环境等步骤。
以上为流水线上的配置,同时在配置时,必须要保证两条流水线上配置的代码源、代码分支和部署环境的正确。
接下来我们看下这个解决方案是否符合前面所定义的研发规范。
我们发现,对于每一个阶段内部的规范,流水线是完全支撑的,但是阶段间的准入很难定义。例如合到 master 之后,需要保证所部署的准入已经通过前面的验证测试,那我们只能通过间接的手段,在保护分支里面设置分支合入的条件,进而达到准入的要求。但是需要注意的是,这两者并不完全对等。另一个问题是,在当前的情况下进行部署时,我们无法知道这次部署所涉及的特性是什么。
5、基于代码库和流水线的解决方案的局限
基于代码和流水线的解决方案,存在两个局限:
一、像早期的 NASA,要正确地执行研发规范,需要配合手册让使用者了解并正确执行操作步骤。包括开始一个新的特性开发时,使用者自行创建一个以 feature- 开头的分支,将代码提交后,使用者需要关注开发测试流水线是否有问题,然后按照要求创建合并请求,把 feature 分支合并到主干。然后,再去检查生产部署流水线是否运行正常。同时,在配置流水线时,使用者需要在执行的层面,保证流水线所对应的环境是正确的。类似宇航员在遇到故障的情况下,他必须遵循手册一步步去执行,如果某一步骤执行有误,那么就可能会出现问题。
二、即使我们根据手册正确地执行研发规定,还是会有信息传递不了,需要依靠线下传递的问题。最典型的就是部署所涉及的特性清单有哪些,而这类清单信息在研发规范中是很常见的。例如当我们作为验收测试的角色,这次测试的范围是什么,测试的东西包含哪些特性和改变,而这些信息需要彼此间传递。但是在传递的中间过程中,信息是否准确完整具有未知性,可能会产生信息丢失,并且后续无法再追溯,除非我们再去另找渠道补充丢失的信息。
6、研发规范承载在哪里?
造成该解决方案的两个局限的根因是什么?在之前,我也问过自己类似的问题,我们制定一个研发规范,它该定在哪里?它的承载是什么?
如果把它按模型的视角画出来,我们就会发现原来的思路明显是有问题的。
按照原来的思路,会发现代码库模板、流水线模板这些研发规范的对象对接不到真实的载体上,这显然是不对的。如果我们参考其他产品或工具的思路,会发现早已有解决方案,只是在工程交付上,没有明确把这个概念提取出来。
很早之前就有了项目的概念,例如云效的项目管理工具 projex,第一步操作往往就是创建项目。项目是研发规范的天然承载体。
进入到工程交付的层面,载体又不太一样。此时项目、代码库已不适合作为载体,因为具体的工作负载、服务、人员在很多时候并不能与代码库和项目一一对应。此外,大库模式或者一个应用涉及到多个代码库。所以在这样的情况下,需要一个名为应用的载体。
以应用承载研发规范在模型上是清晰且合理的。因此,我们引入应用这个概念,并且产生了一个新的产品:云效 AppStack。
应用对应于协作项目或者交付团队、团队空间或产品空间等。相对于项目下的需求,应用下的技术任务被定义为变更请求。
基于云效 AppStack 的研发规范落地演示
我们还是以前面的特性驱动的研发规范来举例。
1、用应用研发流程代替流水线,保证研发规范被正确执行
首先,我们用应用研发流程代替流水线。 因为流水线能定义研发阶段内部的逻辑,无法定义 2 个阶段之间的逻辑。我们引入了一个更上层的概念:研发流程。
简单来说,我们认为研发流程就是 N 条流水线的组合加上流水线的准入限制。
下面,我们进行具体的演示。首先我们会进到 demo-go-echo 这个应用里面。在这个应用里面我们可以看到其研发流程。
在这个研发流程里面,我们可以看到它包含两个阶段,一个测试阶段,一个生产阶段。这与前面两条流水线是可以对应上的。在测试阶段时,我们可以观察到它的触发方式。既可以选择一个 feature 分支去触发,也可以由代码提交自动触发。
接下来,我们看一下研发流程的配置。
如图所示的研发流程里,我们配置了两个阶段,每个阶段为一条流水线,并且阶段间存在准入卡点。例如生产阶段,其分支被固定为 master,并且以测试阶段的成功执行作为准入条件。
此时对照前面的规范,可以发现我们的研发流程与规范所描述的能够完全对应,包括阶段准入、对应分支、环境等。
这样,该研发规范就可完美的映射到 AppStack 的研发流程上,包括成员、角色、研发流程等,都可与规范描述的一一映射。
这样的好处是什么呢?让我们实际走一遍研发流程。
假设我们有个开发任务为实现一个 demo 接口。
我们创建该开发任务,并自动创建 feature 分支,同时因为开发任务的目的是为了满足某个需求,因此我们把这个任务与需求关联起来。
我们修改下代码并提交到该分支,测试阶段会被自动触发,
我们可以清晰地得知,本次触发涉及的特性是什么。同时查看变更详情时,可以看到这个变更对应的需求,点击需求全景图,我们也可展示需求的关联变更,数据都内在地连接了起来。
2、用变更请求贯穿整个应用研发生命周期,保证信息被完整连结
变更请求是一个完整的连接对象,它的作用在于让产品特性的开发任务的各个阶段被聚合起来。在流水线的研发模式里,如果想追溯某一次代码改动,在合入目标分支、打包、测试一路走到哪里,以及当前测的包来源自哪里,当我们想打通双向链路时,里面会存在两个问题。一个问题是,当拿到测试的执行记录时,我们只能拿到分支、来自哪个 commit 的信息,它是合并来的还是代码提交来的等这些问题是未知的。因此,我们在这里做了一个组件来计算这次改动涉及的源头。
这就解决了我们前面的问题:如何收集本次部署所涉及的特性或集成所涉及的特性,即依靠变更请求以及在研发流程中变更管理器的组件来实现。
通过如上的方式,整个应用的研发生命周期都可以连接起来。变更请求有两个目的,一个目的是让开发人员的工程实践被自动同步更新到需求,从而无需手动更新需求的状态;另一个目的是当需要对研发交付进行监控、跟踪和度量时,可以做到端到端的数据连通。
标签:落地,流程,新思路,规范,研发,测试,流水线,分支 From: https://www.cnblogs.com/yyds114/p/18354773