3

我正在使用 Github 创建一个构建管道,它将在每个拉取请求上创建一个检查运行以分析我的应用程序的性能。我已经创建了 Github 应用程序并将其安装到我的仓库并生成了私钥。我需要执行Authenticating as an installation以获得访问令牌。

但是根据文档来获取安装访问令牌,首先我必须获取该应用程序的安装列表,并且必须从该列表中找到特定的安装。但是我不知道如何识别在安装我的应用程序的特定存储库上引发的拉取请求事件的应用程序的特定安装 ID。

我不知道我错过了什么。

4

2 回答 2

4

如果您的 CI/CD 不能与 GitHub 的 webhook 一起使用(例如,由于防火墙),您可以执行以下操作:

#!/bin/bash

HEADER=$( echo -n {\"alg\":\"RS256\"} | base64 | tr -d '=' )
PAYLOAD=$( echo -n \{\"iat\":$(date -u '+%s'),\"exp\":$(( $( date -u '+%s' ) + 600 )),\"iss\":$GITHUB_APP_ID\} | base64 | tr -d '\n' | tr -d '=' | tr / _ | tr + - )
SIGNATURE=$( echo -n "$HEADER.$PAYLOAD" | openssl dgst -sha256 -sign ./private_key -binary | openssl base64 | tr -d '\n' | tr -d '=' | tr / _ | tr + - )
TOKEN=$HEADER.$PAYLOAD.$SIGNATURE

INSTALLATION_ID=$( curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github.v3+json" https://api.github.com/app/installations | jq .[0].id )
INSTALLATION_TOKEN=$( curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github.v3+json" -d '{"permissions":{ "checks":"write"}}' https://api.github.com/app/installations/$INSTALLATION_ID/access_tokens | jq .token | tr -d '"' )
echo $INSTALLATION_TOKEN

或者在 Python 中:

# Implementation of: https://docs.github.com/en/developers/apps/authenticating-with-github-apps#authenticating-as-a-github-app
# Inspired by https://gist.github.com/pelson/47c0c89a3522ed8da5cc305afc2562b0

# TL;DR
# Only GitHub App has an access to annotations API. In order to access this API, we need to
# generate a token based on GitHub App's private key and ID. The token (aka JWT) is valid for only 10 min.

import json
import os
import time

import jwt
import requests
from cryptography.hazmat.backends import default_backend

path_to_github_app_key = os.environ["PATH_TO_GITHUB_APP_KEY"]
cert_bytes = open(path_to_github_app_key, "r").read().encode()
github_app_id = os.environ["GITHUB_APP_ID"]
private_key = default_backend().load_pem_private_key(cert_bytes, None)
time_since_epoch_in_seconds = int(time.time())

payload = {
    # issued at time, 60 seconds in the past to allow for clock drift
    "iat": time_since_epoch_in_seconds - 60,
    # JWT expiration time (10 minute maximum)
    "exp": time_since_epoch_in_seconds + (10 * 60),
    # GitHub App's identifier
    "iss": github_app_id,
}

encoded_payload = jwt.encode(payload, private_key, algorithm="RS256")

headers = {
    "Authorization": "Bearer {}".format(encoded_payload),
    "Accept": "application/vnd.github.v3+json",
}

resp = requests.get("https://api.github.com/app/installations", headers=headers)

installation_id = json.loads(resp.content.decode())[0]["id"]

data = '{"permissions":{ "checks":"write"}}'
resp = requests.post(
    "https://api.github.com/app/installations/"
    + str(installation_id)
    + "/access_tokens",
    headers=headers,
    data=data,
)

installation_token = json.loads(resp.content.decode())["token"]
print(installation_token)

我花了一段时间,但这段代码有效。您需要拥有包含 GitHub 生成的私钥的GITHUB_APP_ID文件。private_key

然后您可以像这样编辑检查运行:

curl -s -H "Authorization: token $GITHUB_APP_INSTALLATION_TOKEN" -H "application/vnd.github.v3+json" -d @body.json https://api.github.com/<username/organization>/$GITHUB_REPO/check-runs

body.json包含以下数据的 JSON 文件在哪里: https ://developer.github.com/v3/checks/runs/

例如:

# Create check "Linter" and set its status to "queued".
# https://developer.github.com/v3/checks/runs/

import json
import os

import requests

github_repo = os.environ["GITHUB_REPO"]
github_token = os.environ["GITHUB_APP_INSTALLATION_TOKEN"]
head_sha = os.environ["COMMIT_SHA"]

check = {
    "name": "Linter",
    "head_sha": head_sha,
    "status": "queued",
    "output": {
        "title": "Waiting...",
        "summary": "Check code with linter",
        "text": "Execute 'golangci-lint run'",
    },
}
data = json.dumps(check)

headers = {
    "Authorization": "token " + github_token,
    "Accept": "application/vnd.github.v3+json",
}

# Send request to GitHub.
requests.post(
    "https://api.github.com/repos/<username/organization>/" + github_repo + "/check-runs",
    headers=headers,
    data=data,
)
于 2020-08-22T13:49:51.653 回答
0

本质上,要与代码无关,您可以调用https://api.github.com/app/installations API 方法来获取最新安装。但是,您必须确保最新的是您需要的,或者您已收到正确的用户/组织,以便您可以在结果中搜索正确的。否则,您需要使用 webhook ( https://developer.github.com/apps/quickstart-guides/setting-up-your-development-environment/#authenticating-as-an-installation )。

于 2020-10-13T06:15:21.123 回答