腾讯云11.11爆款1核2G云服务器首购88元,免费领9888元代金券,百款云产品一折起
接着上篇文章git钩子与自动化部署(上)继续说
webhook
定义
Webhooks allow you to build or set up integrations, such as GitHub Apps , which subscribe to certain events on GitHub.com.
When one of those events is triggered, we'll send a HTTP POST payload to the webhook's configured URL.
Webhooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server. You're only limited by your imagination.
注意关键语句,当我们触发一个事件(比如git push)的时候,github会给我配置的url发一个post请求,并携带一些参数
自动部署过程
这次我们玩的正规一点
目标:本地一行命令npm run dp
实现项目自动打包上传部署
过程:
1.本地命令触发本地shell脚本,自动打包和git add commit push
2.git push会使github发一个post请求给目标服务
3.当服务被触发的时候,执行相关脚本
4.脚本肯定使目标展示目录从github拉文件
5.拉完就完成自动部署了
webhook配置
设置github
进入github 创建一个新项目helloworld,在该项目的setting里面的webhooks里面addwebhooks
我们还可以配置密码,触发事件等等行为
这里我们的content-type 选择 application/json
palyload
我们看下palyload形式
POST /payload HTTP/1.1
Host: localhost:4567
X-GitHub-Delivery: 72d3162e-cc78-11e3-81ab-4c9367dc0958
X-Hub-Signature: sha1=7d38cdd689735b008b3c702edd92eea23791c5f6
User-Agent: GitHub-Hookshot/044aadd
Content-Type: application/json
Content-Length: 6615
X-GitHub-Event: issues
{
"action": "opened",
"issue": {
"url": "https://api.github.com/repos/octocat/Hello-World/issues/1347",
"number": 1347,
...
},
"repository" : {
"id": 1296269,
"full_name": "octocat/Hello-World",
"owner": {
"login": "octocat",
"id": 1,
...
},
...
},
"sender": {
"login": "octocat",
"id": 1,
...
}
}
这个post请求会有独特的请求头,会有和仓库相关的参数repository,会有和提交人相关的参数sender,后面发邮件的时候会用的到
本地脚本配置
流程
- vue-cli初始化项目
- 添加远程库为github中hello-world源
- npm sript里面配置
"dp": "npm run build && sh dp.sh"
-编写dp.sh脚本
#!/bin/sh
echo '添加'
git add .
echo 'commit'
git commit -m 'dp'
echo '推送中..'
git push origin master
这一套下来,我们就可以实现 npm run dp完成自动打包和上传啦
npm scipt
说到npm script,插一嘴,其实这个就是shell脚本
npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。
比较特别的是,npm run新建的这个 Shell,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。
这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写mocha test就可以了。
"test": "mocha test"
而不用写成下面这样。
"test": "./node_modules/.bin/mocha test"
由于 npm 脚本的唯一要求就是可以在 Shell 执行,因此它不一定是 Node 脚本,任何可执行文件都可以写在里面。
npm 脚本的退出码,也遵守 Shell 脚本规则。如果退出码不是0,npm 就认为这个脚本执行失败。
服务器脚本配置
webhook.js
首先服务器装node,pm2。用pm2管理webhook.js服务
编写webhook.js服务,用于对github的那个post请求作出相应
webhook.js
let http = require('http');
var spawn = require('child_process').spawn;
let sendMail = require('./sendMail.js');
let server = http.createServer(function(req,res){
console.log(req.method,req.url);
if(req.url == '/webhook' && req.method =='POST'){
let buffers = [];
req.on('data',function(data){
buffers.push(data);
});
req.on('end',function(){
//获取webhook请求的payload,也是
let payload = JSON.parse(Buffer.concat(buffers));
console.log(payload.pusher,payload.head_commit)
let event = req.headers['x-github-event'];
console.log(payload.repository)
res.setHeader('Content-Type','application/json');
res.end(JSON.stringify({"ok":true}));//这个是github约定的,如果是这个,delivery记录就是绿色成功态,否者就是红色,各种错误信息
if(event === 'push'){
//执行相应的shell
let child = spawn('sh', [`${payload.repository.name}`]);
let buffers = [];
child.stdout.on('data', function (buffer) { buffers.push(buffer)});
child.stdout.on('end', function () {
//获取子进程日志信息
let logs = Buffer.concat(buffers).toString();
//发邮件
sendMail(`
部署日期: ${new Date()}
部署人: ${payload.pusher.name}
部署邮箱: ${payload.pusher.email}
提交信息: ${payload.head_commit.message}
布署日志:
${logs.replace(/\\n/,'
')}
`);
});
}
});
}else{
res.end('Now Found!!!!');
}
});
server.listen(4000,()=>{
console.log('服务正在4000端口上启动!');
});
sendmail.js
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
// host: 'smtp.ethereal.email',
service: 'qq', // 使用了内置传输发送邮件 查看支持列表:https://nodemailer.com/smtp/well-known/
port: 465, // SMTP 端口
secureConnection: true, // 使用了 SSL
auth: {
user: '[email protected]',
// 这里密码不是qq密码,是你设置的smtp授权码
pass: '你的授权码',
}
});
function sendMail(message){
let mailOptions = {
from: '"250351xxxx" <[email protected]>', // 发送地址
to: '[email protected]', // 接收者
subject: '部署通知', // 主题
html:message // 内容主体
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
});
}
module.exports = sendMail;
helloworld.sh
编写helloworld.sh脚本,注意这个名字不是乱取的,是你github仓库的名字,因为在webhook.js里面我是这么执行的脚本
let child = spawn('sh', [`${payload.repository.name}`]); //这里虽然我touch helloworld.sh 但是好像ls的时候没有扩展名,所以这里执行的时候也就没有写
helloworld.sh里面这么写
#!/bin/sh
echo '开始执行webhook钩子'
unset GIT_DIR
DIR_ONE=/home/user/www/ #此目录为服务器页面展示目录
cd $DIR_ONE
echo '清除git缓存'
git clean -df
echo '拉取远程代码'
git pull origin master
echo '部署完成'
此时/home/user下会有 www文件夹,hellowrold可执行文件,webhook.js服务文件
实操
- 本地添加远程github库 helloworld
- 远程服务器/home/user/www/ 添加远程github库 helloworld
- 编写每个部分脚本
- pm2 启动webhook.js
- 本地npm run dp 完成初次上传
- 打开浏览器,此时页面能正常显示为初次内容
- 改变组件的内容,重新npm run dp
- 打开浏览器,此时页面能正常显示为第二次内容,部署成功
如果不成功,我们就需要查看下日志了,打开qq邮箱
如果qq邮箱里没有邮件
在服务器 pm2 log 查看下日志看哪出问题了,有post请求信息吗? 是不是webhook.js没启动?是不是没有git push上去(网不好的时候会遇到,再push一次即可),是不是post请求发出去了但是服务没接受到,查看github的webhook的delivery记录
注意事项
1.服务器权限的问题,我建议还是个人拥有个人的服务器比较好,root权限,想怎么整就怎么整。如果用公司的服务器,ningx访问的时候跨目录可能出问题,ssh配置也可能出问题
。
这里强烈推荐一下腾讯云,最近做活动,88玩一年,安全耐操
0.1折服务器链接。买了不会玩的可以私聊我,三陪政策,包教包会.....
2.ssh怎么配
首先登录远程服务器,命令行输入 ssh-keygen,生成ssh公钥私钥
其次本地首先看有没有~/.ssh目录,没有的化也执行上面的操作
然后 scp ~/.ssh/id_rsa.pub [email protected]:~/.ssh/authorized_keys (把本地共钥复制到远程服务器authorized_keys这个文件中)
再在本地的~/.ssh中添加一个config文件,里面这么写
Host qq
HostName 你的腾讯云服务器ip
Port 22 (ssh默认端口,==括号里面的不要填上去==)
User root
IdentityFile ~/.ssh/id_rsa
大功告成,当在控制台输入ssh qq 就自动连上腾讯云服务器了
3.本地项目和github的ssh连接
~/.ssh/id_rsa.pub放到github公钥里面
4.实操各种bug
见实操,还有其他问题请评论区指出
总结
介绍了webhook钩子以及利用它进行简单自动化部署的实例。并对其中各种可能遇到的问题做了说明。希望能给大家带来一些帮助。
最近老大让我研究把这一套包括部署和eslint同jeckins结合,形成固定流程。压力山大,等研究出来了,再过来叨叨下吧
题外话,写文章真的很辛苦,写了这么久了,竟然一个打赏也没收到,已哭晕。有没有哪位大哥能给个打赏,让我开开荤,支持支持我呗......