什么是WebHook?

WebHook,可以简单理解为一个由特定条件触发的http请求。

例子:在Github中的每个仓库都可以配置webhook,当push触发webhook后,github会根据配置向特定的服务器发送一个http/https请求,并携带相应的信息,服务器收到请求后,可以根据信息做一系列不同的操作。

自动部署实现思路:

github远程仓库有webhook功能,在代码push时,可以配置让其向指定服务器发送一个post请求;当我们的云服务器接受到这个请求时,执行git pull命令拉取最新代码,并执行一系列bash命令即可完成自动部署。

架构图:

image-20240121153808327

问题:

在实践过程中,我发现在服务器上无法直接拉取github代码,原因可能与github被墙有关,因此需要转变思路,使用国内的代码托管平台同步github上的代码,并发送webhook请求,然后服务器再拉取国内代码托管平台上的代码,最后再执行自动部署脚本完成部署

解决思路:

  1. 放弃使用github,改用gitee仓库来存储代码
  2. 使用github同步

调整后的架构:

image-20240121154708594

具体实现步骤:

一、配置gitee仓库的webhook

进入到项目>管理>Webhooks,配置接口的URL,密码,事件并点击确定。

不同与github仓库,gitee仓库默认不验证ssl证书,所以不用额外配置

image-20240120225453957

二、服务器端环境搭建

1.安装node环境

node官网下载linux的node安装包,上传到服务器

image-20240120153732109

解压安装包到 /usr/local/soft 目录下

1
sudo tar -xvf node-v18.16.1-linux-x64.tar.xz -C /usr/local/soft

进入目录为node创建关联(类似于window下配置环境变量)

1
2
3
ln -s /usr/local/soft/node18.16/bin/node /usr/bin/node
ln -s /usr/local/soft/node18.16/bin/npm /usr/bin/npm
ln -s /usr/local/soft/node18.16/bin/npx /usr/bin/npx
2.安装git
1
2
sudo apt update
sudo apt install git

查看版本验证是否安装成功

1
git --version

三、搭建webhook-handler服务(可在windows完成后上传到服务器);

3.1初始化项目

创建一个web-handler文件夹作为项目文件夹,并初始化项目

1
npm init -y 

2)安装依赖

1
npm i express && npm i child_process
3.2使用express搭建node服务

在项目根目录创建一个main.js,写入如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const express = require('express')
const bodyParser = require('body-parser')
const https = require('https')
const fs = require('fs')
const { exec } = require('child_process')

const app = express()
const PORT = 7777
const passwd = `你的webhook密码`

// 使用 body-parser 中间件来解析 JSON 请求体
app.use(bodyParser.json())

// 处理 POST 请求
app.post('/', (req, res) => {
const { head_commit,password } = req.body
if(password!==passwd){
return;
}
console.log('密码验证通过!')
const {
message,
committer: { name },
} = head_commit
if (name&&message) {
console.log(`提交者:${name}; 提交信息:${message}`)
//执行bash脚本
exec('./deploy.sh', (error, stdout, stderr) => {
if (error) {
console.error(`执行出错: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
}

res.status(200).send('OK')
})

// 配置 HTTPS 选项
const httpsOptions = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
}

// 启动 Express 服务器,监听 HTTPS 端口
const server = https.createServer(httpsOptions, app)

server.listen(PORT, () => {
console.log(`Server is running at https://localhost:${PORT}`)
})

同样在根目录新建一个deploy.sh脚本文件,将下面的代码复制进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

WEB_PATH='/var/www/Bro-B.github.io'
WEB_USER='root'
WEB_USERGROUP='root'
DEPLOY_PATH='/var/www/html'

# 设置遇到错误立即退出
set -e

# 捕获错误并输出错误信息
trap 'echo "Error: $0:$LINENO failed" >&2; exit 1;' ERR

echo "博客站自动构建开始..."
cd $WEB_PATH
echo "开始拉取代码..."
git pull
git checkout main
echo "设置权限..."
chown -R $WEB_USER:$WEB_USERGROUP $WEB_PATH

echo "安装依赖中..."
npm i

echo "构建中..."
npm run clean && npm run build

echo "打包文件替换..."
rm -rf $DEPLOY_PATH
mv $WEB_PATH/public $DEPLOY_PATH

echo "Script executed successfully"
3.3生成自签名ssl证书

将上一步中的项目文件夹上传到服务器中(我上传到了/home/lighthouse)

❗️ 仅用于测试,后期服务器绑定域名后可用域名免费生成用于生产环境的ssl证书

安装openssl

1
sudo apt-get install openssl

生成ssl证书和私钥

1
openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr

生成自签名证书

1
openssl x509 -req -in server.csr -signkey server.key -out server.crt

设置私钥权限

1
hmod 600 server.key
4.启动服务

在服务器中,进入到项目文件夹下,执行js脚本启动服务

1
cd /home/light-house/webhook-handler
1
node main.js

启动成功提示:

image-20240120231756955

四、拉取项目代码,测试Webhook

❗️ 进行到这里出现了个小问题,由于国内无法直连github从github仓库克隆,这里需要先将github仓库中的代码同步到gitee,再从gitee拉取最新代码

1.添加GithubAction脚本,向Gitee仓库同步代码

比较简单,可以参考这篇教程:https://cloud.tencent.com/developer/article/1917861

2.拉取项目到服务器

先在服务器上生成ssh

1
ssh-keygen -t rsa -b 4096

生成后进入到 /root/.ssh下,复制公钥添加到gitee中(Gite公钥添加方法自行百度)

1
2
cd /root/.ssh
cat id_rsa.pub

然后将项目克隆到本地

1
2
cd 一个你要存放项目的目录(我的:/var/www)
git clone Gitee项目地址
3.测试webhook的执行情况

在本地仓库随便提交一次并push,将触发githubAction脚本,将代码同步到gitee,gitee同步代码后触发webhook,向服务器发送POST请求,服务器收到请求后,将验证密码,并执行我们写好的deploy.sh脚本自动构建并替换静态文件。

image-20240120230034454

⚠️测试技巧:Gitee发送Webhook后,会有请求历史,点击重新发送可以提高测试效率

image-20240120232304111