Skip to content

使用 Github WebHooks 来实现自动部署

Published: at 04:17 AM

在软件工程中,CI/CD 指的是持续交付和持续部署,常用的 CI/CD 工具有 Jenkins,CircleCI 等等,更轻量的还有 Drone。

我目前在使用 Github Actions 完成 CI 的功能,但我仍需要一种能够实现 CD 的方式。在搭建 Jenkins 进行简单尝试后发现 Jenkins 有些重,我的个人项目其实用不到这么大的工具,而且 Jenkins 的内存占用也是有些大了。于是我转而尝试 Drone,确实够轻量 —— 在云服务器上没有跑任务时内存占用也才 100M 不到。经过一番尝试后发现 Drone 其实一部分替代了 Github Actions 的功能。原来我真正想要的只是 Github Actions + WebHook 就够了,那么这样一来这个 Drone 我也不需要了,我只要写一个 WebHook 就行了。

什么是 WebHook ?

假如往仓库推送了新的代码,服务器该如何知道有版本更新,并且同步最新代码呢?轮询是一个办法但又不是那么的好。最好就是有一种方式当版本更新时会主动通知到服务器,然后服务器再去同步代码并更新部署。从 Github 发送一个 http 请求到一个 Web 服务,接收到请求后就可以开始做一些事情。

虽然在 Github Actions 里发送一个 http 请求就可以完成这件事,但还是用 Github 里独立的更安全完善的 WebHook 功能吧。

当触发特定的事件时,Github 会向你的接口发送一个 Post 请求,并且提供丰富的触发事件可以选择。在添加 WebHook 时需要提供一个密钥,后面 Github 在发送 Post 的时候就会在头部加上由 密钥 + 请求 body 算出的 hmacsha1 和 hmacsha256 值。

在 Node.js 上代码大致如下:

// node 内置的模块
const crypto = require("crypto");

// secret 就是自己的密钥
const hmacsha256 = body =>
  crypto.createHmac("sha256", secret).update(body).digest("hex");

在做完哈希值等验证后可以根据不同的仓库,去做不同的事情,比如可以执行 shell 脚本来拉取仓库再重启服务

const { spawn } = require("child_process");

const main = () => {
  console.log("运行脚本");
  const deploySh = spawn("bash", ["./src/scripts/test.sh"]);
  deploySh.stdout.on("data", data => {
    console.log(Buffer.from(data).toString("utf-8"));
  });
};

module.exports = { main };