最近几天聊天,常常聊到 持续集成 辅助把控 代码质量 ,以前端团队为例,我们来简单聊聊。

本篇很可能是你在网上能找到的使用容器应用最新版本 SonarQube 相对详细的一篇,或者是唯一一篇,所以如果遇到问题,欢迎和我进行讨论沟通。

如何把控质量

个人认为把控质量的核心是形成标准避免错误引入,从而提高应用的健壮性,降低维护成本和不应存在的复杂度,这里在不讨论 测试 的情况下,通常的做法无非:

  1. 在代码提交前或后进行 Code Review,定期走读代码。
  2. 使用 eslintjshintjslint 等工具在开发环境通过 Git Hook 触发,进行风格和简单的质量评估,避免 Bug漏洞坏味道 的代码提交到平台。
  3. 配合 pipeline 使用,定义一些过程脚本,在代码提交后,或者分支合并前去调用以上工具,避免质量不佳的代码合并到开发主干,被“传承”下去。
  4. 使用 istanbul 之类的工具简单检查覆盖率,避免有一定复杂度的业务代码潜在风险过高。
  5. 人员培训,技术氛围建设。

策略的差异

一个良好的开发氛围,第一条是必不可少的,不论是否使用辅助审查系统,使用审查机制,可以把很多不合理的设计和明显使用错误的代码在萌芽期杀死。

如果辅助手段使用本地运行验证,在配套前端开发技术设施不完善的情况下,则可能出现为了省事卸载 Hook 跳过审查的事件;或者需要额外维护规则更新机制的成本,将团队代码规则保存到仓库或者私有包仓库的维护成本,甚至是保存仓库的建设成本。如果云端执行资源不足的话,本地运行则会是一个很好的补充手段。

如果使用云端审查,需要配套设施都相对完善:私有包仓库、CVS 系统、甚至容器仓库、CI Runner 执行环境…(后续或许可以聊聊如何建设这些)

云端审查可以将规则和标准统一,配合 Docker 容器技术可以轻松进行应用资源扩容,远超本地运行效率,并且可以进行扫描存档,客观的反馈代码质量和功能加入、人员培训前后的变化。

而技术团队的氛围建设、人员的技术培训是一件长期持久的事情,打造“有人愿意教”、“有人愿意学”的机会可遇不可求。

相比较之下,如果你的公司已经将 GitLab 升级到了 9.x 以上,并且有资源去做 CI/CD 的事情,那么直接在 Pipeline 过程中添加代码审查是一个相对靠谱的事情。

使用 SonarQube 进行代码分析

接下来我会演示如何使用 SonarQube 最新版本辅助进行代码分支把控质量。

我将最新版本的 SonarQubescanner-runner 封装成了镜像,避免直接在 GitLab Runner 宿主环境直接执行,污染执行环境。

然后在 CI 阶段定义一个新的 Stage,这里假定叫 sonar 好了。

这里使用 Publish 模式将扫描结果回传 SonarQube Web Server,形成持续的报告。

如果你需要将扫描阶段定义为部署前的一个“质量把控关口”,那么需要再简单写一个脚本,在扫描器执行完毕后,抓取当前项目的状态,是否超过 设定的阈值,从而中断后续的流程,脚本参考我上一篇 如果不用 Node.js 写业务 中的使用 Node.js 作为持续集成的粘合剂,获取扫描器返回的接口地址中的 status 状态值即可,比较简单,就略了。

提交触发构建

当你提交代码之后,GitLab Runner 调用镜像中的扫描器脚本(这里使用的Runnerdocker 类型的 Runner)进行扫描,如果成功,大概是这个样子。

CI执行扫描

执行器日志会返回这个任务的具体执行结果,上文有提到该如何处理。

访问 Web 平台,可以看到我们刚刚提交触发的测试报告已经生成,如果有缺陷的话,会展示因为什么,又该如何修正。

扫描结果

相关功能还是比较多的,参考本文自行搭建后,可以自行了解。

默认规则列表

如果上面的规则看不太清楚,可以尝试浏览官方规则列表的在线版本:

当然,如果你愿意的话,可以参考下面的链接进行自定义配置,让扫描报告中包含覆盖率,以及使用自定义的 eslint 规则进行补充或者替换默认的规则:

当然,还有一个定制化更强的套路,使用专门的 eslint 插件,目前插件只能跑在老平台上,感兴趣的你如果对 Java 很熟悉,可以参考官方开源社区的示例和开源的三方 eslint 插件进行升级改造,这里就不展开了。

官方提供了示例、也有三方插件,你甚至可以定义如果包含了哪些词汇、或者文件超出指定大小等就拒绝这次的审查通过,避免代码合并到主干分支造成更大的损失。

说了这么多,那么如何快速搭建一个相对高可用的 SonarQube 呢。

构建你的平台镜像

例子中可以看到,我个人使用私有域名,并签署了私有证书,如果你的公司团队状况类似,可以直接参考,不然的话,去掉相关代码即可。(不去掉也无所谓)

下面是我的镜像,会自动将私有证书进行授信,一般来说未来版本升级,只要修改这个版本号即可使用(7.1、7.2、7.3 验证通过)。

配合的执行脚本:

最后是编排工具使用的配置:

这里依旧是使用 Traefik 的服务发现进行自动注册,扩容我已经讲过好多次了,翻翻前面的文章吧:D。

这里为了能够达到用户和 GitLab 互通等,我还做了一个简单的默认配置,保存在 data/conf/sonar.properties,并使用编排工具映射到容器内,你也可以选择直接把配置打到容器里,或者走配置中心进行远程获取(最佳方案)。

如果你有想定制修改的地方,可以参考官方文档,限于篇幅和时间,这里也先略过,后面还有好多内容。

构建你的扫描器镜像

扫描器我这里分为了两部分,一个镜像是给用户使用的,也就是跨平台的 扫描工具,另外一个是专属于 GitLab Runner的扫描器。

两者差异主要是是否要进行文件挂载、以及是否包含默认执行入口,为了方便维护,我将跨平台的镜像设计为基础镜像,使用脚本基于基础镜像进行修改。

下面是基础镜像:

可以看到,基础镜像包含可配置化的 Node 版本,以及可配置的扫描器,当然,也支持私有证书的授信。

在本地执行的话,到项目代码根目录,需要输入下面的命令运行即可,结果等同使用 CI Runner 执行。

交付给 CI 使用的镜像大致相同,前文提到的脚本内容如下:

在执行完毕你会获得另外一个去除了部分内容的 Dockerfile

如何使用,在上一小节定义 GitLab Runner 有提过,定义 image 字段后,添加一行执行脚本 sonar YOUR_PROJECT_ID 即可。

关于 CI Runner

至于文章中一直提到的 CI Runner,如果公司为你准备好了,直接使用就是了。

如果还没有,参考下面命令,根据自己需求进行调整,注册一个 docker 类型的执行器即可。

其他

最后,我特别喜欢来自 sonarlint 的一句话,也送给你:

Fix issues before they exist

今天下午还有事情,行文仓促,难免有误,如果你发现问题,欢迎向我反馈。

–EOF