1988年,微软高级主管 Paul Maritz 写过一封题为 “Eating our own Dogfood” 的邮件,向微软局域网管理工具项目的测试主管提出 “提高内部使用自家产品比重” 的挑战。从那时起,Dogfooding 作为一个专业术语,快速传播开。
在向消费者推出之前,Dogfooding 允许员工使用并测试他们公司的产品,因此 Dogfooding 可以作为质量测试,它为开发人员提供了在产品发布之前,解决产品相关问题的机会。并且在开发人员使用自己公司产品进行软件开发的过程中,会对他们正在构建的软件有更深的理解,并能切身体会到产品的用户体验如何,这能极大改善创建技术产品的技术专家与产品最终用户脱节的问题。
极狐GitLab 提供开箱即用的开放式一体化安全 DevOps 平台,该平台覆盖了项目管理、源代码管理、集成、持续交付、安全扫描等诸多功能。极狐GitLab 正在积极实践着 Dogfooding 文化,首先,提倡公司各个岗位的人员都使用这个产品,不论是 HR、销售还是研发团队,在不同场景里面使用,覆盖足够多的功能。其次,我们使用 GitLab 并且基于 handbook 来进行协作,将内容和流程都积淀成为 handbook,并把它公开出来。
从 DevOps 这个较大的维度来看,极狐GitLab 的开发人员从四个方面来进行 Dogfooding:
1. 极狐GitLab项目管理实践
极狐GitLab 使用轻量、敏捷、issue 驱动的方式来进行项目管理,并使用机器人辅助去做需求管理。
2. 极狐GitLab版本控制实践
极狐GitLab 版本控制最佳实践五步走,高效管理代码,进行协作。
3. 极狐GitLab持续交付实践
通过 CI/CD 去集成大量自动化工具帮助完成测试,在高效率的同时保证产品的高质量和安全。
4. 极狐GitLab效能评估实践
极狐GitLab 具有价值流分析和效能分析两项功能,辅助进行效能评估。
极狐GitLab项目管理实践
以极狐GitLab 的研发团队举例来说,下图是它的完整研发流程:
极狐GitLab 是月发版制,研发团队的产品迭代周期为一个月,从第一个月的月中到第二个月的月中,一个完整的产品迭代周期分为四个部分:
- 从第一个月月中到第二个月第一个周一,这期间,团队专注于新版本的功能开发;
- 第二个月的第一个周一到第一个周三,产品经理进行下一个迭代周期的计划,研发人员评估工作量;
- 到了第二个月的周三,团队会开具体的需求讨论会,用来明确需求和计划,并给出明确公示进行评估;
- 第二个月的第三个周一,完整迭代周期进入了尾声,团队进行复盘,对值得发扬和需要改进的内容进行分析。
更多详细信息,参见handbook:
- 产品:https://GitLab.cn/handbook/product/planning
- 研发: https://GitLab.cn/handbook/engineering/workflow/
极狐GitLab 的敏捷开发管理体系
那么整个产品迭代项目是如何进行管理的呢?极狐GitLab 支持敏捷开发管理体系,它用群组、子群组和项目来分别对应项目和子项目,通过实施 epic、子 epic 和 issue 来对应原始需求的任务、子任务,这项目管理的第一步。
产品经理创建原始需求后,和研发人员一起细化需求,并基于 invest 原则拆分需求。首先明确所有需求,撰写具体的 user story。撰写完成后,如果大家有其他意见,可以以评论的方式写在该 issue 下,然后进行讨论,直到需求明确。
GitLab 以及 GitHub 这些开源社区或开源产品都是 issue 驱动,即无论是开发的任务、开发的需求还是 bug 缺陷,一律都用 issue 进行管理。
标记 Label 区分 issue 类型
随着组织发展,issue 会越来越多,我们如何进行区分呢?极狐GitLab 以一种灵活的自定义方式去打上不同的 Label,来区分不同 issue。
Lable 是多级式的,第一级是一个 type,它决定了该 issue 是一个 bug、功能还是 QA 等。当打上第一级 Label 后,还需要打上第二级甚至第三级,比如说这个 bug 是性能问题、安全问题,还是来自一个手机端等等,可以自由精准地定义 issue。
看板 Board 自定义 issue 视图
有了 Label 区分还不够,对研发人员来说,需要一个视角去看这些 issue。研发团队可以通过看板的方式进行 issue 管理,看板其实就是不同视角的视图。比如说在极狐内部,研发团队、测试团队还有产品团队都有属于自己的看板。
产品团队关心的是任务的分配,所以有一张以研发工程师为视角的看板,比如张三在做需求A,李四在做需求B,这些都有一张看板;此外还有一张工作流看板,展示需求进行到什么阶段。对于测试人员来说,只需要看到相关 bug,不需要管在做什么,当然也可能会看一下看板,可以根据不同团队的职责进行划分。
机器人 Triage 自动处理 issue/MR
Triage 机器人也是个非常有趣,有价值的功能。如果用户不清楚 issue 的提交方式,会导致 issue 管理困难。举个例子,当用户提交 issue 后,没有分配人员来跟进,那它就被搁置了;或者用户不清楚该打上什么样的标记,是 bug 还是功能,导致 issue 分类混乱。
使用 triage 机器人可以轻松解决这些问题。当用户提交了一个 issue 后,他不知道该进行什么操作,就把 issue 关闭了,这个行为被机器人捕获到,它会立即在这个 issue 下添加一条评论,并且发邮件告知创建人应该打上 type。当用户打上 type 后,机器人又会随机从测试人员中选择一位,把他加到这个 issue 的指派人里,跟进这个 issue。通过这种方式可以很好地把 issue 管理起来。
里程碑 Milestone 迭代规划与回顾
在项目之初和完成之后,可以使用里程碑来对项目进行规划和回顾。以下图极狐GitLab 15.1 的燃尽图为例:
这个燃尽图并不是理想的燃尽图,因为它并不贴合参考线。在整个迭代周期的第一周,研发人员开始处理需求的时候,会发现有些需求描述得不是很清楚,导致评估内容增加,或者说有一些新的需求会引进来,所以这个曲线在第一周的时候甚至有点上扬。
前两周集中进行开发,这时并没有开始大规模测试,所以曲线比较平缓。两周后,主要功能都完成测试,开始介入大规模测试,这时又会发现一些 bug,所以曲线又有一些向上的波动。两三周之后,这个曲线开始急剧下降。
GitLab 版本控制最佳实践五步走
版本控制即如何管理代码,代码如何协作,极狐GitLab 对于版本控制总结出了五步走的最佳实践。
第一步:选择分支策略
在这一步并不是让大家去使用主流分支策略的某一种,而是应该在企业内部制定一套统一的、适合自己的分支策略。只有分支策略统一之后,研发流程和管理才容易做到统一。
下图是极狐GitLab 的分支模型,以 master 主干分支为主。如果要做新功能,或开发新需求,需要创建对应的功能分支 feature,然后基于 feature 分支来做开发。开发完成没有问题之后,必须通过评审的方式把它合并到主分支里,这是一个完整的流程。举个例子,如果我们要修复一个 bug,需要创建 bug fix 的分支,然后再通过评审合并进主分支。
如果所有的功能都做得比较稳定,临近发版的时候,再从 master 分支里再抽出一个版本分支 stable ,比如说现在要发 15.0 ,那就抽一个 15.0 的 stable 分支出来。但是并不是所有的版本一定都可以一直用下去,封版之后难免会有一些问题。
当需要做一些热修复 hotfix 来修复安全漏洞时,还是走 bug fix 分支策略,再通过 cherry pick 的方式把它从 master 分支抽出去。比如说修复了漏洞,就把提交的这部分代码 cherry pick 到 15.0 的 stable 分支里,打上 Label。一开始是15.0.0,修复了一个版本之后,就变成了15.0.1,再往后依此类推。15.0 stable 这个分支相当于已独立,不会再往 master 合并。
第二步:基于分支开发
建议大家基于一个新的分支进行开发,不要直接在主分支下开发,这样做优点体现在两方面。
第一是便于协同。举个例子,假如说现在要做一个新的功能,多位开发人员都在同一个分支里去进行开发,此时分支没有隔离,大家同时提交代码,导致别人的工作没办法进行。
第二是便于审核。当每个研发人员都基于一个新的分支进行开发后,想要合并进主分支,则每个研发人员提交的代码都能在评审后合并入主分支,能很好地控制代码质量和代码安全风险。
第三步:小步快跑提交
写了代码之后,研发人员一定要尽快提交,避免电脑或磁盘损坏导致代码丢失。另外,当一口气提交了太多代码时,如果我们要做一些回退,让一些功能选择性上线,则无法完成此操作,因为从大量提交的代码里不能很好地识别哪些代码对应哪些功能。
第四步:描述提交信息
GitLab 是一个开源项目,任何人都可以贡献代码,但是需要规范管理。比如极狐GitLab 分支命名有一定规则,它可能以版本号开头,或以 feature 开头全都是小写,只允许使用中划线、下划线,不允许使用其他间隔字符。
对于代码提交也是同样的,代码提交 commit message 需要大写开头,必须清晰地描写出你要做什么事,还要带上对应issue编号,因为这样才能把需求和代码关联起来,这是一些具体的要求。
极狐GitLab 有个功能是推送规则,可以通过正则表达式的方式进行约束和校验,能保证社区贡献者也按照这个规则来进行开发。
第五步:定期代码评审
最后一步也是最重要的一步就是代码评审,做好代码评审才能充分发挥版本控制、基于分支开发最主要的价值。好处很明显,但大家也知道,劣势就是要花费大量时间去做代码评审,且收益可能并不是那么明显,所以很多企业就忽略掉这一步了。
那该如何去做代码评审呢?
首先会在整个的合并请求里面去关联,这一次代码的合并解决什么问题,实现什么需求,需要与前面的 issue 对应关联起来。
其次是谁来做代码评审。GitLab 每一个功能模块都有相对应的研发负责人,我们可以叫他 code owner ,这个关系是提前建立好的,在不同文件夹里对应好。一旦提交代码影响到这些不同文件夹的代码,就会有相应人员会参与到评审中。整个过程是自动的,不需要手动去分配。
最后,尽量使用自动化测试工具,比如代码质量扫描、安全扫描、性能测试、单元测试等,都能通过自动化的方式结合 CI/CD 实现,并且结果能返回到代码评审里,自动化测试工具最主要的价值和意义就是帮助我们完成评审。比如单元测试率一定要达到多少,代码质量一定要达到什么级别,才能把该代码合并进去,对于评审人员来说,就不需要再去人工检查命名规不规范,注释写没写全,这些过程全都是自动化的了。通过使用自动化测试工具,评审员更多地做一些抽查工作,极大提高效率。
极狐GitLab 持续交付实践
极狐GitLab CI 流水线
极狐GitLab 内部的 CI/CD 流程跟绝大部分公司没有太大的区别,CI 负责打包编译,然后 CD 负责发布。
但是具体细节,比如说在 CI 除了要解决代码构建的问题外,还要完成质量扫描、安全扫描和单元测试,并把测试报告集成进来。这些功能都是极狐GitLab 自带的,并会尽可能把这些功能用在实践中。
虽然某些功能在上线初期并不那么强大,但还是需要持续使用,一方面可以通过实践验证这些功能是否正常,从而不断完善它。另一方面,通过这些功能来保障发布出去的产品质量和安全。
单元测试
具体来看一下就是单元测试在做什么?其实就是基本的主要功能的单元级别的测试用例自动化。其中重点是两个数据,第一个是测试用例的通过率必须是 100%。如果单元测试都没有通过,那一定存在问题,无法被合并。第二个要看的数据覆盖率,即核心代码覆盖到单元测试的比例,这个数据必须达到 90% 才能被合并。
质量测试
定义代码质量有这几个指标:变量的命名是否规范,注释是否齐全,整个代码风格是否符合该语法的最佳实践,还有兼容性、复杂性、重复性各个方面,从这些指标来对整个代码进行全面的质量扫描。
极狐GitLab 对自己产品的质量要求是,所有严重问题一定要解决,主要级别问题或主要以下级别问题可以选择性解决。关于主要级别问题举例来说,在一个函数里面,条件判断不应该超过四个,超过就认为这个函数略复杂,或者说这个函数的代码超过 50 行也认为复杂。这其实是规则定义的问题,规则是存在一定灵活性的,如果认为没有必要去聚焦拆分函数,而是实现它的功能,那么便于阅读就可以了,并非完全要严格执行这样的规定。
安全扫描
极狐GitLab 将 7 种不同类型的安全扫描的工具集成到了一起,每一次代码提交都可以使用这些安全能力覆盖一遍,包括动态测试、静态测试、密钥检测、依赖项检测等等。
扫描出的严重级别和高级别的安全漏洞,一定要严肃对待,并且要全部解决。此外,因为用到了非常多静态测试,而静态测试容易出现误报,因此有些误报的数据需要研发人员去进行评论,给出意见,相关审核人员确认后,把它标记为忽略就可以了。
在合并请求中使用GitLab CI
使用了这么多自动化测试工具,最后还是要把测试结果返回到代码的合并请求里,帮助进行代码评审,这才是最重要的一点,但整个 CI 过程跟代码评审其实存在一些问题。
举个例子,如果要在合并之前执行流水线,那么流水线执行在哪?执行在原分支,原分支即功能分支,首先需要确保新加的功能在新分支上能否编译通过,如果新分支的 CI 都无法通过,合并后肯定会有问题。
但即便在原分支下 CI 能通过,也并不代表它合并到目标分支之后也能通过,因为主分支如 master 分支不断有新代码合上来,无法保证本次合并之后,会不会跟主干分支的代码有冲突或潜在干扰,一旦合并后出现问题,那该主分支就无法使用,因此这里存在一些问题和风险。
常用的解决办法是在一次 CI job 里,本地模拟这个代码已经合并,而不是在 GitLab 代码仓中,在server 级别去合并。实践方式很简单,用 git 命令后,fetch 再加 git merge 命令,就可以实现整个代码的模拟合并,之后再去运行流水线,这意味着实现了预测未来的能力。一旦流水线通过后,代码再合并入目标分支,出现冲突的风险会降低。
另一种方式,对于极狐GitLab 来说,已经把它做成了产品化的功能,叫合并结果流水线,开启它就可以实现类似效果,极狐GitLab 每一次代码评审都是基于合并结果流水线去实现的。
极狐GitLab CD 流水线 for 自部署(Delivery)
CD 中的 D 代表两种不同的意义,一个是 delivery,一个是 deploy。Delivery 就是打包,完成交付。GitLab 主打的是私有化部署,所以大多以安装包的方式交付给客户和用户,在这样一个场景里,更多的就是面向不同操作系统进行打包,打出不同的版本镜像来。
极狐GitLab CD 流水线 for SaaS(Deploy)
第二个 D 是 deploy,极狐GitLab SaaS 产品分成两种不同环境,一个是 staging 环境,即预览环境;还有一个是真正的使用环境——production 环境。无论是哪种环境,我们都采用金丝雀发布的策略,即有三套副本,这三套副本里有一套是 canary,另两个是主版本。如果使用 GitLab 的 SaaS,可以在左上角看到一个 next 标记,点击之后就会切换到 canary 副本。
对于 staging 环境来说,发版策略是每天发三次,六点、十二点和下午四点会自动发布。而对于生产环境来说是每周两次,并且是需要人工参与的,这个影响比较大,需要人员进行把控。因为 GitLab 这个项目容量体积差不多有 500 个 G,所以整个 CI/CD 流程需要一个多小时,部署完成后,会自动发到研发人员聊天工具进行提醒。
上图右下部分Release Tools Bot 处有早上 8:13 的一条通知,这说明是第二次构建,并且前一次失败了。六点钟开始构建一个多小时的时间,到七点钟可能构建失败了,然后又构建到八点钟。此外,每一次发版都要把这个版本跟具体的合并请求关联起来,即每一次发版都要有清晰的 release note。
效能评估
价值流分析
最后是效能上的一些实践,这部分分成三个方面,第一个是价值流图,第二个是 Dora 指标,第三个是代码提交量和代码提交行数的统计。
价值流是对研发中各个环节用时中位数的统计,比如说计划、编码、测试、评审等环节的用时,它会识别工作流中哪些环节是瓶颈,从而分析到底是哪个环节的哪一些人和事情出了问题。
其次是 Dora 指标,Dora for K 指标如部署频率、变更前置时间、恢复率、恢复时间、变更失败率,都是行业内比较通用的指标。对于极狐来说,部署频率是10.4,意味着每天至少要部署 10 次。而后两个指标是没数据的,因为这是上个月新版本中的功能,这个图是本月初截的,因此还没有数据。
效能分析
效能分析其实就是排行榜,但这并不能完全地衡量一个人的价值。效能某种意义上是可以评估的,但是一个人的价值并不能被完全量化。
极狐GitLab 也有一些员工评优的方式,比如说极狐GitLab 是月发版,因此每个月都会评选这个月的 MVP,即对该月版本贡献最大的同学,这个 MVP 并非通过代码量去评判,而是从产品层面来看做的功能是否有价值。
此外更多是评估研发人员跟其他同事、核心团队,在沟通交流、代码评审各环节协作过程中,对员工的感受、态度、积极性、为人处事等方面进行考察。也就是说一部分做量化的考核,一部分还是以非量化的感性方式为主。
分享回顾
首先是 Dogfooding,极狐GitLab 内部会优先使用自己的产品,当内部有需求想去采购第三方系统时,第一时间要想到自己的产品能不能做这个事,如果可以,就推广到全员去使用,无论是后勤、销售还是研发。这可以帮助发现问题,不断改进产品。
Dogfooding 另一个重要的价值就是可以帮助我们去做创新。举个例子,在极狐内部,用 GitLab 管理 OKR,跟客户交流信息也全部记录在 GitLab。可以不断发掘产品功能,适用于不同场景中。
其次是项目管理,极狐GitLab 使用轻量、敏捷、issue 驱动的方式来进行项目管理,并使用机器人辅助去做需求管理。这个大家是可以借鉴的,就是用 webhook 加 API 的方式去帮助我们更好进行项目管理。
第三是版本控制五步走的最佳实践。
第四是持续交付 CI/CD,重点是两个方面,第一是我们通过 CI/CD 去集成大量自动化工具帮我们完成测试。另一方面以自动化测试为门禁帮助我们进行代码评审,在高效率的同时保证产品的高质量和安全。
最后在效能评估部分提到了价值流、Dora 和效能管理。其中最重要的,就是效能某种意义上是可以度量的,但是一个人的价值并不是完全可以被度量的。