如何使用Node.js和GithubWebhooks保持远程项目同步
介绍
在与多个开发人员一起开发项目时,如果一个人推送到存储库,然后另一个人开始对过时的代码版本进行更改,这可能会令人沮丧。 诸如此类的错误会耗费时间,因此值得设置一个脚本来保持您的存储库同步。 您还可以在生产环境中应用此方法以快速推送修补程序和其他更改。
虽然存在其他解决方案来完成此特定任务,但编写自己的脚本是一种灵活的选择,为将来的定制留出了空间。
GitHub 允许您为存储库配置 webhooks,这些事件是在事件发生时发送 HTTP 请求的事件。 例如,您可以使用 webhook 在有人创建拉取请求或推送新代码时通知您。
在本指南中,您将开发一个 Node.js 服务器,该服务器在您或其他人将代码推送到 GitHub 时侦听 GitHub webhook 通知。 该脚本将使用最新版本的代码自动更新远程服务器上的存储库,从而无需登录服务器来拉取新提交。
先决条件
要完成本教程,您需要:
- 按照 Ubuntu 16.04 初始服务器设置指南 设置一台 Ubuntu 16.04 服务器,包括具有
sudo
权限的非 root 用户和防火墙。 - Git 安装在本地机器上。 您可以按照教程 贡献开源:Git 入门 在您的计算机上安装和设置 Git。
- 使用官方 PPA 在远程服务器上安装 Node.js 和
npm
,如 如何在 Ubuntu 16.04 上安装 Node.js 中所述。 安装发行版稳定版就足够了,因为它为我们提供了推荐的版本,无需任何额外配置。 - Github 上包含您的项目代码的存储库。 如果您没有计划,请随意 fork 这个示例 ,我们将在本教程的其余部分使用它。
第 1 步 — 设置 Webhook
我们将从为您的存储库配置 webhook 开始。 这一步很重要,因为没有它,Github 不知道当事情发生时要发送什么事件,或者将它们发送到哪里。 我们将首先创建 webhook,然后创建响应其请求的服务器。
登录到您的 GitHub 帐户并导航到您要监控的存储库。 单击存储库页面顶部菜单栏中的 Settings 选项卡,然后单击左侧导航菜单中的 Webhooks。 点击右上角的添加Webhook,如果出现提示输入你的账号密码。 您将看到如下所示的页面:
- 在 Payload URL 字段中,输入
http://your_server_ip:8080
。 这是我们稍后会写的 Node.js 服务器的地址和端口。 - 将 内容类型 更改为
application/json
。 我们将编写的脚本将需要 JSON 数据,并且无法理解其他数据类型。 - 对于 Secret,输入此 webhook 的密码。 您将在 Node.js 服务器中使用此密钥来验证请求并确保它们来自 GitHub。
- 对于你希望哪些事件触发这个webhook,选择just the push event。 我们只需要推送事件,因为那是代码更新并需要同步到我们的服务器的时候。
- 选中 Active 复选框。
- 查看字段并单击 添加 webhook 以创建它。
一开始 ping 会失败,但请放心,您的 webhook 现在已经配置好了。 现在让我们将存储库克隆到服务器。
第 2 步 — 将存储库克隆到服务器
我们的脚本可以更新存储库,但它无法处理最初的存储库设置,所以我们现在就这样做。 登录到您的服务器:
ssh sammy@your_server_ip
确保您位于主目录中。 然后使用 Git 克隆您的存储库。 请务必将 sammy
替换为您的 GitHub 用户名,并将 hello_hapi
替换为您的 Github 项目的名称。
cd git clone https://github.com/sammy/hello_hapi.git
这将创建一个包含您的项目的新目录。 您将在下一步中使用此目录。
克隆项目后,您可以创建 webhook 脚本。
第 3 步 — 创建 Webhook 脚本
让我们创建我们的服务器来监听来自 GitHub 的那些 webhook 请求。 我们将编写一个 Node.js 脚本,在端口 8080
上启动一个 Web 服务器。 服务器将监听来自 webhook 的请求,验证我们指定的秘密,并从 GitHub 拉取最新版本的代码。
导航到您的主目录:
cd ~
为您的 webhook 脚本创建一个名为 NodeWebhooks
的新目录:
mkdir ~/NodeWebhooks
然后导航到新目录:
cd ~/NodeWebhooks
在 NodeWebhooks
目录中创建一个名为 webhook.js
的新文件。
nano webhook.js
将这两行添加到脚本中:
webhook.js
var secret = "your_secret_here"; var repo = "/home/sammy/hello_hapi";
第一行定义了一个变量来保存您在步骤 1 中创建的密钥,该密钥验证请求来自 GitHub。 第二行定义了一个变量,该变量保存了您要在本地磁盘上更新的存储库的完整路径。 这应该指向您在步骤 2 中签出的存储库。
接下来,添加这些将 http
和 crypto
库导入脚本的行。 我们将使用这些来创建我们的 Web 服务器并对秘密进行哈希处理,以便我们可以将其与从 GitHub 收到的内容进行比较:
webhook.js
let http = require('http'); let crypto = require('crypto');
接下来,包含 child_process
库,以便您可以从脚本执行 shell 命令:
webhook.js
const exec = require('child_process').exec;
接下来,添加此代码以定义一个新的 Web 服务器来处理 GitHub Webhook 请求并在它是真实请求时拉下新版本的代码:
webhook.js
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
更新我们的本地存储库。
完成的脚本如下所示:
webhook.js
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);
如果您遵循初始服务器设置指南,则需要通过允许端口 8080
上的流量来允许此 Web 服务器与外部 Web 通信:
sudo ufw allow 8080/tcp
现在我们的脚本已经到位,让我们确保它正常工作。
第 4 步 - 测试 Webhook
我们可以使用 node
在命令行中运行它来测试我们的 webhook。 启动脚本并在终端中保持进程打开:
cd ~/NodeWebhooks nodejs webhook.js
返回到 Github.com 上的项目页面。 单击存储库页面顶部菜单栏中的 Settings 选项卡,然后单击左侧导航菜单中的 Webhooks。 单击您在步骤 1 中设置的 webhook 旁边的 Edit。 向下滚动,直到看到 Recent Deliveries 部分,如下图所示:
按下最右侧的三个点以显示 Redeliver 按钮。 在节点服务器运行的情况下,单击 Redeliver 再次发送请求。 确认要发送请求后,您将看到成功的响应。 这由重新发送 ping 后的 200 OK
响应代码指示。
我们现在可以继续确保我们的脚本在后台运行并在启动时启动。 使用 CTRL+C
停止节点 webhook 服务器。
第 5 步 — 将 Webhook 安装为 Systemd 服务
systemd 是 Ubuntu 用来控制服务的任务管理器。 我们将设置一个服务,允许我们在启动时启动我们的 webhook 脚本,并使用 systemd 命令来管理它,就像我们使用任何其他服务一样。
首先创建一个新的服务文件:
sudo nano /etc/systemd/system/webhook.service
将以下配置添加到告诉 systemd 如何运行脚本的服务文件中。 这告诉 Systemd 在哪里可以找到我们的节点脚本并描述我们的服务。
确保将 sammy
替换为您的用户名。
/etc/systemd/system/webhook.service
[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 master
webhook 将触发,您的更改将显示在您的服务器上。
结论
您已经设置了一个 Node.js 脚本,它将自动将新提交部署到远程存储库。 您可以使用此过程来设置您想要监控的其他存储库。 您甚至可以将其配置为在推送存储库时将网站或应用程序部署到生产环境。