内容
Python でGitHub AppのJWTを生成、Installation Access Tokenを生成してからGitHub APIをたたく。
GitHub App user access tokenを使うことも可能だが今回は割愛
準備
pip install cryptography PyJWT
JWTの取得
import sys
import time
import os
import jwt
def get_jwt(pem_path: str, client_id: str) -> str:
# Open PEM
with open(pem_path, 'rb') as pem_file:
signing_key = pem_file.read()
payload = {
# Issued at time
'iat': int(time.time()),
# JWT expiration time (10 minutes maximum)
'exp': int(time.time()) + 600,
# GitHub App's client ID
'iss': client_id
}
# Create JWT
encoded_jwt = jwt.encode(payload, signing_key, algorithm='RS256')
print(f"JWT: {encoded_jwt}")
return encoded_jwt
if __name__ == "__main__":
pem_path = os.environ["GITHUB_APP_PEM_PATH"]
client_id = os.environ["GITHUB_APP_CLIENT_ID"]
jwt = get_jwt(pem_path, client_id)
JWTの確認
def check_jwt(jwt: str) -> dict:
"""Check JWT by sending a request to GitHub API
"""
url = 'https://api.github.com/app'
headers = {
'Authorization': f'Bearer {jwt}',
'Accept': 'application/vnd.github.v3+json'
}
r = requests.get(url=url, headers=headers)
return r.json()
if __name__ == "__main__":
pem_path = os.environ["GITHUB_APP_PEM_PATH"]
client_id = os.environ["GITHUB_APP_CLIENT_ID"]
jwt = get_jwt(pem_path, client_id)
print(check_jwt(jwt))
Appの情報が出てくればOK ✅️
Installation Access Tokenの取得
def get_installation_id(jwt: str) -> int:
url = 'https://api.github.com/app/installations'
headers = {
'Authorization': f'Bearer {jwt}',
'Accept': 'application/vnd.github.v3+json'
}
r = requests.get(url=url, headers=headers)
return r.json()[0]['id']
を追加して
if __name__ == "__main__":
pem_path = os.environ["GITHUB_APP_PEM_PATH"]
client_id = os.environ["GITHUB_APP_CLIENT_ID"]
installation_id = os.getenv("GITHUB_APP_INSTALLATION_ID")
jwt = get_jwt(pem_path, client_id)
print(check(jwt))
if installation_id is None:
installation_id = get_installation_id(jwt)
print(installation_id)
これでinstallation_idを取得 installation_idは GITHUB_APP_INSTALLATION_ID
に入れておけば毎回APIを叩かなくて済むようになる。
GitHub Webhook Event使う場合には payloadに installation idも含まれるので自分で取得しなくていい
Installation Access Tokenを使ってAPIを叩く
def send_gh_api_request(access_token: str, path: str) -> dict:
"""
access_token(str) : Installation Access Token or PAT
path(str) : API path e.g /{owner}/{repo}/pulls?&state=closed
"""
url = 'https://api.github.com/repos' + path
headers = {
'Authorization': f'Bearer {access_token}',
'Accept': 'application/vnd.github+json'
}
r = requests.get(url=url, headers=headers)
return r.json()
res = send_gh_api_request(iat, "/<owner>/<repo>/pulls?&state=closed")
CloseされたPRを取得できた ✅️
Ref
- https://github.com/jpadilla/pyjwt/issues/790
- https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
- https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app
- https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app