乐趣区

关于前端工程化: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(`
            <h1> 部署日期: ${new Date()}</h1>
            <h2> 部署人: ${payload.pusher.name}</h2>
            <h2> 部署邮箱: ${payload.pusher.email}</h2>
            <h2> 提交信息: ${payload.head_commit.message}</h2>
            <h2> 布署日志:<br/> ${logs.replace(/n/,'<br/>')}</h2>
        
        `);
                });
            }
        });
    }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: '250351xxxx@qq.com',
        // 这里明码不是 qq 明码,是你设置的 smtp 受权码
        pass: '你的受权码',
    }
});

function sendMail(message){
    let mailOptions = {
        from: '"250351xxxx" <250351xxxx@qq.com>', // 发送地址
        to: '250351xxxx@qq.com', // 接收者
        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 邮箱

如果 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 username@hostname.com:~/.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
见实操,还有其余问题请评论区指出

退出移动版