如果您的 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,
)