跳转到内容

创建 GitHub App

本指南介绍如何让你的服务器拥有自己的 GitHub 身份。整个过程大约两分钟,只有 服务器所有者需要操作,而且每台服务器只需做一次。

至于事后连接你自己的账户,请参阅 设置 GitHub 集成。

一次注册要承担两项不同的工作,而应用正是让这两者都名副其实的关键:

工作 由什么来应答 为什么重要
个人登录 应用的客户端 ID,经由设备流 你得到一个属于你自己的凭据,保存在服务器上,在所有设备上通用 —— 无需粘贴或轮换令牌
服务器行事 应用的 ID + 私钥 → 安装令牌 webhook、PR 轮询和工单同步不再依赖某一个人的令牌是否仍然有效

注意表格中没有的东西:客户端密钥。GitHub 的设备流仅凭客户端 ID 就能完成身份 验证 —— 无论是设备代码请求还是令牌轮询 —— 因此登录并不需要保存任何密钥。

没有你自己的应用时,第一项工作仍然可以通过构建内置的客户端 ID 完成;第二项工作 则会回退到服务器所有者的凭据,于是后台工作就搭在了最先完成初始化的那个人身上。

  • 你是服务器所有者 —— providerApps.* 操作仅限所有者执行, 其他人根本看不到这张卡片
  • 一个 GitHub 账户,或一个你可以在其中创建应用的组织
  • 不需要任何可公开访问的东西:登录采用设备流,因此服务器 不需要入站端口、隧道、回调 URL 或域名
  1. 打开 github.com/settings/apps/new (对于组织:Settings → Developer settings → GitHub Apps → New GitHub App)
  2. GitHub App name —— 随便填;Control Center (yourname) 就行。它会出现在 服务器所做的提交和评论上
  3. Homepage URL —— 随便填,例如 https://github.com/your-name
  4. Callback URL —— 留空。设备流不需要它
  5. 勾选 Enable Device Flow。这是登录绝不可缺少的唯一一项设置
  6. 取消勾选 Webhook → Active,除非你要单独接入 webhook
  7. 在 Repository permissions 下,至少授予:
    • Contents:Read and write
    • Metadata:Read-only(必选)
    • Pull requests:Read and write
    • Issues:Read and write,如果你用 GitHub Issues 作为工单, 以及为了让机器人搜索 PR 对话中的评论 (参见从 GitHub PR 与 Control Center 对话)
    • Checks:Read-only,用于 PR 页面上的 CI 状态
  8. 在 Where can this GitHub App be installed? 下,选一项合适的 —— “Only on this account” 适合个人服务器
  9. 点击 Create GitHub App

创建完成后,在应用页面上立即取得它们:

值 位置
App ID General 标签页,靠近顶部
Client ID General 标签页,“Client secrets” 下方
Private key Generate a private key —— 会下载一个 .pem 文件

私钥文件只会下载一次,GitHub 之后不会再显示它。请把它保留到粘贴完成;你随时可以 再生成一个。

客户端密钥是可选的,只换来一样东西:如果你把 “Expire user authorization tokens” 保持开启,它就是用来静默续期某个人的令牌, 而不必每八小时请对方重新登录一次。登录本身从不使用它。

更简单的做法是把这个过期设置关掉,这样就哪里都不需要密钥了。如果你保持开启, 就生成一个密钥并粘贴到 设置 → 服务器 → 单点登录(提供商应用卡片)中 —— 它没有对应的环境变量,也不会被内置到构建里,因此始终留在你的服务器上。

一个已注册但未安装的应用可以验证人的身份,却读不到任何内容。

  1. 在应用页面上打开 Install App
  2. 把它安装到你的账户或组织上
  3. 选择 All repositories,或选中这台服务器应当看到的那些仓库
  1. 前往 设置 → 服务器 → 单点登录,滚动到 提供商应用卡片
  2. 在 GitHub 区块中设置各个字段:
    • 应用 ID —— 数字形式的 App ID
    • 私钥 —— 粘贴整个 .pem,包括 BEGIN 和 END 行
    • 客户端 ID —— 来自同一个页面
    • 客户端密钥 —— 仅当你生成了密钥时填写(用于令牌刷新)
  3. 点击测试

密钥在保存时就会被解析,因此被截断或格式错误的粘贴会当场被拒绝,而不会在几小时 后的后台请求中才失败。测试更进一步,会向 GitHub 询问该应用安装在哪些账户上 —— “已保存”和“可用”是两种不同的说法,只有后者才意味着有东西能真正运行。

检查点:GitHub 区块显示“服务器可以自身身份行事,且个人可以登录”,并且 设置 → 工作区 → 个人资料与身份 → 代码托管 下的 GitHub 行现在会提供 使用 GitHub 登录。

对于无界面或脚本化安装,服务器会在某个字段还没有存储值时,首次从环境中播种它:

终端窗口
GITHUB_APP_ID=123456
GITHUB_APP_PRIVATE_KEY="$(cat control-center.private-key.pem)"
GITHUB_CLIENT_ID=Iv1.0123456789abcdef

这些值没有对应的命令行标志 —— 命令行上的密钥可以被主机上的任何进程通过 ps 读到。环境是配置它们的唯一位置,而且它的优先级高于构建内置的任何值。 .env.template 是完整的列表。

本地开发时,仓库根目录的 .env 保存同样的值,桌面端会把它传递给所启动的服务 器。请把密钥写在一行里:.env 的一个值就是一行,而双引号内的 \n 会被解码 为换行符。

GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEow…\n-----END RSA PRIVATE KEY-----"

GITHUB_APP_ID 和 GITHUB_APP_PRIVATE_KEY 与沙盒令牌代理已经读取的名称相同, 因此配置过细粒度智能体令牌的主机可以免费获得登录通道。播种每个字段只发生 一次 —— 此后以存储的值为准,所以在设置中做的修改不会被下一次重启覆盖。

Linear 没有设备流,因此它的登录是一次浏览器往返,确实需要回调 URL —— 提供商应用卡片会显示应当注册的那个确切 URL。

  1. 在 linear.app/settings/api/applications/new 创建一个 OAuth 应用
  2. 把 Callback URL 设为卡片所显示的那个 URL,一字不差
  3. 把 Client ID 和 Client secret 粘贴到 Linear 区块
  4. 可选地添加一个工作区 API 密钥 —— 当没有人类发起时,服务器就是用这个 凭据来同步工单的

登录对话框提示提供方没有返回设备代码

标题为“登录对话框提示提供方没有返回设备代码”的部分

应用上的 Enable Device Flow 没有开启。在 General 下把它打开,然后重试。

测试显示凭据可用,但应用没有安装在任何地方

标题为“测试显示凭据可用,但应用没有安装在任何地方”的部分

注册和安装是两个独立的步骤。在应用页面上打开 Install App 并安装它。

请粘贴整个 .pem 文件,包括 -----BEGIN 和 -----END 行。ed25519 或 EC 密钥 都用不了 —— GitHub App 使用 RSA 签名。

某个成员已登录,却看不到任何仓库

标题为“某个成员已登录,却看不到任何仓库”的部分

该应用没有安装在拥有这些仓库的账户上,或者它的安装选择了不同的仓库。他们自己 的登录所能提供的,仅限于该应用被允许看到的内容。