前提
以下の環境で実装、動作確認
要素 | バージョン |
---|---|
debian | 8.6 |
python | 3.6.2 |
概要
GithubAPIを用いて、自身がGithub上のリモートリポジトリに対してpushした内容からコミットログを取得し、それに関する情報をTwitterAPIを用いてツイートしたお話。
本記事ではTwitterAPIを利用するためのコンシューマキー、アクセストークンは取得済みであることを前提としている。
同じことはGithubのWebhookを使ってできるしむしろ自然だが、その場合サーバーを用意する必要があるので、今回はあえてpull型で非効率なやり方を採用
動作イメージ
リモートリポジトリがGithub上にあるリポジトリに対して適当にコミット/プッシュ
$ git commit -m "コミットテスト" [master e6bb9e4] コミットテスト 1 file changed, 1 insertion(+) $ git push origin master Counting objects: 3, done. Delta compression using up to 2 threads. Compressing objects: 100% (3/3), done.
今回実装したコマンドを実行する
$ python main.py
以下のように、リポジトリ名、コミットメッセージ、diffへのリンクがツイートされる
GithubAPIについて
GithubAPIは、名前の通りGithubの各種読み書きを行うためのAPI。
公開されているデータの取得に関しては認証無しで手軽に利用できる。
例えば、curlコマンドを用いて以下のURLに対してGETリクエストを送信すると
curl -i https://api.github.com/users/sa2knight/events
以下のように、該当ユーザのGithubでのイベントログを取得することができる
[ { "id": "6516862394", "type": "PushEvent", "actor": { "id": 16274215, "login": "Sa2Knight", "display_login": "Sa2Knight", "gravatar_id": "", "url": "https://api.github.com/users/Sa2Knight", "avatar_url": "https://avatars.githubusercontent.com/u/16274215?" }, "repo": { "id": 96615971, "name": "Sa2Knight/degulog2", "url": "https://api.github.com/repos/Sa2Knight/degulog2" }, "payload": { "push_id": 1946817475, "size": 1, "distinct_size": 1, "ref": "refs/heads/master", "head": "4208370eb0cda0a1bab02fd3fbe5bf7e3e6f5f29", "before": "afd8b8647c2b810ceb731a74bad20c7388c19974", "commits": [ { "sha": "4208370eb0cda0a1bab02fd3fbe5bf7e3e6f5f29", "author": { "email": "shingo.sasaki.0529@gmail.com", "name": "shingo sasaki" }, "message": "バックアップ追加", "distinct": true, "url": "https://api.github.com/repos/Sa2Knight/degulog2/commits/4208370eb0cda0a1bab02fd3fbe5bf7e3e6f5f29" } ] }, "public": true, "created_at": "2017-08-27T15:22:08Z" }, { "id": "6516846556", "type": "PushEvent", (以下省略)
ここで取得できるイベントは、Webで言う以下のような、そのユーザのリポジトリに対する操作全般の情報なので、今回はこのAPIを用いることにする
ライブラリの導入
今回はPython3を用いて実装するので、Pythonのパッケージ管理ツールであるpipを用いて、以下の二種類のライブラリを導入する。
- requests
— HTTPライブラリ - twitter
— TwitterAPI用
TwitterAPIの利用には認証も絡んでくるので、専用のライブラリを利用する。GithubAPIは特定URLにGETするだけなのでHTTPライブラリで直接実行することに。
$ pip install requests $ pip install twitter
ソースコード
import twitter import requests import json import os FILE_NAME = "last_id" EVENTS_URL = "https://api.github.com/users/sa2knight/events" REPOSITORY_URL = "https://api.github.com/repos" def tweet(text): auth = twitter.OAuth(consumer_key=os.environ['TWITTER_CONSUMER_KEY'], consumer_secret=os.environ['TWITTER_CONSUMER_SECRET'], token=os.environ['TWITTER_ACCESS_TOKEN'], token_secret=os.environ['TWITTER_ACCESS_SECRET']) t = twitter.Twitter(auth=auth) t.statuses.update(status=text) def tweet_event(event): tweet_text = f""" @null Githubにコミットをプッシュしました。 [{event['repository']}] 「{event['commits'][0]['message']}」 """.strip() if 1 < len(event['commits']): tweet_text += f"ほか{len(event['commits']) - 1}件" tweet_text += f"\n\n{event['commits'][0]['url']}" tweet(tweet_text) def save_id(id): with open(FILE_NAME, 'w') as f: f.write(id) def load_id(): if os.path.exists(FILE_NAME): with open(FILE_NAME, 'r') as f: return f.readline() else: return '' def is_new_id(id): return id != load_id() def parse_commit_log(repo_name, commit): return { 'url': f"https://github.com/{repo_name}/commit/{commit['sha']}", 'message': commit['message'] } def get_repository_description(repo_name): url = f"{REPOSITORY_URL}/{repo_name}" response = requests.get(url) repository = json.loads(response.text) return repository['description'] def get_recent_push_event(): response = requests.get(EVENTS_URL) events = json.loads(response.text) recent_event = list(filter(lambda e: e['type'] == 'PushEvent', events))[0] repo_name = recent_event['repo']['name'] commits = list(map(lambda c: parse_commit_log(repo_name, c), recent_event['payload']['commits'])) return { 'id': recent_event['id'], 'repository': get_repository_description(recent_event['repo']['name']), 'commits': commits, } event = get_recent_push_event() if is_new_id(event['id']): tweet_event(event) save_id(event['id']) print('ツイートを投稿しました') else: print('ツイートは不要です')
スクリプトを実行すると概ね以下の手順でツイートされる
1. GithubAPIを叩いて、自身の最新のコミットを含んだイベントログを取得
2. 直近で取得したイベントIDをファイルに保存しておき、そのIDと比較、一致していた場合変更なしとして終了
3. イベントログを元にツイートするテキストを生成
4. TwitterAPIを用いてツイート
所感
- 本スクリプトを15分おきぐらいにcronで実行すれば、概ねコミット内容がツイートされる
- Webhookと違ってpull型になるので、リアルタイムにはできない
- 単にGithubAPIが使いたくて遊んだだけで実用性はあんまり無い