-
A1. 附录 A: Git 在其他环境
- A1.1 图形界面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 小结
-
A2. 附录 B: 在应用程序中嵌入 Git
-
A3. 附录 C: Git 命令
6.5 GitHub - 脚本化 GitHub
脚本化 GitHub
至此,我们已经涵盖了 GitHub 的所有主要功能和工作流程,但是任何大型团队或项目都可能需要进行定制或集成外部服务。
幸运的是,GitHub 在许多方面都非常容易“黑进”。在本节中,我们将介绍如何使用 GitHub 的钩子系统及其 API 来使 GitHub 按照我们希望的方式工作。
服务与钩子
GitHub 仓库管理中的“钩子与服务”部分是让 GitHub 与外部系统交互的最简单方式。
服务
首先,我们来看看服务。钩子和服务集成都可以在仓库的“设置”部分找到,我们之前在那里查看了添加协作者和更改项目默认分支。在“Webhooks and Services”选项卡下,您会看到类似于服务与钩子配置部分的内容。

有几十种服务可供选择,其中大部分是与其他商业和开源系统的集成。它们大多用于持续集成服务、bug 和问题跟踪器、聊天室系统和文档系统。我们将演示如何设置一个非常简单的钩子:电子邮件钩子。如果您从“添加服务”下拉列表中选择“电子邮件”,您将获得一个配置屏幕,如电子邮件服务配置所示。

在这种情况下,如果我们点击“添加服务”按钮,每次有人推送到仓库时,我们指定的电子邮件地址都会收到一封电子邮件。服务可以监听许多不同类型的事件,但大多数只监听推送事件,然后利用这些数据做一些事情。
如果您正在使用的系统希望与 GitHub 集成,您应该在此处检查是否存在现有的服务集成。例如,如果您使用 Jenkins 来运行代码库的测试,您可以启用 Jenkins 内置服务集成,以便每次有人推送到您的仓库时都触发一次测试运行。
钩子
如果您需要更具体的功能,或者您想与此列表中未包含的服务或网站集成,则可以改用更通用的钩子系统。GitHub 仓库钩子非常简单。您指定一个 URL,GitHub 将在您想要的任何事件发生时向该 URL 发布一个 HTTP 有效负载。
通常,其工作方式是您可以设置一个小型 Web 服务来侦听 GitHub 钩子有效负载,然后在收到数据时对其进行处理。

Web 钩子的配置非常简单。在大多数情况下,您只需输入一个 URL 和一个秘密密钥,然后点击“添加 Webhook”。有几个选项可以选择您希望 GitHub 向您发送有效负载的事件——默认情况下,只有在有人将新代码推送到您仓库的任何分支时,才会收到 `push` 事件的有效负载。
让我们看一个您可能设置来处理 Web 钩子的小型 Web 服务示例。我们将使用 Ruby Web 框架 Sinatra,因为它相当简洁,您应该能够轻松理解我们在做什么。
假设我们希望在特定人员将修改了特定文件的内容推送到我们项目的特定分支时收到电子邮件。我们可以通过以下代码轻松实现:
require 'sinatra'
require 'json'
require 'mail'
post '/payload' do
push = JSON.parse(request.body.read) # parse the JSON
# gather the data we're looking for
pusher = push["pusher"]["name"]
branch = push["ref"]
# get a list of all the files touched
files = push["commits"].map do |commit|
commit['added'] + commit['modified'] + commit['removed']
end
files = files.flatten.uniq
# check for our criteria
if pusher == 'schacon' &&
branch == 'ref/heads/special-branch' &&
files.include?('special-file.txt')
Mail.deliver do
from 'tchacon@example.com'
to 'tchacon@example.com'
subject 'Scott Changed the File'
body "ALARM"
end
end
end
在这里,我们获取 GitHub 传递给我们的 JSON 有效负载,并查找是谁推送的,他们推送到了哪个分支,以及所有被推送的提交中涉及了哪些文件。然后我们对照我们的标准进行检查,如果匹配,则发送一封电子邮件。
为了开发和测试类似这样的功能,在设置钩子的同一屏幕上,您会有一个方便的开发者控制台。您可以查看 GitHub 尝试为该 Webhook 进行的最后几次传递。对于每个钩子,您可以深入了解其传递时间、是否成功以及请求和响应的主体和头部信息。这使得测试和调试您的钩子变得异常简单。

此功能的另一个优点是,您可以轻松地重新传递任何有效负载以测试您的服务。
有关如何编写 Webhook 以及您可以监听的所有不同事件类型的更多信息,请访问 GitHub 开发者文档:https://githubdocs.cn/en/webhooks-and-events/webhooks/about-webhooks。
GitHub API
服务和钩子为您提供了一种接收仓库事件推送通知的方式,但如果您需要有关这些事件的更多信息怎么办?如果您需要自动化诸如添加协作者或标记问题等操作怎么办?
这就是 GitHub API 派上用场的地方。GitHub 拥有大量的 API 端点,可以以自动化方式完成您在网站上几乎所有能做的事情。在本节中,我们将学习如何认证并连接到 API,如何在问题上发表评论,以及如何通过 API 更改拉取请求的状态。
基本用法
您能做的最基本的事情是对不需要认证的端点进行简单的 GET 请求。这可以是关于用户的信息,或者是关于开源项目的只读信息。例如,如果我们想了解更多关于名为“schacon”的用户的信息,我们可以运行如下命令:
$ curl https://api.github.com/users/schacon
{
"login": "schacon",
"id": 70,
"avatar_url": "https://avatars.githubusercontent.com/u/70",
# …
"name": "Scott Chacon",
"company": "GitHub",
"following": 19,
"created_at": "2008-01-27T17:19:28Z",
"updated_at": "2014-06-10T02:37:23Z"
}
有大量的此类端点可以获取关于组织、项目、问题、提交的信息——几乎是您在 GitHub 上可以公开看到的所有内容。您甚至可以使用 API 来渲染任意 Markdown 或查找 `.gitignore` 模板。
$ curl https://api.github.com/gitignore/templates/Java
{
"name": "Java",
"source": "*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
"
}
评论问题
然而,如果您想在网站上执行操作,例如评论 Issue 或 Pull Request,或者如果您想查看或与私人内容互动,则需要进行身份验证。
有几种认证方式。您可以使用只包含用户名和密码的基本认证,但通常更好的做法是使用个人访问令牌。您可以从设置页面的“应用程序”选项卡生成此令牌。

它会询问您此令牌所需的范围和描述。请务必使用良好的描述,这样当您的脚本或应用程序不再使用时,您可以放心地删除该令牌。
GitHub 只会向您显示一次令牌,所以请务必复制它。现在您可以使用此令牌在脚本中进行身份验证,而不是使用用户名和密码。这很好,因为您可以限制您想要做的事情的范围,并且令牌是可撤销的。
这还有一个额外的好处,可以提高您的速率限制。如果没有认证,您将被限制为每小时 60 个请求。如果您进行认证,则每小时可以发出多达 5,000 个请求。
所以让我们用它来评论我们的一个问题。假设我们想在特定问题(问题 #6)上留下评论。为此,我们必须向 `repos/
$ curl -H "Content-Type: application/json" \
-H "Authorization: token TOKEN" \
--data '{"body":"A new comment, :+1:"}' \
https://api.github.com/repos/schacon/blink/issues/6/comments
{
"id": 58322100,
"html_url": "https://github.com/schacon/blink/issues/6#issuecomment-58322100",
...
"user": {
"login": "tonychacon",
"id": 7874698,
"avatar_url": "https://avatars.githubusercontent.com/u/7874698?v=2",
"type": "User",
},
"created_at": "2014-10-08T07:48:19Z",
"updated_at": "2014-10-08T07:48:19Z",
"body": "A new comment, :+1:"
}
现在,如果您转到那个问题,您可以看到我们刚刚成功发布的评论,如通过 GitHub API 发布的评论所示。

您可以使用 API 完成网站上几乎所有操作——创建和设置里程碑、将人员分配给问题和拉取请求、创建和更改标签、访问提交数据、创建新的提交和分支、打开、关闭或合并拉取请求、创建和编辑团队、评论拉取请求中的代码行、搜索网站等等。
更改拉取请求的状态
我们最后看一个示例,因为它在处理 Pull Request 时非常有用。每个提交可以关联一个或多个状态,并且有一个 API 可以添加和查询该状态。
大多数持续集成和测试服务都利用此 API 来响应推送,通过测试被推送的代码,然后报告该提交是否通过了所有测试。您还可以使用它来检查提交消息格式是否正确,提交者是否遵循了您的所有贡献指南,提交是否有效签名——以及许多其他事情。
假设您在您的仓库上设置了一个 webhook,它会触发一个小型 web 服务,该服务检查提交消息中是否存在 `Signed-off-by` 字符串。
require 'httparty'
require 'sinatra'
require 'json'
post '/payload' do
push = JSON.parse(request.body.read) # parse the JSON
repo_name = push['repository']['full_name']
# look through each commit message
push["commits"].each do |commit|
# look for a Signed-off-by string
if /Signed-off-by/.match commit['message']
state = 'success'
description = 'Successfully signed off!'
else
state = 'failure'
description = 'No signoff found.'
end
# post status to GitHub
sha = commit["id"]
status_url = "https://api.github.com/repos/#{repo_name}/statuses/#{sha}"
status = {
"state" => state,
"description" => description,
"target_url" => "http://example.com/how-to-signoff",
"context" => "validate/signoff"
}
HTTParty.post(status_url,
:body => status.to_json,
:headers => {
'Content-Type' => 'application/json',
'User-Agent' => 'tonychacon/signoff',
'Authorization' => "token #{ENV['TOKEN']}" }
)
end
end
希望这相当简单易懂。在这个 Web 钩子处理程序中,我们遍历刚刚推送的每个提交,在提交消息中查找字符串“Signed-off-by”,最后通过 HTTP 向 `/repos/
在这种情况下,您可以发送一个状态('success'、'failure'、'error')、发生的描述、用户可以访问以获取更多信息的目标 URL,以及一个“上下文”,以防单个提交有多个状态。例如,一个测试服务可能会提供一个状态,而像这样的验证服务也可能会提供一个状态——“上下文”字段是它们区分的方式。
如果有人在 GitHub 上打开了一个新的 Pull Request,并且设置了此钩子,您可能会看到类似于通过 API 的提交状态的内容。

您现在可以看到,消息中包含“Signed-off-by”字符串的提交旁边有一个绿色小对勾,而作者忘记签署的提交旁边则有一个红色叉号。您还可以看到 Pull Request 会获取分支上最后一次提交的状态,并在失败时向您发出警告。如果您使用此 API 获取测试结果,这非常有用,这样您就不会意外合并最后一次提交测试失败的代码。
Octokit
尽管我们在这些示例中几乎所有操作都通过 `curl` 和简单的 HTTP 请求完成,但存在一些开源库,它们以更符合惯例的方式提供此 API。在撰写本文时,支持的语言包括 Go、Objective-C、Ruby 和 .NET。请访问 https://github.com/octokit 获取更多信息,因为它们处理了大部分 HTTP 请求。
希望这些工具能够帮助您自定义和修改 GitHub,使其更好地适应您的特定工作流程。有关整个 API 的完整文档以及常见任务的指南,请访问 https://githubdocs.cn/。