Node—关于自动化构建与持续集成的学习笔记

2,151 阅读16分钟

一、自动化构建相关概念

1.1. 什么是自动化测试?

自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常,在设计了测试用例并通过评审之后,由测试人员根据测试用例中描述的规程一步步执行测试,得到实际结果与期望结果的比较。在此过程中,为了节省人力、时间或硬件资源,提高测试效率,便引入了自动化测试的概念。

简而言之,自动化测试就是自动完成单元测试,单元测试属于自动化构建的一类构建任务。

1.2. 什么是自动化构建?

所谓自动化构建,就是通过自动化构建脚本的调度,让不同的构建工具互相配合,由计算机自动完成软件构建操作。

摊煎饼果子就是构建,阿姨给你摊就是人工构建,机器给你摊就是自动化构建。

构建表示一个处理操作,这个处理操作有输入和输出,输入是原材料,通过构建的操作产出输出结果,摊煎饼果子是构建,面糊、鸡蛋是原材料,煎饼果子就是输出。软件开发当中,构建的原材料就是程序代码,构建的结果就是软件。

1632902158.png

不同的编程语言和不同的编程项目,它们构建操作的复杂度是不同的,以C语言为例,C语言的源代码是.c、.h文件,要构建生成可执行的程序需要经过两个步骤:

  • 首先将源文件编译成.o或者.obj目标文件
  • 再把目标文件和静态库.lib文件链接成可执行文件

由此可见,C语言的构建过程是两个基本操作,分别是编译和链接。

1632902195.png

C语言是编译型程序,不构建是无法生成可执行程序的。对于Web,我们的编程语言是JS,JS是解释型语言,并不需要编译和链接,可以直接在浏览器环境中运行,但是JS项目同样需要构建。

1.3. 什么是持续集成?

持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。

关于持续集成百度百科解释的非常到位:baike.baidu.com/item/%E6%8C…

1.4. 前端项目五大类常见构建任务

下图是前端项目常见的构建任务分类:

1632902229.png

JavaScript没有C语言里面的编译和链接构建任务,但是这里有五大类构建任务,比C语言来的更多、更复杂,所以经常说前端开发软件工程的复杂度往往大于算法复杂度以及架构的复杂度。前端项目和后端项目的构建任务是不一样的,虚线框表示后端项目常见的构建任务,对于后端项目来说,常见的构建任务只有这两类。

所以说后端项目的构建比前端项目更简单,比如node.js开发的后端代码不需要压缩js文件来进行性能优化。

1.5. 软件开发中构建相关的共性

编程语言的不同,创建项目的类型不同,构建任务也不同。构建任务千差万别,意味着不管是人工构建还是自动构建都是不同的。

这很好理解,比如你做一套煎饼果子和做一套婚宴,这中间的操作复杂度肯定是不一样的。

所以需要做一个抽象,把编程语言和不同项目的差异都剥离出来,将构建相关的、共性的软件开发过程罗列出来,如下图所示,单独一列就是狭义的自动化构建,从左到右这六列都加起来就是广义的自动化构建。

1632902252.png

1.6. 自动化构建的优势

  1. 由计算机自动完成,不需要人工参与,所以可以有效的减少构建、部署过程中的错误和纰漏

  2. 由计算机自动执行,可以提高开发效率,计算机自动执行构建任务的成本很低,意味着可以提高构建的频率,所以可以每日构建,或者代码有了变更就立刻执行构建任务,可以持续构建

  3. 自动化构建会执行单元测试,单元测试首先要对代码做模块化设计,模块化更有利于代码的维护和重构

  4. 通过自动化构建中的单元测试可以有效提升软件质量,减少程序中的bug

  5. 通过自动化构建中的静态代码检查可以使项目团队成员编写的代码更符合编码规范,更有利于团队协作

1.7. 构建的流程

我们编写的软件从无到有在开发的整个生命周期中会在三种不同的环境上运行。

同一个产品在不同环境的代码配置是不一样的,对应两种模式,例如:你的女朋友在家里和在单位穿衣打扮肯定不一样(如果一样,我只好送你一句wc),场合不一样要求也不一样,同样道理,同样功能的软件产品在不同的环境上面会构建不同的模式。如下图所示:

1632902378.png

测试环境需要找Bug,为了方便调试,所以代码里面会包含大量调试信息,生产环境里面已经找过Bug了,所以不需要这些调试打印信息,它需要的就是性能和精简。因此可以说调试模式对应的就是测试环境(严格意义上讲开发环境不对应任何模式,非要说的话可以算是调试模式),发布模式对应的就是生产环境。

1.7.1. 环境的区别

1632902433.png

1.7.2. 两个模式的区别

1632902456.png

二、自动化构建的相关工具

玩过吃鸡的都知道落地以后首先要捡抢,自动步枪、冲锋枪等等,捡了武器才能打架,同样的,自动化构建里面要完成自动化构建操作,也需要相应的工具软件来支持,这里面需要三大类软件来支持:

1632902478.jpg

2.1. 版本控制系统

版本控制系统是自动化构建的基础,往往跟持续集成工具配合使用来完成自动化构建,主流的版本控制系统有下图中两大类。

1632902853.jpg

svn已经过时了,现在都是用git。

2.2. 开源的分布式版本控制系统开源社区

有了git还不够,在团队开发时往往需要远程仓库来集中存放代码,这时候就需要git服务器,在大型的互联网公司一般都会使用gitlab来搭建自己的服务器存放私有代码,小团队或是个人开发者可以使用免费的git服务器,一般也称为开源社区,常用的开源社区如下图。

1632902916.png

2.3. 构建任务工具

前端项目开发中,构建任务比较多(五大类),操作也比较复杂,这时候需要专门的构建任务工具,常见的构建任务工具如下,前端项目构建工具可选择grunt、gulp、webpack,node.js后端项目简单的选择npm即可(npm中也可以写script脚本),选择什么工具看团队。

1632902942.jpg

在构建的任务工具里面往往需要编写构建脚本,构建脚本来安排是哪种构建模式、每个构建模式下边要执行哪些任务清单。

每一个构建任务往往是需要配置参数的,这里面会配置三类参数:

  • 构建操作的输入参数
  • 构建操作产生的结果放在哪,也就是输出参数
  • 构建操作的一般参数

以图片压缩为例,第一个参数就是告诉构建任务图片源文件放在哪个目录下,第二个就是告诉构建任务压缩之后的图片放到哪个目录下,第三个参数就是图片压缩的比例是多少。

2.4. 持续集成工具

准确来说持续集成工具应该叫做持续集成服务器,因为所有的自动化构建执行操作都是在持续集成服务器上完成的,你必须有一台服务器,在服务器上面去干活,去构建任务。

常见的持续集成工具有下面几个:

1632907141.jpg

用的最多的是Travis CI和Jenkins,Travis CI是跟github集成的,可以支持大部分主流的编程语言。Jenkins是开源的,很多互联网公司都会在企业内部搭建自己的Jenkins服务器来完成自动化构建。

三、实战(Gitbook自动化构建)

实战结果如下图所示

image.png

demo链接:mr-jemp.github.io/cjpbook/

3.1. 自动化构建工具选择

  • 版本控制系统选择:github
  • 构建任务工具选择:npm
  • 持续集成工具选择:Travis CI

3.2. 操作步骤

首先第一次发布需要人工构建和发布,后面的发布就可以采用自动化了。

3.2.1. 第一次发布步骤(人工)

1、进入github,创建一个新的仓库(添加README文件和.gitignore文件,选择MIT协议)

1632907711.png

2、克隆仓库,进入项目目录,创建gh-pages分支(注意分支名是规定好的,别乱写,这个分支用来发布)

1632907839.png

1632907857.png

1632907869.png

3、切换到主分支(2020年10月1日后github将创建仓库的默认分支改成了main),创建两个章节.md文件,再添加一个SUMMARY.md文件(用于电子书左侧导航)

1632907963.png

1632907977.png

1632907988.png

4、编写.md文件的内容

1632908014.png

1632908040.png

5、全局安装gitbook cli工具(需要使用淘宝源),使用gitbook -V命令查看版本,会自动安装gitbook 3.2.3版本(有的版本会安装失败,我的node版本10.21.0安装成功),运行gitbook build命令生成电子书

1632908104.png

等它安装完成,非常慢,可能十几分钟,淘宝源也依然慢,安装完成如下图所示

1632908157.png

安装成功再次输入gitbook -V看到如下输出可以验证是否安装成功

1632908199.png

然后运行构建命令

1632908215.png

构建成功后项目目录下多了个_book目录,这就是构建结果存放位置,里面文件如下

1632908254.png

6、编辑.gitignore文件,将_book目录排除,不作为仓库内容提交,然后将代码推送到main分支

1632908296.png

1632908319.png

此时github仓库中main分支代码如下

1632908361.png

7、切换到gh-pages分支,将_book目录下的所有文件复制到项目根目录下,然后删除_book目录(删除后我们的git仓库不需要额外再保存一份打包代码),将改动提交到该分支并推送到远程分支,这个推送远程仓库的过程就是发布的过程

1632908431.png

删除_book目录后的文件如下图所示(怕有人看不明白,所以截图说明一下)

1632908538.png

然后将文件改动推送到远端gh-pages分支(第一次推送时需要使用git push --set-upstream origin gh-pages命令在远程仓库创建该分支,后面只需要使用git push命令提交即可)

1632908679.png

1632908689.png

这样第一次人工构建就发布成功了,发布后的访问地址是:github的名字 + github.io + 仓库名称

如:xxx.github.io/cjpbook/

发布后的页面如下图所示

1632908773.png

3.2.2. 后续发布步骤(自动)

假如此时我们要新增一个章节,需要做如下步骤:

1、切换到main分支,创建ch03.md文件

1632909214.png

2、编辑ch03.md文件的内容,并修改SUMMARY.md文件的内容

1632909236.png

1632909254.png

增加了一个章节之后还需要做重复的工作,再运行gitbook build,然后切换到gh-pages分支上将新生成的文件复制过去完成发布动作,非常麻烦,如果后面还有十次添加,我们就要执行这两个动作十次,所以我们需要让下图的两个动作自动完成,这就是自动化构建。

1632909281.png

以travis CI工具为例,下图是官方文档的说明,首先需要使用github授权Travis CI才可以使用

1632909302.png

文档地址:docs.travis-ci.com/user/tutori…

访问Travis Ci服务器:app.travis-ci.com/,用github账号去登录,会给你发验证邮件,验证成功后进入Dashboard页面,选择需要构建的仓库,可以点击Trigger build按钮进行构建

1632909543.png

然后需要在项目根目录下创建.travis.yml文件,这是travis CI持续集成服务器的配置文件,这个配置文件相当于做了一个持续集成的脚本文件,意味着持续集成服务器收到你的构建触发要做哪些工作,常见配置如下:

language: node_js
node_js:
  - "10"

# 这个script在node.js项目中就是npm test
after_script:
  - gitbook build    # 构建成html文件,默认在_book目录下
  - cd ./_book       # 进入_book目录
  - git init         # 初始化git仓库
  - git config user.name "${USER_NAME}"    # 设置git用户名
  - git config user.email "${USER_EMAIL}"  # 设置git用户邮箱
  - git add .        # 将文件改动添加到暂存区
  - git commit -m "publish gitbook" # 将暂存区内容添加到本地仓库
  - git push --force --quiet "https://${ACC_TOKEN}@${GH_REF}" master:${BRANCH} # 将文件改动推送到版本库

# 在main分支上有了新的提交会触发.yml脚本
branches:
  only: 
    - main

配置文件分三大段:

  • 第一段表示说明项目是用什么编程语言去写的
  • 第二段是构建任务
  • 第三段表示这段脚本在什么情况下触发

注意git push这一行的代码,后面的分支名是master,如果写成main会导致最后一步提交代码时报下图中的错误信息,原因是github在2020年10月1日将仓库的默认分支名修改成了main,但是通过git init命令创建的仓库默认分支名是master,因为匹配不上所以报错,这里踩了坑提醒一下

1632909671.png

参考:www.jianshu.com/p/e8342a72c…

3、将代码变更提交到main分支

  • git add .
  • git commit -m '提交信息'
  • git push

4、回到github,切换到main分支,查看提交

1632909768.png

可以看到提交记录后面有一个图标,图标有三种,分别是:

  • 黄色圆圈:代表正在构建
  • 打勾:表示构建成功
  • 打叉:表示构建失败

点击图标,点击Details

1632909797.png

拉到最底下可以看到有个链接,点击View more details on Travis CI进入Travis CI工作台

1632909817.png

这里可以看到详细的构建信息

1632909838.png

现在的构建是失败的,为什么?

原因是我们的.travis.yml文件中有很多类似${USER_NAME}这种变量,这些为什么要用变量来表示?是因为.travis.yml这个文件是个纯文本的脚本文件,会放到仓库里面,我们创建仓库时选择的协议是MIT协议,意味着这些代码是开源的,这几个变量的位置是敏感信息,不希望被他人知道,因此用变量来代替。

那怎么让这几个变量正确识别呢?

只需要在travis CI服务器上面针对这个项目来设置这五个环境变量,设置好之后这个脚本文件就能成功跑了。

脚本的环境变量如下:

  • ACC_TOKEN:xxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • BRANCH:gh-pages
  • GH_REF:github.com/yourname/cjpbook
  • USER_EMAIL:xxxxxxxxx@qq.com
  • USER_NAME:xxxx

将这几个变量的值都改成你自己的信息。

因为travis在编译好后需要把编译好的代码push到你的仓库分支下面,那肯定需要你仓库的访问权限,这就是我们生成token的意义。

点自己github右上角的图像-> 点Settings->左边会有一个列表点击Developer settings->在点击Personal access tokens->点击Generate new token->为token起一个名字ACC_TOKEN,只勾选第一项列表,只要有推送代码的权限就可以了,然后点击Generate token生成。

生成token后不要关闭当前页面,请记下此token;因为它只显示一次,忘记了只能再次生成。

1632909985.png

5、到travis CI服务器上添加环境变量,点击More options,选择Settings

1632910025.png

在这里输入环境变量的name和value,然后点击Add按钮进行添加,添加完成后会在上面显示

1632910047.png

有了这五个环境变量之后,其实还是有问题的,我们来看构建信息

1632910065.png

命令行的出错信息是exited with 2,只要命令行的退出码不是0都是错误退出。

6、在项目目录下执行npm init -y命令生成package.json文件

1632910094.png

在这个package.json文件中有一个script脚本,脚本中有一个test命令,这就是npm test自动化测试的脚本命令,这个脚本里面有一段信息,就是执行两个命令,一个是err打印信息,另一个是退出,这个exit 1是不对的,这个退出码是0才对,所以我们需要将退出码更改为0,这样将来就会执行这个测试命令,因为我们这个demo不需要测试,只要是正确的退出码这个命令就通过了。

1632910128.png

还有一个问题,因为这个.travis.yml文件的构建脚本中有一条gitbook build命令,Travis CI服务器把你的代码克隆下来之后不会给你安装gitbook这个工具软件,因此我们还需要在package.json中添加devDependencies依赖来安装gitbook-cli工具

1632910151.png

7、将代码变更推送到远端仓库main分支

  • git add .
  • git commit -m '提交信息'
  • git push

回到github,查看提交,重复上面第4步,可以看到本次代码构建成功

1632910216.png

仓库里也可以看到本次提交是打勾的

1632910231.png

此时回到gh-pages分支可以看到编译好的ch03.html文件了

1632910247.png

刷新gitbook页面,可以看到第三章添加成功

1632910263.png

四、总结

Travis CI自动化构建流程是什么?

以上面实战为例,当你或者你的团队成员在仓库main分支上提交新的变更之后,会触发Travis CI服务器来做持续集成,前提是你的项目目录下有.travis.yml这个配置文件。

Travis CI服务器会做什么事情?

Travis CI服务器首先会克隆你的仓库,相当于在Travis CI服务器启动一个开发环境(虚拟机),接下来导入五个环境变量,然后安装node.js环境和版本,接下来执行npm install安装项目依赖,因此就会安装gitbook-cli工具,接着执行npm test来进行测试,接下来就是执行我们在.travis.yml文件中编写的after_script命令,依次执行完每一条之后就完成退出了。

自动化构建.drawio.png

对于node.js项目来说,Travis CI会执行两个默认脚本,如下图所示,npm test执行的实际上是项目文件中的package.json中的script代码,注意需要将默认脚本退出码改成0,否则会导致构建失败。

1632965086.png

Travis CI服务器上默认会执行以下九个脚本,如下图所示,这九个脚本实际上分为三大类,如下图中的蓝条部分:

  • 第一类:安装项目依赖。项目依赖不安装好项目是不能运行的
  • 第二类:执行脚本。脚本包含执行构建任务、单元测试等等
  • 第三类:完成部署操作。

1632965140.png


以上我们通过Travis CI + github + npm演示了自动化构建的流程,不同工具需要做的任务会有所不同,但只要我们掌握自动化构建的工作流程,选择不同的工具只需要进行相应的调整即可。

演示代码已上传github:

github.com/Mr-Jemp/cjp…