はじめに
GitHubのIssuesでタスク管理をしている場合、現在オープンになっているIssueを一覧化して可視化したいことがあります。この記事では、GitHub Actionsを使用して自動的にIssueの一覧をREADMEに反映させる方法を紹介します。
実装の概要
この実装では以下の機能を実現しています。
- Issueの変化を自動取得
- ラベルごとに分類して構造化
- 自動的にREADMEを更新
- 手動での更新も可能
自動更新されたREADME.md
は以下のように表示されます。
実装方法
1. Pythonスクリプト (update_issues.py)
GitHubのAPIを使用してIssueを取得し、README.mdを生成するスクリプトです。
import os
import requests
from collections import defaultdict
from datetime import datetime
from github import Github
def get_issues(repo_name, token):
"""
GitHubのオープンなIssueを取得する
Args:
repo_name (str): リポジトリ名 (例: "username/repository")
token (str): GitHub Personal Access Token
Returns:
list: Issue情報のリスト
"""
g = Github(token)
repo = g.get_repo(repo_name)
issues = []
# stateをopenに指定して、オープンなissueのみを取得
for issue in repo.get_issues(state='open'):
issue_data = {
'number': issue.number,
'title': issue.title,
'state': issue.state,
'created_at': issue.created_at,
'labels': [label.name for label in issue.labels],
'url': issue.html_url
}
issues.append(issue_data)
return issues
def organize_by_label(issues):
"""
Issueをラベルごとに整理する
Args:
issues (list): Issue情報のリスト
Returns:
dict: ラベルごとにIssueを整理した辞書
"""
label_issues = defaultdict(list)
# ラベルなしのIssueも考慮
for issue in issues:
if not issue['labels']:
label_issues['no_label'].append(issue)
else:
for label in issue['labels']:
label_issues[label].append(issue)
return dict(label_issues)
def create_readme_content(organized_issues):
"""
整理されたIssue情報からREADMEの内容を生成する
Args:
organized_issues (dict): ラベルごとに整理されたIssue情報
Returns:
str: README用のマークダウン文字列
"""
now = datetime.now()
content = ["# Issue Summary\n"]
content.append(f"*Last updated: {now.strftime('%Y-%m-%d %H:%M:%S')}*\n")
content.append(f"*Update ID: {now.timestamp()}*\n") # 必ず差分が出るように一意のIDを追加
total_issues = sum(len(issues) for issues in organized_issues.values())
content.append(f"**Total Open Issues: {total_issues}**\n")
# ラベルごとにIssueを表示
for label, issues in sorted(organized_issues.items()):
content.append(f"## {label}\n")
content.append(f"*Number of issues: {len(issues)}*\n")
# Issue一覧
for issue in sorted(issues, key=lambda x: x['created_at'], reverse=True):
created_date = issue['created_at'].strftime('%Y-%m-%d')
content.append(f"- 🟢 [{issue['title']}]({issue['url']}) (#{issue['number']}) - created: {created_date}")
content.append("\n")
# 実行ログ
content.append("## Update Log\n")
content.append(f"- Script executed at: {now.strftime('%Y-%m-%d %H:%M:%S.%f')} UTC\n")
return "\n".join(content)
def main():
# 環境変数から認証情報を取得
token = os.environ.get("GITHUB_TOKEN")
repo_name = os.environ.get("GITHUB_REPOSITORY")
if not token or not repo_name:
raise ValueError("Required environment variables are not set")
# Issueを取得して整理
issues = get_issues(repo_name, token)
organized_issues = organize_by_label(issues)
# README用の内容を生成
readme_content = create_readme_content(organized_issues)
# README.mdに書き出し
with open("README.md", "w", encoding="utf-8") as f:
f.write(readme_content)
if __name__ == "__main__":
main()
2. GitHub Actions Workflow (.github/workflows/update-issues.yml)
Issueの作成削除時とラベル付与削除時と手動実行を可能にするワークフローの設定です。
name: Update Issue Summary
on:
issues:
types:
- opened # Issue作成時
- closed # Issue close時
- labeled # ラベル付与時
- unlabeled # ラベル削除時
workflow_dispatch: # 手動実行も可能
jobs:
update-readme:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install PyGithub requests
- name: Generate new README
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python update_issues.py
- name: Commit and Push changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add README.md
git diff --quiet && git diff --staged --quiet || (git commit -m "Update Issue summary [skip ci]" && git push)
セットアップ手順
-
リポジトリのセットアップ
- 新しいリポジトリを作成
-
update_issues.py
をリポジトリのルートに配置 -
.github/workflows/update-issues.yml
を作成
-
環境設定
- 特別な設定は必要ありません
- GitHub ActionsのデフォルトのGITHUB_TOKENとGITHUB_REPOSITORYが自動的に利用されます
コードの解説
主要な機能
-
Issue取得(get_issues関数)
def get_issues(repo_name, token): # state='open'を指定してオープンなIssueのみを取得 for issue in repo.get_issues(state='open'): # ...
- オープン状態のIssueのみを取得
- タイトル、作成日、ラベルなどの情報を収集
-
ラベルによる整理(organize_by_label関数)
def organize_by_label(issues): label_issues = defaultdict(list) # ラベルなしのIssueも'no_label'として管理
- 各Issueをラベルごとに分類
- ラベルのないIssueも適切に管理
GitHub Actionsの特徴的な部分
on:
issues:
types:
- opened # Issue作成時
- closed # Issue close時
- labeled # ラベル付与時
- unlabeled # ラベル削除時
workflow_dispatch: # 手動実行も可能
-
workflow_dispatch
: 手動実行を可能にする設定
動作確認方法
-
手動実行による確認
- GitHubリポジトリの「Actions」タブに移動
- 「Update Issue Summary」ワークフローを選択
- 「Run workflow」ボタンをクリック
-
実行結果の確認
- READMEが更新されているか確認
- 実行ログでエラーが発生していないか確認
カスタマイズのポイント
- README形式のカスタマイズ
-
create_readme_content
関数を編集することで、出力形式を変更可能
-
まとめ
この実装により、以下のことが実現できます。
- Issueの自動的な可視化
- ラベルを使った効率的なタスク管理
実装は比較的シンプルですが、タスク管理の効率化に役立つ機能となっています。