按照 之前这篇博文 将 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
它可以在 git push 之后自动向指定的 URL 发出一个请求,只要你在服务器监听这个请求,在接收到之后做出相应的处理就可以完成工作(跳过了 Travis 的步骤,没有中间商赚差价)
Payload URL 就是代码更新时将会被请求的 URL,填入 http://<服务器IP>:<监听的端口号>/路径
Secret 是设置的密码,在下面会用的,假设我这里填入的是 123456
其实这里的操作就相当于在服务器上运行一个后端程序,接收请求做一定的操作,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,说明脚本正常运行
在上面的 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 脚本哦!
上述工作完成后,先进行一次 push 和 pull,确保 cd.sh 已经存在在服务器端的项目中,之后客户端对于项目的更新就都可以在 push 后自动构建和部署到服务器啦!
(这里将 shell 脚本放在项目中其实不是一个很好的选择,因为如果需要更新 shell 脚本,必须先人工做一次 push + pull 才能保证服务器端的 shell 脚本是最新的版本,如何改善请大家积极思考)