『入る学科間違えた高専生』の日記

プログラミングのコードを書いたりする予定です。あとは日記等。あといつまで高専生やねん

PythonでGitHubの特定のリポジトリのPRをマージする

はじめに

お久しぶりです。まだ生きてます。(昨日、母親に生存確認されました)

自動で自分の書き込み権限があるリポジトリの PR をマージしたいなという思いから前に作ったけどブログに書くまでもないなと思っていたのですが、
最近ブログのトップに広告が表示されだしてしまったので書きます。

今回、このコードを書いたのは、あるサーバアプリプロジェクトが GitHub の PR をマージすることによって AWS の CodePipeline が動いて EC2 にデプロイする仕組みになってるんですけど、
金銭的リソースの制限があるので AutoScaling の最小サイズ(1にしてます)のままで動いています。
これだとトラフィックコントロールしてもデプロイしてる間はプロダクトにアクセスができないので夜中にデプロイしたいという要望にお答えしたい。
しかし、デプロイするたびに夜中に起きてるのはしんどい→明日だって仕事だ。明日はデートだ!とかいろいろある。ちなみに僕にはデートの予定はない。
ここで、 AWS Lambda + CloudWatch を使って夜中に発火させればいいんじゃないかということ書いた次第です。

環境

準備

Personal access tokens からトークンを取得しておきましょう!

GitHub API を叩きまくってもいいんですけど、ドキュメントが膨大すぎてわからなかったので調べたらライブラリがあったので使用します!

$ pip install pygithub

ソースコード

from base64 import b64decode
from github import Github

import boto3
import os


def _get_github_access_token():
    encrypted = os.environ.get('GITHUB_ACCESS_TOKEN')
    decrypted = boto3.client('kms').decrypt(CiphertextBlob=b64decode(encrypted))['Plaintext']
    return decrypted.decode('utf-8')


def lambda_handler(event, handler):
    owner = os.environ.get('GITHUB_OWNER', 'nnsnodnb')
    repository = os.environ.get('GITHUB_REPOSITORY', 'hogepiyofoobar')

    access_token = _get_github_access_token()
    github = Github(access_token)

    # クライアントを使用して対象のリポジトリを取得
    repo = github.get_repo(f'{owner}/{repository}')

    # リポジトリのマージしたい PR を取得
    pull = repo.get_pull(int(os.environ.get('GITHUB_PULL_REQUEST_NUMBER')))

    # GitHub の PR の画面で実際にマージする際に作られるコミットを再現したかったので適当で
    commit_message = pull.title
    number = pull.number
    ref = pull.head.ref

    pull.merge(commit_message=commit_message, commit_title=f'Merge pull request #{number} from {owner}/{ref}')

というような感じです。

今回は、先程取得した GitHubトークンを KMS で暗号化していますが、もし必要なければ適宜対応でお願いします!
KMS の説明は省略します。

qiita.com

ここらへんが参考になるかなと思います。

Lambda の環境変数で、

GITHUB_ACCESS_TOKEN: {{ YOUR ACCESS TOKEN }}
GITHUB_OWNER: {{ OWNER }}
GITHUB_REPOSITORY: {{ REPOSITORY NAME }}
GITHUB_PULL_REQUEST_NUMBER: {{ マージしたいPRの番号 }}

を設定しています。

アップロード

自分は lambda-uploader で zip だけを生成して Lambda の画面で手動でアップロードしました。

もしくは、依存ライブラリを作業ディレクトリにインストールして zip にするっていう形ですかね。

$ pip install -t . pygithub

最後に

これだけのために 2383文字 も書いてるんじゃないよっていう感じです。
今日は仕事が中途半端に何もなくなってしまったのでブログを書きました。
それと最近、ヘルニアなのかは知らないんですが、ずっと右足の太ももが痺れるように痛いです。いい整形外科あったら教えてください。

Aqoursのライブに関係者席で入らせてください!