はじめに
GitHubのIssuesを使って個人的にタスク管理をし始めた。自分にassignされたissuesの一覧は https://github.com/issues/assigned で見ることができるが、実際にどの程度処理したのか過去の履歴が見られなかったので、Pythonを使って可視化することにした。
主な実行環境は以下の通り。
- macOS Big Sur 11.1
- conda 4.9.2
- Python 3.7.7
- PyGithub 1.54
PyGithub
PythonからGitHub APIを叩くには、PyGithubという便利なモジュールが存在するのでこれを使う。インストールはconda install -c conda-forge pygithub
でよい。
事前の準備としてGitHubのアクセストークンを作成する必要がある。PyGithubを使って、GitHubの情報を取得してみたという記事にしたがって、Select Scopesのrepoにチェックを入れてトークンを作成する。
やることとしては、自分にassignされたissuesを取得して、その作成時刻(およびcloseした時刻)を取得すればよい。
詳細はPyGithubの公式ドキュメントを参照されたいが、コードのスニペットは以下の通り。
from github import Github
# トークンを用いてGithubオブジェクトを作成
g = Github(token)
# 引数なしのget_userで自分(AuthenticatedUser)を取得する
user = g.get_user()
# get_user_issuesで自分にassignされたclosedなissueのPaginatedListを取得
issues = user.get_user_issues(filter="assigned", state="closed")
# 作成時刻とclose時刻を取得
for issue in issues:
print(issue.created_at)
print(issue.closed_at)
実際のコードと実行結果
過去30日間のissueの数と増減をグラフにした。タイトルには期間内に、及びopen/closedした数も書いておいた。
from datetime import datetime as dt
from datetime import timedelta
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from github import Github
# 時刻配列の初期化
today = dt.strptime(dt.now().strftime("%Y-%m-%d"), "%Y-%m-%d")
times = []
counts = []
for day in range(-30, 2):
times.append(today + timedelta(days=day))
counts.append(0)
times2 = []
increments = []
decrements = []
for day in range(-30, 1):
times2.append(today + timedelta(days=day) + timedelta(hours=12))
increments.append(0)
decrements.append(0)
# GitHubのissuesの取得
token = "" # あなたのトークン
g = Github(token)
user = g.get_user()
for issue in user.get_user_issues(filter="assigned", state="open"):
created = issue.created_at
for index, time in enumerate(times):
if created <= time:
counts[index] += 1
for index, time2 in enumerate(times2):
begin_time = time2 - timedelta(hours=12)
end_time = time2 + timedelta(hours=12)
if begin_time <= created and created < end_time:
increments[index] += 1
for issue in user.get_user_issues(filter="assigned", state="closed"):
created = issue.created_at
closed = issue.closed_at
for index, time in enumerate(times):
if created <= time and time < closed:
counts[index] += 1
for index, time2 in enumerate(times2):
begin_time = time2 - timedelta(hours=12)
end_time = time2 + timedelta(hours=12)
if begin_time <= created and created < end_time:
increments[index] += 1
if begin_time <= closed and closed < end_time:
decrements[index] -= 1
# グラフの描画
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(times, counts, color="black")
ax.bar(times2, increments, color="red")
ax.bar(times2, decrements, color="blue")
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
plt.title(
f"wm-ytakano's issues (open={np.sum(increments)} closed={np.sum(decrements)})")
plt.grid()
plt.savefig("issues.png")