GitHub / GitLab Webhook 接口开发指南
前一阵子要开发一个从 GitLab / GitHub 通过 Webhook 拉取文件并且上传指定 OSS 的接口,于是就找起了 GitHub 和 GitLab 的官方文档。
当然官方文档实在是太过冗长,尤其是公司自建的 GitLab 版本还有可能不一致,所以就只能看搭建的 GitLab 提供的文档信息,对于一些遇到的问题就看命看版本查了。
当然所幸除了接口版本以外并没有遇到什么太大的坑,遇到了问题也可以根据版本来查,可以说这绝对是严格遵照 RESTful API 的一个优点,这一点无论是 GitHub 还是 GitLab 都做得很好。
由于 GitLab 和 GitHub 用的是两套接口,所以这里分开来介绍,不过方法都是相同的:
拉取压缩包,解压缩,上传文件。另一种方法是 git clone
下来,但是感觉 git clone
依旧太麻烦,所以就选了拉取压缩包。
GitLab
下载压缩包的接口:https://docs.gitlab.com/ee/api/repositories.html#get-file-archive
这里有两个参数:
id (required) - The ID or URL-encoded path of the project owned by the authenticated user
sha (optional) - The commit SHA to download defaults to the tip of the default branch
这里需要两个信息,project 的 id 与 sha,都可以通过 Webhook 获得:
const { checkout_sha: checkoutSha, project_id: projectId } = body
但是不同的是 id 是放在 参数(param)中的,而 sha 则是以 querystring 传入的(GitHub 与它不一样),如果不传入 sha,默认为 master 分支最新的代码。
当然,我们还会设置 secret token,这个 secret token 可以通过 header 中的 x-gitlab-token
获得。
然后我们就得到了 GitLab 的相关信息。
如果 API 中获取的内容需要权限,可以使用 PRIVATE-TOKEN
这一 header 传入 token。
GitHub
GitHub 的 Webhook 接口方式与 GitLab 有点不同,我们这里使用的还是 V3 版的 Restful 接口。
针对 GitHub 的 Webhook 最重要的是怎么计算出 secret token 与我们原先设定的相一致。GitHub 就没有 GitLab 那么简单了,我们需要先计算一番,具体可见Validating payloads from GitHub,如果看不懂 Ruby 没关系,下面提供一段 JavaScript:
const strBody = JSON.stringify(body); // 将整个 body 带出去变成 string
const sign = crypto.createHmac("sha1", secretKey) // secretKey 为你需要核对的 token
.update(strBody)
.digest("hex"); // 加密成十六进制
ctx.assert(ctx.header["x-hub-signature"].replace("sha1=", "") === sign, 403, "Wrong Sign");
然后把 header 中的 x-hub-signature
带有 sha1=value
中的 value 和 sign
作对比即可。
其次 GitHub 需要通过 header 中的 x-github-event
来判断 event 的类型,否则会出错,不同的 Event 传入的内容可能不一样,需要对 ping 做一些特殊处理,如果是 ping,直接返回 200,这样就可以过 GitHub 的检查了。
从 request body 中,你还可以找到 repository 信息和相对应的 commit 的信息,也可以获得 Repo Org 的信息(这里我们不需要仓库 Org,所以暂不表述)
const { repository, head, head_commit: headCommit } = body;
我们需要的接口是:
https://github.com/${org}/${repositoryName}/archive/${sha}.zip
其中:
repositoryName = repository.name
sha = headCommit.id
其中如果需要授权,在 header 中写入:
"Authorization": `token ${TOKEN}`
植入部分
如果您觉得文章不错,可以通过赞助支持我。
如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。