自动化构建之 Jenkins™

1. 使用 Jenkins 自动化构建

1.1. 背景

前端构建及部署工作大多都是人工去做,随着业务扩大,项目迭代速度变快,人员增多,各种问题都暴露出来,本文是对前端自动化工作流进行探索后的一篇经验分享,将通过一个简单案例分享一下基于 Jenkins 的前端自动化工作流搭建的过程,搭建完这套工作流,我们只需要在本地发起一个 git 提交,剩下的打包构建,代码部署,提醒等功能全部自动化完成,让持续集成、持续交付、持续部署变得简单易操作,真正解决人工构建部署的诸多问题。

1.2. Jenkins 是什么

Jenkins 是一款业界流行的开源持续集成工具,广泛用于项目开发,具有自动化构建、测试和部署等功能。

1.3. 本案例要实现的功能

本地项目发起一个 git 提交,剩下的打包构建,代码部署等全部自动化完成。

2. 项目准备

2.1. 项目准备

先准备本地一个项目,我这里直接使用 vue-cli 脚手架生成了一个项目,其他技术栈也一样,只要是个项目就行。

  • 在创建项目之前,必须要有 nodeJS 环境(nodeJS下载地址);并将 npm 的镜像设置为国内淘宝镜像: npm config set registry https://registry.npm.taobao.org
  • 使用 npm 全局安装 vue 的脚手架工具,npm install -g vue-cli
  • 使用 npm 全局安装 webpack 的脚手架工具,npm install -g webpack
    本地创建项目 vue init webpack jenkins-demo
    jenkins1
    我们可以选择 yarn 来代替 npm;相比 npm,yar n的速度更快,更安全。可到 yarn官网 进行查看。
    使用 npm install 安装完依赖之后,可以运行 npm start 来查看项目:
    jenkins2

2.2. 创建远程仓库

建立这个项目的远端git仓库,并把本地代码提交上去。可以为 github,gitlab,码云等,我这里用的是 github。
jenkins4

2.3. 服务器环境

我这里用的是一台 CentOS 6.8 64 位服务器,可以使用 yum install 来安装环境配置。

  • Java
    yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel
  • Git
    yum install git 拉取项目时需要;
  • Node
    yum install nodejs 编译前端项目;
  • Jenkins
    yum install jenkins
    jenkins 无非就是一个 war 包,可以在官网直接下载。

2.4. 启动 Jenkins

下载完 war 包后,可以直接通过 java -jar jenkins.war 来运行 Jenkins,也可以通过 tomcat 来运行 Jenkins。

  1. jenkins 的默认端口是 8080,启动成功后在浏览器打开
  2. 进入后会让我们输管理员密码,打开网页上提示路径下的文件,复制密码粘贴输入即可
  3. 然后会让安装需要的插件,此处选默认即可,等待安装完成
  4. 创建一个管理员账户
  5. 上面都完成后会看到这个界面
    jenkins3
    该案例最终 Jenkins 运行在 http://111.231.238.23:8080/

2.5. 创建任务

点击创建一个新任务自由风格的软件项目
jenkins3

3. 实现 git 钩子功能

首先我们要实现一个 git 钩子功能,就是我们向 github/gitlab/码云等远程仓库 push 我们的代码时,Jenkins 能知道我们提交了代码,这是自动构建自动部署的前提,钩子的实现原理是在远端仓库上配置一个 Jenkins 服务器的接口地址,当本地向远端仓库发起 push 时,远端仓库会向配置的 Jenkins 服务器的接口地址发起一个带参数的请求,Jenkins 收到后开始工作。

3.1. 添加远程仓库地址

jenkins6

3.2. 添加触发器

安装 Generic Webhook Trigger Plugin 插件(系统管理-插件管理-搜索 Generic Webhook Trigger Plugin )如果可选插件列表为空,点击高级标签页。
第 2 步安装的触发器插件功能很强大,可以根据不同的触发参数触发不同的构建操作,比如我向远程仓库提交的是 master 分支的代码,就执行代码部署工作,我向远程仓库提交的是某个 feature 分支,就执行单元测试,单元测试通过后合并至 dev 分支。灵活性很高,可以自定义配置适合自己公司的方案,这里方便演示我们不做任何条件判断,只要有提交就触发。在任务配置里勾选 Generic Webhook Trigger 即可。
jenkins6

3.3. 创库配置钩子

仓库配置钩子 此处以 github 为例,进入 github 项目主页后,点击 settings -> Webhooks -> Add webhook。
jenkins6
Payload URL 格式为:http://(User ID):(API Token)@<(Jenkins IP:PORT)>/generic-webhook-trigger/invoke。
userid 和 api token 在 Jenkins 的系统管理-管理用户-admin-设置里。
jenkins6
Jenkins IP 地址和端口是你部署 Jenkins 服务器的 ip 地址,端口号没改过的话就是 8080。密码填你和上面 userid 对应的密码。下面的几个选项是你在仓库执行什么操作的时候触发钩子,这里默认用 push,content-type 默认为 application/json。

3.4. 测试钩子

jenkins6
点击测试,如果配置是成功的,你的 Jenkins 左侧栏构建执行状态里将会出现一个任务。
jenkins6
另外,你也可以试下本地提交代码,提交代码后,Jenkins 也会开始一个任务,目前我们没有配置任务开始后让它做什么,所以默认它只会在你提交新代码后,将新代码拉取到 Jenkins 服务器上。到此为止,git 钩子我们配置完成。

4. 实现自动化构建

git push 触发钩子后,Jenkins 就要开始工作了,自动化的构建任务可以有很多种,比如说安装升级依赖包,单元测试,e2e 测试,压缩静态资源,批量重命名等等,无论是 npm script 还是 webpack,gulp 之类的工作流,你之前在本地能做的,在这里同样可以做。

  1. 首先,和本地运行 npm script 一样,我们要想在 Jenkins 里面执行 npm 命令,先要在 Jenkins 里面配置 node 的环境,当然服务器有 node 环境也可以。
  2. (若服务器已经有 node 环境,可以跳过此步骤)Jenkins 里面配置 node 的环境,可以通过安装插件的方式,使用 nvm wrapper 这个插件。打开刚刚的 Jenkins 任务,点击配置里面的构建环境,勾选这个,并指定一个 node 版本。
    jenkins6
  3. 点击构建,把要执行的命令输进去,多个命令使用 && 分开。
    jenkins6
  4. 保存后,此时本地修改一下代码 push 测试一下(也可以点击立即构建测试),点击本次触发的那个任务,选择控制台输出,将会看到 Jenkins 在云端执行的过程。
    jenkins6
    命令行最后一行是 Finished 状态的如果是 SUCCESS(蓝色)则证明执行的任务都顺利进行,是 FAILURE(红色)则证明中间有重大错误导致任务失败,UNSTABLE(黄色)代表有虽然有些小问题,但不阻碍任务进行,黄色或者红色可以去命令行看下错误输出,看下哪里出了问题。
    如果上一步是SUCCESS,点击项目的工作空间,将会发现多了 dist 和 node_modules 两个文件夹。
    至此,我们已经搭建了一个简易的构建工作流程,构建完成了,我们需要自动化部署。
    jenkins6

5. 实现自动化部署

5.1. SSH Server 配置

自动化部署可能是我们最需要的功能了,公司就一台服务器,我们可以使用人工部署的方式,但是如果公司有100台服务器呢,人工部署就有些吃力了,而且一旦线上出了问题,回滚也很麻烦。所以这一节实现一下自动部署的功能。

  1. 首先,先在 Jenkins 上装一个插件 Publish Over SSH ,我们将通过这个工具实现服务器部署功能。
  2. 在要部署代码的服务器上创建一个文件夹用于接收 Jenkins 传过来的代码,我在服务器上建了一个 /work/front 的文件夹,用于接收传送过来的文件(注意文件的权限)。
  3. Jenkins 想要往服务器上部署代码必须登录服务器才可以,这里有两种登录验证方式,一种是 ssh 验证,一种是密码验证,就像你自己登录你的服务器,你可以使用 ssh 免密登录,也可以每次输密码登录,系统管理-系统设置里找到 Publish over SSH 这一项。

重点参数说明:

Passphrase:密码(key的密码,没设置就是空)
Path to key:key文件(私钥)的路径
Key:将私钥复制到这个框中(path to key和key写一个即可)

SSH Servers 的配置:
SSH Server Name:标识的名字(随便你取什么)
Hostname:需要连接ssh的主机名或ip地址(建议ip)
Username:用户名
Remote Directory:远程目录(上面第二步建的testjenkins文件夹的路径)

高级配置:
Use password authentication, or use a different key:勾选这个可以使用密码登录,不想配 ssh 的可以用这个先试试
Passphrase / Password:密码登录模式的密码
Port:端口(默认22)
Timeout (ms):超时时间(毫秒)默认300000

配置完成后,点击 Test Configuration 测试一下是否可以连接上,如果成功会返回 success,失败会返回报错信息,根据报错信息改正即可。
jenkins6

5.2. 构建配置

接下来进入我们创建的任务,点击构建,增加 2 行代码,意思是将 dist 里面的东西打包成一个文件,因为我们要传输。
传输时请特别注意是否拥有被传输的文件夹的读写修改权限。
jenkins6

1
2
3
4
npm install &&
rm -rf dist &&
npm run build
tar -zcvf dist.tar dist

点击构建后操作,增加构建后操作步骤,选择 send build artificial over SSH, 参数说明:

Name :选择一个你配好的ssh服务器
Source files :写你要传输的文件路径
Remove prefix :要去掉的前缀,不写远程服务器的目录结构将和 Source files 写的一致
Remote directory :写你要部署在远程服务器的那个目录地址下,不写就是 SSH Servers 配置里默认远程目录
Exec command :传输完了要执行的命令,我这里执行了解压缩和解压缩完成后删除压缩包2个命令。

jenkins6

5.3. 配置 Nginx 代理静态资源

jenkins6

5.4. push 测试

现在当我们在本地将 Welcome to Your Vue.js App 修改为 Jenkins 后发出一个 git push,过一会就会发现我们的服务器上已经部署好了最新的代码。
jenkins6
jenkins6

6. 参考文档

持续集成是什么
前端开源项目持续集成三剑客