介绍
在多人协作开发项目中,如果一个人向代码仓库推送代码,而另一个人又开始修改旧版本,这可能会非常令人沮丧。为了避免此类错误,编写一个脚本来保持代码仓库同步就显得尤为重要。您还可以将此方法应用于生产环境,以便快速进行紧急修复和其他更改。.
虽然还有其他方法可以完成这项特定任务,但编写自己的脚本是一个灵活的选择,可以为未来的自定义留出空间。.
GitHub 允许你为代码仓库配置 Webhook,Webhook 是一种事件触发机制,当特定事件发生时,它会发送 HTTP 请求。例如,你可以使用 Webhook 在有人创建拉取请求或推送新代码时收到通知。.
本指南将指导您创建一个 Node.js 服务器,该服务器会监听 GitHub webhook 通知,以便在您或其他用户向 GitHub 推送代码时自动更新。此脚本会自动将远程服务器上的仓库更新为最新版本的代码,无需登录服务器即可提交新代码。.
先决条件
- 已配置的 Ubuntu 服务器,包括一个具有 sudo 权限的非 root 用户和一个防火墙。.
- Git 已安装在您的本地计算机上。.
- Node.js 和 npm 已使用官方 PPA 安装在远程服务器上。.
- GitHub 上的一个仓库,其中包含您的项目代码。.
步骤 1 – 设置 Webhook
我们首先要为你的仓库配置一个钩子。这一步非常重要,因为如果没有它,GitHub 就不知道在发生某些事情时应该发送哪些事件,也不知道应该把事件发送到哪里。首先,我们会创建 Webhook,然后创建一个服务器来响应它的请求。.
登录您的 GitHub 帐户并导航至要监控的仓库。点击仓库页面顶部菜单栏中的“设置”选项卡,然后点击左侧导航菜单中的“Webhooks”。点击右上角的“添加 Webhook”,并在提示时输入您的帐户密码。您应该会看到类似这样的页面:
- 在“有效载荷 URL”字段中,输入 http://your_server_ip:8080。这是我们稍后将要编写的 Node.js 服务器的地址和端口。.
- 请将内容类型更改为 application/json。我们编写的脚本需要 JSON 数据,无法识别其他数据类型。.
- 在“密钥”栏中,输入此 Webhook 的密钥。您将在 Node.js 服务器上使用此密钥来验证请求,并确保请求是从 GitHub 发送的。.
- 要指定触发此 Webhook 的事件,只需选择推送事件即可。我们只需要推送事件,因为代码会在推送事件发生时更新,并需要与我们的服务器同步。.
- 选中“启用”复选框。.
- 查看字段,然后点击“添加 webhook”进行创建。.
最初 ping 操作会失败,但请放心,您的 webhook 已配置完成。现在让我们将代码库克隆到服务器。.
步骤 2 – 将存储库克隆到服务器
我们的脚本可以更新仓库,但无法初始化仓库,所以我们现在来初始化它。请登录您的服务器:
ssh sammy@your_server_ip请确保您位于用户主目录下。然后使用 Git 克隆您的仓库。请务必将您的 GitHub 用户名替换为 sammy,并将您的 GitHub 项目名称替换为 hello_hapi。.
cd
git clone https://github.com/sammy/hello_hapi.git这将创建一个包含您项目的新目录。您将在下一步中使用此目录。.
项目克隆完成后,即可创建 webhook 脚本。.
步骤 3 – 创建 Webhook 脚本
让我们创建一个自己的服务器来监听来自 GitHub 的 webhook 请求。我们将编写一个 Node.js 脚本,在 8080 端口启动一个 Web 服务器。该服务器监听 webhook 请求,验证我们指定的密钥,并从 GitHub 拉取最新版本的代码。.
返回主菜单:
cd ~创建一个名为 NodeWebhooks 的新目录,用于存放你的 webhook 脚本:
mkdir ~/NodeWebhooks然后进入新目录:
cd ~/NodeWebhooks在 NodeWebhooks 目录中创建一个名为 webhook.js 的新文件。.
nano webhook.js在脚本中添加这两行代码:
/* Your codevar secret = "your_secret_here";
var repo = "/home/sammy/hello_hapi";... */第一行定义了一个变量,用于保存第一步中创建的密钥,该密钥用于验证请求是否来自 GitHub。第二行定义了一个变量,用于保存本地磁盘上要更新的仓库的完整路径。该路径应指向您在第二步中检出的仓库。.
接下来,在脚本中添加导入 http 和 crypto 库的代码。我们将使用这些库来创建 Web 服务器和密钥哈希,以便将其与从 GitHub 获取的密钥进行比较:
let http = require('http');
let crypto = require('crypto');接下来,添加 child_process 库,以便您可以从脚本中运行 shell 命令:
const exec = require('child_process').exec;接下来,添加以下代码以定义一个新的 Web 服务器,该服务器将处理 GitHub webhook 请求,如果请求有效,则推送新版本的代码:
http.createServer(function (req, res) {
req.on('data', function(chunk) {
let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
if (req.headers['x-hub-signature'] == sig) {
exec('cd ' + repo + ' && git pull');
}
});
res.end();
}).listen(8080);`http.createServer()` 函数会在 8080 端口启动一个 Web 服务器,监听来自 GitHub 的请求。出于安全考虑,我们会验证请求中包含的密钥是否与我们在步骤 1 创建 Webhook 时指定的密钥匹配。该密钥以 SHA1 哈希字符串的形式在 `x-hub-signature` 标头中发送,因此我们会对我们的密钥进行哈希处理,并将其与 GitHub 发送给我们的密钥进行比较。.
如果请求有效,我们将运行 shell 命令,使用 git pull 更新我们的本地存储库。.
最终的脚本如下所示:
const secret = "your_secret_here";
const repo = "~/your_repo_path_here/";
const http = require('http');
const crypto = require('crypto');
const exec = require('child_process').exec;
http.createServer(function (req, res) {
req.on('data', function(chunk) {
let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
if (req.headers['x-hub-signature'] == sig) {
exec('cd ' + repo + ' && git pull');
}
});
res.end();
}).listen(8080);如果您已按照初始服务器设置指南进行操作,则需要允许此 Web 服务器通过允许端口 8080 上的流量与外部网络通信:
sudo ufw allow 8080/tcp现在脚本已经编写完毕,让我们确保它能正常运行。.
步骤 4 – Webhook 测试
我们可以使用 Node.js 在命令行运行 webhook 来进行测试。启动脚本并让进程在终端中保持运行:
cd ~/NodeWebhooks
nodejs webhook.js返回 GitHub.com 上的项目页面。点击仓库页面顶部菜单栏中的“设置”选项卡,然后点击左侧导航菜单中的“Webhooks”。点击您在步骤 1 中设置的 Webhook 旁边的“编辑”。向下滚动即可看到“最近提交”部分,如下图所示:
点击右侧的三个点,即可调出“重新发送”按钮。在节点服务器运行期间,点击“重新发送”按钮重新发送请求。确认发送请求后,您将看到成功响应。重新发送 ping 请求后,会收到 200 OK 响应代码,表示请求已成功发送。.
现在我们可以确保脚本在后台运行,并在启动时自动运行。使用 CTRL+C 可以停止 Node.js Webhook 服务器。.
步骤 5 – 将 Webhook 安装为 Systemd 服务
systemd 是 Ubuntu 的任务管理器,用于管理服务。我们将启动一个服务,以便在启动时自动运行 webhook 脚本,并使用 systemd 命令像管理其他服务一样管理它。.
首先创建一个新的服务文件:
sudo nano /etc/systemd/system/webhook.service
将以下配置添加到服务文件中,以告知 systemd 如何运行脚本。此配置会告诉 systemd 在哪里可以找到我们的节点脚本,并描述我们的服务。.
请务必将 Sami 替换为您的用户名。.
[Unit]
Description=Github webhook
After=network.target
[Service]
Environment=NODE_PORT=8080
Type=simple
User=sammy
ExecStart=/usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js
Restart=on-failure
[Install]
WantedBy=multi-user.target启用新服务,使其在系统启动时启动:
sudo systemctl enable webhook.service现在启动服务:
sudo systemctl start webhook请确保服务已启动:
sudo systemctl status webhook您将看到以下输出,表明该服务已激活:
Output
● webhook.service - Github webhook
Loaded: loaded (/etc/systemd/system/webhook.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2018-08-17 19:28:41 UTC; 6s ago
Main PID: 9912 (nodejs)
Tasks: 6
Memory: 7.6M
CPU: 95ms
CGroup: /system.slice/webhook.service
└─9912 /usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js现在您可以将新的提交推送到您的存储库,并在服务器上查看更改。.
在您的桌面设备上,模拟该存储库:
git clone https://github.com/sammy/hello_hapi.git修改代码仓库中的一个文件。然后提交修改后的文件,并将代码推送到 GitHub。.
git add index.js
git commit -m "Update index file"
git push origin masterwebhook 将被激活,您的更改将显示在您的服务器上。.
结果
您已设置了一个 Node.js 脚本,用于自动将新提交部署到远程仓库。您可以使用此流程设置要监控的其他仓库。您甚至可以将其配置为在推送仓库时将网站或应用程序部署到生产环境。.











