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服务文件

实操

  1. 本地添加远程github库 helloworld
  2. 远程服务器/home/user/www/ 添加远程github库 helloworld
  3. 编写每个部分脚本
  4. pm2 启动webhook.js
  5. 本地npm run dp 完成初次上传
  6. 打开浏览器,此时页面能正常显示为初次内容
  7. 改变组件的内容,重新npm run dp
  8. 打开浏览器,此时页面能正常显示为第二次内容,部署成功

如果不成功,我们就需要查看下日志了,打开qq邮箱

注意事项

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
见实操,还有其他问题请评论区指出

你可能感兴趣的:(前端工程化)