CI/CD系列 | 如何把持续集成放在本地?

2,348 阅读6分钟

本系列将会从宏观角度,讲述CI/CD相关知识。系列文章不求把每一项都讲仔细,而是让大家能对CI/CD整体流程有大致的概念。无论你是前端,后端,或是运维团队,只要是CI/CD链路上的一份子,相信这系列文章对你都会有帮助。 阅读更多专栏文章

本文讲述内容定位为:CI 持续集成

image.png

本地执行持续集成

现在市面上的大部分CI/CD工具已经非常成熟了,自动化程度都很高。然而,对于小型团队或者个人开发者来说,未必能得到额外的CI/CD服务资源 。对于这种情况,把CI过程放在本地执行,也许是最适合的方案。

优势

在之前介绍CI/CD的文章中提过,持续集成环节的目标是提前发现问题代码,确保上交代码的质量。从这个角度来看,这部分工作完全可以放在开发者本地进行。带来的好处是:

  • 减低成本:免去额外的CI资源
  • 个人定制化: 开发者可以根据实际情况,定制化修改CI规则。

缺点

诚然,大部分的团队不会选择在本地进行CI,因为它会带来一些问题:

  • 额外的环境要求:开发者在搭建开发环境之余,还需要配置CI需要的运行环境。
  • 增加代码提交时间:每次提交代码前,都需要执行CI操作,会使代码提交的时间变长。
  • 占用开发资源:把CI放本地,本质上是运行资源的一种转嫁。开发者在执行CI时可能会被占用部分硬件资源,可能导致其他开发进度受阻。

在了解完把持续集成放本地的优劣之后,我们来看看有什么实现的方案。

利用Npm Scripts

这个方案是NodeJs开发者的专属。其实Npm设计scripts的时候,留了两个可供开发者调用的Hook—— prepost

使用方式

开发者在定义 npm script 的时候,可以通过定义 pre + scriptpost + script 的方式,让npm自动执行某些命令。其中执行顺序为pre脚本——指定脚本——post脚本。举个例子:

{
  ...
  "scripts": {
    "precompress": "{{ compress命令执行之前触发的操作 }}",
    "compress": "{{ compress命令 }}",
    "postcompress": "{{ compress命令执行之后触发的操作 }}"
  }
  ...
}

观察上方例子,假如我们已经有了一个compress命令,我们可以继续增加名为precompress或者postcompress的script。这样每次执行npm run compress的时候,Npm都会自动在package.json的script中找是否存在precompress或者postcompress命令,如果存在,就会指定顺序执行。

Life Cycle Scripts

虽然我们可以用pre、post很自由地为脚本添加hook命令,但这种自由并不是无限制的。Npm本身保留了一系列的默认脚本,官方把这些scripts叫作 Life Cycle Scripts(生命周期脚本) 。这些脚本是有固定执行条件的,换句话说,只要你在package.json中定义了这些脚本,只会在Npm规定的条件下执行,而不是按上文提的pre、post规则。

目前 Life Cycle Scripts 有以下例子:

image.png

使用场景

常见的Npm Scripts使用场景,是npm pack 和 npm publish。这种情况一般是某位开发者维护一个团队内部的npm包,每次修改完之后发布到指定的npm仓库。举个例子:开发者可以把源码构建的动作放在

prepare 中,这样只要执行publish就可以自动构建代码。同时,也可以做代码规范扫描等操作。

Git Hooks

与Npm Scripts相比Git Hooks是更通用的方式,因为它没有开发语言的限制,适用于所有开发者。

跟NpmScripts一样,Git Hooks是 Git 官方留的一些列git操作的生命周期钩子,用户定义之后,可以在某个git操作触发时,执行事先规定的脚本。

使用方式

Git Hooks的使用很简单,在任何一个初始化git 的项目目录下找到 .git/hooks 打开即可。

image.png 在默认情况下可以看到一些列以.sample结尾的文件,这些就是 Git Hooks 的用例示范,想要激活某个hook只要把文件名的.sample后缀删掉即可。现在随便打开一个文件,可以看到下图内容:

image.png

可以看到 Git Hooks 的脚本是用shell写的,这也是为什么说它适合所有开发者的原因。在sample文件中也写部分使用说明,上图内容就是pre-commit.sample的内容,pre-commit 的脚本会执行在 git commit 命令执行之前。

接下来我们来尝试一下,先在 .git/hooks/ 下新建一个文件,命名为 pre-commit。并写入内容

#!/bin/sh
echo 'pre-commit 执行了!'

然后在项目文件中,随便改点东西,再执行一次commit。

# 随便新建一个文件
touch ./temp.txt
# git add 处理
git add ./temp.txt
# 测试 git commit 
git commit -m 'test'

可以看到下图输出结果:

image.png

现在,相信大家已经掌握了 Git Hooks 的使用了,开发者可以根据自己的时间情况来修改不同的脚本内容,以完善项目的CI步骤。

可选HOOKS

Git 留给我们可以选择的Hooks有很多,下面列举一些使用频率比较高的部分,如果有兴趣了解更多的朋友,可以自行到官网查阅。

名称说明
pre-commitgit commit执行前,可以通过git commit --no-verify绕过
post-commitgit commit执行后,因为不会影响commit的结果,所以一般用作通知提示。
pre-merge-commitgit merge执行前,可以通过git merge --no-verify绕过
commit-msggit commit 和 git merge 执行前,可以通过 --no-verify参数绕过
pre-rebasegit rebase执行前。

使用场景

Git Hooks 是使用场景显然会更广,主要体现在两点:

  • 没有开发语言限制,适用于所有开发者。
  • 与 git 结合,可以有效保护仓库代码。

在此CI环节,我们可以实现诸如代码检查,分支管理,更新推送等操作。

Husky

相信大家已经发现,尽管我们改了git hooks 内容,但在 .git 文件夹中的内容是不参与git同步的,这样我们的脚本便不能跟团队其他成员共享。此时Husky出现了,它是一个专门处理 git hooks 的开源工具。

它的工作原理很简单,通过把所有的git hooks 定义在一个配置文件中,并把配置文件加入git管理。这样团队其他人都可以得到这个配置文件,从而实现把 git hooks 共享了。

配置文件例子:

{
  "hooks": {
    "pre-commit": "echo 'pre-commit 执行了!'"
  }
}

Husky的Github 地址是: github.com/typicode/hu…,有兴趣的朋友可以自行了解。

总结

今天我们了解了在持续集成环节中,最低成本一种操作——把CI放在本地。这种操作对于小团队,或个人开发者来说是价值很高的选择。如果你真正学习CI/CD,这也是一个学习尝试很好的方式。希望大家在掌握这种方法之后,在面对合适的场景时,可以有更多的选择。

进一步了解

Npm Scripts文档:docs.npmjs.com/cli/v8/usin…

Git Hooks 文档:git-scm.com/docs/githoo…

如果你觉得本文对你有一点帮助,麻烦给我点个赞吧~~ 谢谢