【Devops】通过 Gihub WebHooks 实现自动构建部署 Vue 项目

按照 之前这篇博文 将 Vue 项目打包发布到服务器上,每次更新都需要手动 build 并通过 Filezilla 传输到服务器,虽然也并不麻烦,但总显得不够自动化,不够工程化~

于是,决定研究一下如何自动构建与部署项目,使得代码更新后只需一次 push 就能自动完成从更新到构建到部署的全过程!

配置详情

和 之前这篇博文 一致

客户端:Windows 10 家庭版

服务器:CentOS 7 + Nginx

初步尝试

首先,我选择的是之前项目组中使用过的 Travis

由于这种方式的尝试 没有成功 而暂被搁置,这里不再详细叙述每一步操作,仅仅简述一下原理和过程

如果大家想要了解具体过程请关注本人的后续博客哦(明示关注)

1. 首先,使用 Github 账号登录 https://www.travis-ci.org/,可以在里面看到所有的 public 仓库并将其 activate

2. 在项目中编写 .travis.yml 定义脚本,此时,你每进行一次 git push 都会触发 travis 执行你所定义的脚本

3. 通过 ssh 生成公钥私钥,添加到服务器的 /.ssh/authorized_key 中,这样才能免密码访问你的服务器

4. 由于 travis 上的一切全部是公开的,为了防止密钥泄露,我们必须使用 ruby 的 gem 安装 travis 命令行工具;使用命令行工具可以将密钥再次加密后秘密存储

5. 让 travis 携带密钥访问你的服务器,执行提前书写好的 shell 脚本,完成代码更新-构建-部署的过程

没有成功的原因是因为...下 ruby-installer 太慢了......

原理详解

虽然 travis 的尝试没有成功,但也并不是全无收获,至少明确了自动化构建部署的原理究竟为何

在 travis 中,一次 push 引发的流程是这样的:

git push → github 通知 travis → travis 执行 .travis.yml 中的脚本 → travis 通过脚本连接到服务器并执行服务器上的 shell 脚本 → shell 脚本完成服务器上的代码更新 → shell 脚本对更新后的代码进行构建和部署

可以看出,更新构建部署这些最为核心的步骤都是通过 shell 脚本完成的,所以我们在服务器外做的一切,其实都只是为了在代码更新时对服务器做一个通知,让它执行我们预先编写好的脚本

Github WebHooks

明确了原理之后,我们就有了一个更简单的解决方案——Github WebHooks

它可以在 git push 之后自动向指定的 URL 发出一个请求,只要你在服务器监听这个请求,在接收到之后做出相应的处理就可以完成工作(跳过了 Travis 的步骤,没有中间商赚差价)

1. 首先,进入你想要自动部署的 Github 项目,添加一个 WebHook

Payload URL 就是代码更新时将会被请求的 URL,填入 http://<服务器IP>:<监听的端口号>/路径

Secret 是设置的密码,在下面会用的,假设我这里填入的是 123456

 2. 监听请求

其实这里的操作就相当于在服务器上运行一个后端程序,接收请求做一定的操作,JS、PHP、Java 等等都能做到

这里提供一个 js 脚本(源代码来自 这篇博文,我针对自己的情况做了一些修改)

// cd-helper.js
var http = require('http')
var createHandler = require('github-webhook-handler')
// 这里的 secret 值为之前在 GitHub 上设置的密码
var handler = createHandler({ path: '/cd', secret: '123456' })
 
// 注意!只有 exec 才能一次执行多条指令!如果使用 spawn 会出错!
function run_cmd(cmd) {
    var exec = require('child_process').exec;
    exec(cmd);
}

// 这里需要进行针对性的修改
function generateBash(projectName) {
    return `chmod +x /my/nginx-project/${projectName}/cd.sh; /my/nginx-project/${projectName}/cd.sh`;
}

// 监听在 Github WebHook 中所写的端口
http.createServer(function (req, res) {
    handler(req, res, function (err) {
        res.statusCode = 404
        res.end('not found')
    })
}).listen(8888)
 
handler.on('error', function (err) {
    console.error('Error:', err.message);
})

// 监听 git push 事件,根据项目名做不同的处理
handler.on('push', function (event) {
    switch(event.payload.repository.name) {
        case 'vant-study':
            console.log("vant-study updated");
            run_cmd(generateBash('vant-study'));
            break;
    }
})
 
handler.on('issues', function (event) {
    console.log('Received an issue event for %s action=%s: #%d %s',
        event.payload.repository.name,
        event.payload.action,
        event.payload.issue.number,
        event.payload.issue.title);
})

在运行这个脚本之前,首先要确保你的服务器上已经安装了 node(不会安装请参见 这篇博文)

接着将脚本上传到服务器(我这里上传至 /my)

最后登录到服务器,通过命令行使脚本持久化运行

cd /my
npm install github-webhook-handler
nohup node cd-helper.js >nohup.out 2>&1 &

检验:通过客户端访问之前填写的 Github WebHook 请求 URL,如果看到 not found,说明脚本正常运行

3. 编写 shell 脚本

在上面的 js 代码中可以看到,我这个脚本的核心其实是执行了 chmod +x /my/nginx-project/${projectName}/cd.sh; /my/nginx-project/${projectName}/cd.sh 这两条命令,其含义是授予项目中 cd.sh 脚本执行的权限并执行它(看不懂的朋友请学习 Linux 基础命令)

我的 cd.sh 也很简单,请看:

cd /my/nginx-project/vant-study
git pull
npm install
npm run build
nginx -s reload

作用就是 cd 进入项目目录,git pull 更新代码,npm install 安装依赖,npm run build 构建项目,nginx -s reload 重启 nginx

这里 shell 脚本的编写其实是具有高度的特殊性的,由于每个人部署项目的方式和服务器路径的不同,这里需要大家真正理解脚本的作用和执行过程

以我为例,通过 之前这篇博文 大家也知道,我对于项目的部署就是更新 dist 目录再重启 nginx 即可(这里注意,和 之前这篇博文 不一样的一点是我把原来 nginx 配置中的 /my/nginx-project/dist 改成了 /my/nginx-project/${projectName}/dist,大家要懂得变通哦!不能无脑抄!)

所以,我要做的工作只是将新代码 pull 下来重新 build,大家请根据自己部署方式的不同灵活编写 shell 脚本哦!

4. 完结撒花

上述工作完成后,先进行一次 push 和 pull,确保 cd.sh 已经存在在服务器端的项目中,之后客户端对于项目的更新就都可以在 push 后自动构建和部署到服务器啦!

(这里将 shell 脚本放在项目中其实不是一个很好的选择,因为如果需要更新 shell 脚本,必须先人工做一次 push + pull 才能保证服务器端的 shell 脚本是最新的版本,如何改善请大家积极思考)

你可能感兴趣的:(部署&服务器,Github,WebHooks,Vue,CI/CD,devops,CentOS)