公司从当初的SVN代码版本控制,FTP手动上传项目代码zip压缩包,到现在的git代码版本控制,jenkins一键打包部署环境,已经初步完成了手动到自动的大跃进.回过头来看看本身的项目,还处在本地仓库修改代码 -> 提交远程github仓库 -> 本身上服务器手动pull最新分支代码的原始阶段.不能忍javascript
OK,接下来让咱们开始咱们的进化偷懒之旅,你们一块儿跟随个人心路历程一块儿进化.java
当咱们本地仓库修改完成push远程仓库以后, 服务器可以自动拉取最新分支代码,自动完成项目部署.node
工欲善其事必先利其器,开始行动前有必要理解一波webhooks钩子自动部署原理;nginx
本地仓库 -> (push提交代码) -> 远程仓库(webhooks钩子) -> (发送带有key的post请求) -> 测试/生产服务器(执行部署脚本)
复制代码
知悉了原理以后咱们来看看咱们须要准备些什么:git
远程仓库的webhooks设置你只须要找到具体位置点进去:github
URL: 设置post请求的地址(即服务器服务地址)web
key: 这个key能够设置也能够不设置,建议设置,防止他人随意请求服务器接口而后自动疯狂拉代码部署,至关于一个验签shell
部署脚本(.sh)就自由发挥,本身平时怎么手动部署的就咋写就完事了,建立文件auto_build.sh
.Linux下建立目录使用mkdir 目录名
,建立文件使用touch 文件名
.npm
PROJECTNAME_PATH = '/usr/local/src/项目目录';
echo "Starting deployment"
cd $PROJECTNAME_PATH
git checkout .
git pull
npm i
gulp release
pm2 start ecosystem.config.js
echo "Finished"
复制代码
执行脚本的时候注意一下用户权限的问题以及基本命令的全局安装.gulp
接下来的重头戏就是构建起一个可以接收远程仓库post请求的服务,这一样也很简单.你能够借助插件github-webhook-handler 的帮助,快速创建起这样一个服务,建立文件deploy.js
.
ps: 这里的secret就是上面webhooks设置中的key
var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: '/webhook', secret: 'myhashsecret' })
http.createServer(function (req, res) {
handler(req, res, function (err) {
res.statusCode = 404
res.end('no such location')
})
}).listen(7777)
handler.on('error', function (err) {
console.error('Error:', err.message)
})
handler.on('push', function (event) {
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref)
})
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)
})
复制代码
ps: 还能够设置当有人给本身仓库提issues时发邮件提醒本身23333333
若是服务没法启动,报错相似Error: Cannot find module 'github-webhook-handler'
,但是依赖包明明已经全局安装过了.确认方法:
npm root -g // 查看npm全局安装路径
=> /root/.nvm/versions/node/v9.10.1/lib/node_modules
cd /root/.nvm/versions/node/v9.10.1/lib/node_modules
ll // 查看目录文件确认依赖是否安装
复制代码
确认安装后能够经过如下步骤解决:
deploy.js
所在目录npm link github-webhook-handler
复制代码
如今,你须要作的是将auto_build.sh
和deploy.js
结合起来.
阅读上面代码,你会发现handler
监听到push
事件调用对应的函数,因此你要作的就是在函数中执行auto_build.sh
命令,你须要在deploy.js
添加以及更改以下代码
// 新增runCmd函数
funciton runCmd(cmd, args, callback) {
var spawn = require('child_process').spawn; // node子进程
var child = spawn(cmd, args);
var response = '';
child.stdout.on('data', buffer => response += buffer.toStirng());
child.stdout.on('end', () => callback(response));
}
// 修改push监听事件 我这里auto_build.sh和deploy.js位于同一目录文件中
handler.on('push', function(event) {
runCmd('sh', ['./auto_build.sh'], function(text) { console.log(text) });
});
复制代码
ps: 能够经过console.log()
在相应的步骤输出相应提示,方便查错
咱们但愿deploy服务可以一直运行在服务器上,当远程仓库发送post请求提示咱们有新代码push的时候可以正常执行部署脚本.这时咱们须要以守护进程的方式来启动deploy.js
服务,当服务意外崩溃时可以重启服务,完全解放咱们的双手.
这里提供两种方法供你们选择,均可以经过npm
安装:
forever
就是保证进程退出时,应用会自动重启。forever start deploy.js // 启动服务进程
forever list // 列出全部进程
forever logs id // 查看进程输出日志
forever stop id // 中止服务进程
forever restart id // 重启服务进程
forever -m 5 deploy.js // 最多重启次数为5
复制代码
pm2
功能强大,除了重启进程之外,还能实时收集日志和监控。pm2 start deploy.js // 启动服务进程
pm2 list // 列出全部进程
pm2 logs id // 查看进程输出日志
pm2 stop id // 中止服务进程
pm2 restart id // 重启服务进程
pm2 delete id // 删除服务进程
复制代码
由于个人服务器在腾讯云上面,7777端口并未放开,因此经过一个Nginx反向代理到服务器安全组开放端口.
在远程仓库发送post测试请求前必定要确认
本身服务器安全组端口已放开!!!
本身服务器安全组端口已放开!!!
本身服务器安全组端口已放开!!!
重要的事情说三遍! 下面是我nginx配置
server {
listen 8080;
server_name localhost;
location /webhook {
proxy_pass http://127.0.0.1:7777;
}
}
复制代码
ps: Linux下重启nginx,进入nginx的sbin目录运行命令./nginx -s reload
Nginx启动 ! deploy服务启动 ! 远程仓库webhook设置完毕 ! 点击测试按钮 !
而后......
报错!!! (强颜欢笑and笑容逐渐消失.jpg
{
"error": "No X-Hub-Signature found on request"
}
复制代码
看了半天......才想起来个人项目代码远程仓库是码云gitee.com,由于github私人private仓库2019年2月以前都是须要付费的,因此涉及私人的项目代码我都选择了码云做为远程仓库,然而个人插件是github-webhook-handler
!!!!能通才有鬼 TAT
不要紧,小问题.都到这一步了,男人怎么能说不行!
先去github上搜下有没有对应gitee的webhook插件,要是没有就forkgithub-webhook-handler
下来本身改下改为适配gitee码云的.果真让我搜到了gitee-webhook-middleware
,而后deploy.js
改一改
var createHandler = require('gitee-webhook-middleware');
var handler = createHandler({ path: '/webhook', token: '你的key' });
复制代码
重启服务,点击测试 !
{
"ok": true
}
复制代码
完美 !
上服务器一看项目代码仍是旧的,妈耶还有坑...后来发现gitee的post请求事件是Push Hook
// handler.on('push', function() {});
handler.on('Push Hook', function() {});
复制代码
至此,从新测试,项目代码更新成功 !
偷懒成功! 偷懒果真是工程师第一辈子产力
如今每当我本地仓库push代码到远程仓库,服务器就会拉取最新版本代码自动部署.
这只是我一次简单尝试,咱们彻底能够扩展自动化测试,自动化部署于一体,完成多人协做开发时的CI/CD,大大减小人力成本,减小人为错误的发生,提升你们的工做效率.