如何使用 Node.js 和 Github Webhooks 保持远程项目同步

介绍

在与多个开发人员一起工作时,当一个人推到一个存储库,然后另一个人开始对代码的过时版本进行更改时,可能会令人沮丧。

虽然有其他解决方案来完成这个特定的任务,但写自己的脚本是一个灵活的选项,在未来留下了自定义空间。

GitHub允许您为您的存储库配置 webhooks,这些事件在事件发生时发送 HTTP 请求。

在本指南中,您将开发一个 Node.js服务器,每当您或其他人将代码推到 GitHub 时,都会听取 GitHub Webhook 通知。

前提条件

要完成本教程,您将需要:

步骤 1 - 设置一个 Webhook

这个步骤很重要,因为没有它,Github不知道在事情发生时要发送什么事件,或者在哪里发送它们。

登录您的 GitHub 帐户并导航到您想要监控的存储库。在存储库页面上顶部菜单栏中单击设置选项卡,然后在左侧导航菜单中单击Webhooks选项卡。在右侧单击添加 Webhook选项卡,并在提示时输入您的帐户密码。

Webhooks Page

  • Payload URL字段中,输入 http://your_server_ip:8080. 这是我们即将写的 Node.js 服务器的地址和端口。
  • Content type 更改为 application/json. 我们要写的脚本将期待 JSON 数据,并且无法理解其他数据类型。
  • 对于 Secret,为此 webhook 输入秘密密密密码。 您将在您的 Node.js 服务器中使用此秘密来验证请求并确保它们来自 GitHub。
  • 对于您想要触发此 webhook 的事件,只需选择 ** push 事件**. 我们只需要推动事件,因为它是当代码更新并需要

ping 最初会失败,但请放心您的 webhook 现在已经配置了,现在让我们把存储库克隆到服务器上。

步骤 2 – 将存储库克隆到服务器

我们的脚本可以更新一个存储库,但它不能处理最初的存储库设置,所以我们现在会这样做。

1[environment local]
2ssh sammy@your_server_ip

确保你在您的主目录中,然后使用Git来克隆您的存储库,请确保用您的GitHub用户名替换sammy,用您的Github项目名称替换hello_hapi

1cd
2git clone https://github.com/sammy/hello_hapi.git

这将创建一个包含您的项目的新目录,您将在下一步使用该目录。

随着项目的克隆,您可以创建 webhook 脚本。

步骤 3 – 创建 Webhook 脚本

让我们创建我们的服务器来聆听那些来自GitHub的webhook请求,我们将写一个Node.js脚本,在端口8080上启动一个Web服务器,服务器将聆听来自webhook的请求,验证我们指定的秘密,并从GitHub中提取最新版本的代码。

导航到您的家庭目录:

1cd ~

创建一个名为NodeWebhooks的webhook脚本的新目录:

1mkdir ~/NodeWebhooks

然后导航到新目录:

1cd ~/NodeWebhooks

NodeWebhooks目录中创建一个名为webhook.js的新文件。

1nano webhook.js

将这两个行添加到脚本中:

1[label webhook.js]
2var secret = "your_secret_here";
3var repo = "/home/sammy/hello_hapi";

第一行定义了一个变量,以保持您在步骤 1 中创建的秘密,该变量验证了请求来自GitHub。第二行定义了一个变量,该变量持有您想在本地磁盘上更新的完整路径。

接下来,添加这些行,将httpcrypto库导入脚本中,我们将使用这些来创建我们的Web服务器,并哈希秘密,以便我们可以将其与我们从GitHub获得的内容进行比较:

1[label webhook.js]
2let http = require('http');
3let crypto = require('crypto');

接下来,包括child_process库,以便您可以从脚本中执行壳命令:

1[label webhook.js]
2const exec = require('child_process').exec;

接下来,添加此代码来定义一个新的 Web 服务器,该服务器处理 GitHub Webhook 请求,并将新版本的代码拉下,如果是真实的请求:

 1[label webhook.js]
 2http.createServer(function (req, res) {
 3    req.on('data', function(chunk) {
 4        let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
 5
 6        if (req.headers['x-hub-signature'] == sig) {
 7            exec('cd ' + repo + ' && git pull');
 8        }
 9    });
10
11    res.end();
12}).listen(8080);

http.createServer()函数在端口8080上启动一个Web服务器,它会听取来自Github的入口请求,为了安全目的,我们验证请求中包含的秘密与我们在步骤 1中创建Webhook时所指定的秘密相匹配,秘密被传递到x-hub-签名标题中作为一个SHA1加密字符串,所以我们将我们的秘密加密,并将其与GitHub发送给我们的内容进行比较。

如果请求是真实的,我们执行一个壳命令以使用git pull更新我们的本地存储库。

完成的剧本看起来像这样:

 1[label webhook.js]
 2const secret = "your_secret_here";
 3const repo = "~/your_repo_path_here/";
 4
 5const http = require('http');
 6const crypto = require('crypto');
 7const exec = require('child_process').exec;
 8
 9http.createServer(function (req, res) {
10    req.on('data', function(chunk) {
11        let sig = "sha1=" + crypto.createHmac('sha1', secret).update(chunk.toString()).digest('hex');
12
13        if (req.headers['x-hub-signature'] == sig) {
14            exec('cd ' + repo + ' && git pull');
15        }
16    });
17
18    res.end();
19}).listen(8080);

如果您遵循初始服务器设置指南,则需要允许该 Web 服务器通过允许对端口 8080 的流量与外部 Web 进行通信:

1sudo ufw allow 8080/tcp

现在我们的脚本已经到位,让我们确保它正常工作。

步骤 4 - 测试 Webhook

我们可以通过使用节点来测试我们的webhook,在命令行中运行它。

1cd ~/NodeWebhooks
2nodejs webhook.js

返回您的项目页面在 Github.com。 点击您的库存页面上顶部菜单栏中的设置卡,然后点击Webhooks在左导航菜单中。

Edit Webhook

按一下右边的三个点,以显示 Redeliver按钮. 当节点服务器运行时,点击 Redeliver 以再次发送请求。一旦您确认要发送请求,您将看到成功的响应。

我们现在可以继续确保我们的脚本在背景中运行,并在启动时开始使用CTRL+C来阻止节点webhook服务器。

步骤 5 — 安装 Webhook 作为 Systemd 服务

systemd是Ubuntu使用的任务管理器来控制服务,我们将设置一个服务,允许我们在启动时启动我们的webhook脚本,并使用systemd命令来管理它,就像我们在任何其他服务中一样。

创建一个新的服务文件:

1sudo nano /etc/systemd/system/webhook.service

将下列配置添加到服务文件中,该文件告诉 systemd 如何运行脚本. 这告诉 Systemd 在哪里找到我们的节点脚本并描述我们的服务。

请确保用您的用户名替换sammy

 1[label /etc/systemd/system/webhook.service]
 2[Unit]
 3Description=Github webhook
 4After=network.target
 5
 6[Service]
 7Environment=NODE_PORT=8080
 8Type=simple
 9User=sammy
10ExecStart=/usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js
11Restart=on-failure
12
13[Install]
14WantedBy=multi-user.target

启用新服务,以便在系统启动时启动:

1sudo systemctl enable webhook.service

现在开始服务:

1sudo systemctl start webhook

确保服务开始:

1sudo systemctl status webhook

您将看到以下输出,表示该服务正在运行:

 1[secondary_label Output]
 2 webhook.service - Github webhook
 3   Loaded: loaded (/etc/systemd/system/webhook.service; enabled; vendor preset: enabled)
 4   Active: active (running) since Fri 2018-08-17 19:28:41 UTC; 6s ago
 5 Main PID: 9912 (nodejs)
 6    Tasks: 6
 7   Memory: 7.6M
 8      CPU: 95ms
 9   CGroup: /system.slice/webhook.service
10           └─9912 /usr/bin/nodejs /home/sammy/NodeWebhooks/webhook.js

您现在可以将新承诺推向您的存储库,并在您的服务器上查看更改。

从您的桌面计算机,克隆存储库:

1[environment local]
2git clone https://github.com/sammy/hello_hapi.git

对存储库中的任何一个文件进行更改,然后发起文件并将您的代码推到GitHub。

1[environment local]
2git add index.js
3git commit -m "Update index file"
4git push origin master

Webhook将启动,您的更改将出现在您的服务器上。

结论

您已经设置了一个 Node.js 脚本,该脚本将自动部署新的承诺到远程存储库. 您可以使用此过程来设置您想要监控的额外存储库。

Published At
Categories with 技术
comments powered by Disqus