GitHub Profile README用動的サマリーカードの自作実装

はじめに

GitHubのプロフィールREADMEには、自身のGitHubリポジトリのコミット数や使用言語などをグラフィカルに表示するSummary Cardsがあります。以前は以下のものを使用していました。

しかし、動きのあるものが欲しくなり、自分で作成することにしました。

リポジトリ情報の取得

GitHubのAPIを利用して、リポジトリの情報を取得できます。フィールREADMEを彩る、動くProfile Summaryを自作" date: 2021-06-30T10:17:23+09:00 draft: false tags: [“GitHub”, “プログラミング”]

はじめに

GitHubのプロフィールREADMEには、自身のGitHubリポジトリのコミット数や使用言語などをグラフィカルに表示するSummary Cardsがあります。以前は以下のものを使用していました。

しかし、動きのあるものが欲しくなり、自分で作成してみることにしました。

リポジトリ情報の取得

GitHubのAPIを利用して、リポジトリの情報を取得できます。

https://api.github.com/users/{username}/repos

上記のAPIからは、以下のようなJSON形式の情報を取得できます。

[
    {
        "id": 312465317,
        "node_id": "MDEwOlJlcG9zaXRvcnkzMTI0NjUzMTc=",
        "name": "1day",
        "full_name": "yuhi-sa/1day",
        "private": false,
        "owner": {
            "login": "yuhi-sa",
            "id": 62089243,
            "node_id": "MDQ6VXNlcjYyMDg5MjQz",
            "avatar_url": "https://avatars.githubusercontent.com/u/62089243?v=4",
            "gravatar_id": "",
            "url": "https://api.github.com/users/yuhi-sa",
            "html_url": "https://github.com/yuhi-sa",
            "followers_url": "https://api.github.com/users/yuhi-sa/followers",
            "following_url": "https://api.github.com/users/yuhi-sa/following{/other_user}",
            "gists_url": "https://api.github.com/users/yuhi-sa/gists{/gist_id}",
            "starred_url": "https://api.github.com/users/yuhi-sa/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/yuhi-sa/subscriptions",
            "organizations_url": "https://api.github.com/users/yuhi-sa/orgs",
            "repos_url": "https://api.github.com/users/yuhi-sa/repos",
            "events_url": "https://api.github.com/users/yuhi-sa/events{/privacy}",
            "received_events_url": "https://api.github.com/users/yuhi-sa/received_events",
            "type": "User",
            "site_admin": false
        },
...リポジトリ数分続く
]

この情報から、リポジトリごとの使用言語やサイズを取得します。

カードの作成

Pythonの matplotlib.animation を用いて、角度をずらしながら円グラフをプロットすることで、回転する円グラフを作成しました。

  • 円グラフを回転させるコードはこちらを参考にしました。
  • 動画プロットの方法については、こちらの記事も参照してください。
def update(num, pie_chart_elements, ax, colors, names, sizes):
    if len(pie_chart_elements) > 0:
        ax.cla() # 現在の軸をクリア
    
    # 円グラフを再描画。startangleで回転角度を調整
    pie_chart_elements = ax.pie(sizes, labels=names, autopct=lambda p: '{:.1f}%'.format(p) if p >= 2.5 else '',\
                                shadow=True, startangle=4*num, colors=colors)
    ax.set_title("Top Size Repos")

def main():
    names, sizes = get_repo_data(user) # APIからデータを取得する関数
    
    fig, ax = plt.subplots() # FigureとAxesを同時に作成
    
    # 初期の円グラフを描画
    pie_chart_elements = ax.pie(sizes, labels=names, autopct=lambda p: '{:.1f}%'.format(p) if p >= 2.5 else '',\
                                shadow=True, startangle=0, colors=colors)
    
    # アニメーションを作成
    # frames: update関数に渡される値のシーケンス (0から90まで)
    # fargs: update関数に追加で渡す引数
    # interval: フレーム間の遅延時間 (ミリ秒)
    ani = animation.FuncAnimation(fig, update, frames=91, fargs=[pie_chart_elements, ax, colors, names, sizes], interval=100)
    
    # アニメーションをGIFとして保存
    # writer: 'ffmpeg' を使用する場合、別途ffmpegのインストールが必要
    # dpi: 解像度
    ani.save('../cards/top.gif', writer="ffmpeg", dpi=100)
    plt.show() # アニメーションを表示

GitHub Actionsによる自動生成

毎日新しいカードが自動生成されるように、GitHub Actionsの schedule イベントを利用しました。

name: Create Card # ワークフローの名前

on:
  push:
    branches: [ master ] # masterブランチへのpushで実行
  pull_request:
    branches: [ master ] # masterブランチへのプルリクエストで実行
  fork:
    branches: [ master ] # リポジリがフォークされた時に実行
  schedule:
    - cron: '45 10 * * *' # 毎日UTC 10:45に実行 (日本時間19:45)

jobs:
  build: # ジョブのID

    runs-on: ubuntu-latest # Ubuntu環境で実行

    steps:
    - uses: actions/checkout@v4 # リポジトリをチェックアウト
    
    - name: Set up Python 3.9 # Python 3.9環境をセットアップ
      uses: actions/setup-python@v5 # actions/setup-python@v5 を使用
      with:
        python-version: 3.9

    - name: Install dependencies # 依存関係をインストール
      run: |
        python -m pip install --upgrade pip
        pip install flake8 pytest # flake8とpytestは通常テスト用なので、必要なければ削除
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi # requirements.txtがあればインストール

    - name: Remove Old Gifs and Configure Git # 古いGIFを削除し、Gitを設定
      run: |
        rm -f cards/lang.gif cards/top.gif # -f オプションでファイルが存在しなくてもエラーにならない
        git config user.name "github-actions[bot]" # GitHub Actionsのbotユーザー名
        git config user.email "github-actions[bot]@users.noreply.github.com" # GitHub Actionsのbotメールアドレス
        # git add と git commit は、次のステップでまとめて行うのが一般的
        # git push は、このステップでは行わない
        
    - name: Update Card # カードを更新(生成)
      run: |
        bash start.bash # カード生成スクリプトを実行

    - name: Commit and Push Changes # 変更をコミットしてプッシュ
      run: |
        git add cards/ # 生成されたGIFファイルを追加
        git commit -m "Update profile summary cards" # コミットメッセージ
        git push origin master # masterブランチにプッシュ

使い方

  1. このリポジトリをフォーク(Fork)します。
  2. username.txt ファイルを編集し、ご自身のGitHubユーザー名に書き換えます。
  3. フォークしたリポジトリのGitHub Actionsタブに移動し、ワークフローを手動で実行(Run workflow)します。 (以降は24時間ごとに自動で更新されます)
  4. ご自身のGitHubプロフィールREADMEに、以下のMarkdownコードを追記してください。{username} の部分をご自身のGitHubユーザー名に置き換えてください。
# 使用言語の円グラフ
![Repos per Language](https://github.com/{username}/github_cards/blob/master/cards/lang.gif?raw=true)

## リポジトリサイズの円グラフ
![Top Size Repos](https://github.com/{username}/github_cards/blob/master/cards/top.gif?raw=true)

# 横幅を指定する場合の書き方
<img src="https://github.com/{username}/github_cards/blob/master/cards/lang.gif?raw=true" width="40%">
<img src="https://github.com/{username}/github_cards/blob/master/cards/top.gif?raw=true" width="40%">