-
1. 起步
-
2. Git 基础
-
3. Git 分支
-
4. 服务器上的 Git
- 4.1 协议
- 4.2 在服务器上部署 Git
- 4.3 生成 SSH 公钥
- 4.4 架设服务器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方托管服务
- 4.10 小结
-
5. 分布式 Git
-
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 和服务”选项卡下,您会看到一个类似 服务和钩子配置部分 的界面。
您可以从几十种服务中选择,其中大多数都是与其他商业和开源系统的集成。它们大多用于持续集成服务、错误和问题跟踪器、聊天室系统和文档系统。我们将逐步介绍如何设置一个非常简单的服务:电子邮件钩子。如果您从“添加服务”下拉菜单中选择“email”,您将看到一个类似 电子邮件服务配置 的配置屏幕。
在这种情况下,如果我们点击“添加服务”按钮,指定的电子邮件地址将在每次有人推送到仓库时收到一封电子邮件。服务可以监听许多不同类型的事件,但大多数只监听推送事件,然后对该数据执行某些操作。
如果您正在使用的某个系统需要与 GitHub 集成,您应该在此处查看是否有现成的服务集成可用。例如,如果您使用 Jenkins 在代码库上运行测试,您可以启用 Jenkins 内置的服务集成,以便在每次有人推送到您的仓库时触发一次测试运行。
钩子
如果您需要更具体的东西,或者想与列表中未包含的服务或网站集成,您可以使用更通用的钩子系统。GitHub 仓库钩子非常简单。您指定一个 URL,GitHub 会在您想要的任何事件发生时将 HTTP 有效负载发送到该 URL。
通常,它的工作方式是您可以设置一个小型 Web 服务来监听 GitHub 钩子有效负载,然后在收到数据时对其进行处理。
要启用钩子,请在 服务和钩子配置部分 中点击“添加 webhook”按钮。这将带您进入一个类似 Web hook 配置 的页面。
Web hook 的配置非常简单。在大多数情况下,您只需输入一个 URL 和一个密钥,然后点击“添加 webhook”。有几个选项可以选择 GitHub 发送有效负载的事件 — 默认情况下,只会在有人将新代码推送到仓库的任何分支时发送 push 事件的有效负载。
让我们看一个您可能需要设置来处理 Web hook 的 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 尝试为该 Web hook 进行的最后几次传递。对于每个钩子,您可以深入了解其传递时间、是否成功,以及请求和响应的 body 和 headers。这使得测试和调试钩子变得异常容易。
另一个很棒的功能是,您可以轻松地重新传递任何有效负载来测试您的服务。
有关如何编写 Web hooks 以及可以监听的所有不同事件类型的更多信息,请访问 GitHub 开发者文档:https://githubdocs.cn/en/webhooks-and-events/webhooks/about-webhooks。
GitHub API
服务和钩子提供了接收关于仓库事件的推送通知的方式,但如果需要更多关于这些事件的信息怎么办?如果需要自动化诸如添加协作者或标记问题之类的事情怎么办?
这时 GitHub API 就派上用场了。GitHub 提供了大量的 API 端点,几乎可以自动化地完成您在网站上能做的任何事情。在本节中,我们将学习如何进行身份验证并连接到 API,如何评论某个问题,以及如何通过 API 更改 Pull Request 的状态。
基本用法
最基本的操作是对不需要身份验证的端点进行简单的 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*
"
}
评论某个问题
但是,如果您想在网站上执行操作,例如评论某个问题或 Pull Request,或者想查看或与私有内容进行交互,您就需要进行身份验证。
有几种身份验证方法。您可以使用简单的用户名和密码进行基本身份验证,但通常最好使用个人访问令牌。您可以从设置页面的“Applications”选项卡生成此令牌。
它会询问您要为该令牌授予哪些权限范围以及一个描述。请确保使用一个好的描述,这样当您的脚本或应用程序不再使用时,您就可以放心地删除该令牌。
GitHub 只会向您显示一次令牌,所以请务必将其复制。现在您可以在脚本中使用此令牌进行身份验证,而不是使用用户名和密码。这样做的好处是您可以限制操作的范围,并且令牌是可撤销的。
这还有增加速率限制的好处。如果不进行身份验证,您每小时最多只能进行 60 次请求。如果您进行身份验证,则每小时最多可以进行 5,000 次请求。
所以,让我们使用它来评论我们的一个问题。假设我们想在特定问题 #6 上留下评论。为此,我们必须向 repos/<user>/<repo>/issues/<num>/comments 发送 HTTP POST 请求,并将刚刚生成的令牌作为 Authorization 标头。
$ 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、创建和更改标签、访问提交数据、创建新的提交和分支、打开、关闭或合并 Pull Request、创建和编辑团队、在 Pull Request 的代码行上发表评论、搜索网站等等。
更改 Pull Request 的状态
最后还有一个例子,我们来看一下,因为它对于处理 Pull Request 非常有用。每个提交都可以关联一个或多个状态,并且有一个 API 用于添加和查询这些状态。
大多数持续集成和测试服务都利用此 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 hook 处理程序中,我们遍历刚刚推送的每个提交,在提交消息中查找“Signed-off-by”字符串,最后我们通过 HTTP POST 到 /repos/<user>/<repo>/statuses/<commit_sha> API 端点,并附带状态信息。
在这种情况下,您可以发送一个状态('success'、'failure'、'error')、一个描述发生了什么的描述、一个用户可以访问以获取更多信息的 target URL,以及一个“context”,以防单个提交有多个状态。例如,一个测试服务可能会提供一个状态,而一个像这样的验证服务也可能提供一个状态 — “context”字段就是它们被区分开的方式。
如果有人在 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/。