Githubリポジトリの一覧を取得する

この記事は MicroAd Advent Calendar 2024の12日目の記事です。
https://qiita.com/advent-calendar/2024/microad

# 概要
Githubリポジトリの利用状況調査のため、リポジトリの一覧を取得したくなりました。
Pythonでスクリプトを作成したので、共有していきたいと思います。

### 目次
- トークンの作成
- 環境変数の設定
- ライブラリのインストール
- オーガナイゼーションの一覧を取得
- リポジトリの一覧を取得
- まとめ

それではやっていきましょう。

# トークンの作成

Settings>Developer Settings>Personal access tokens (classic)
を辿って、Genarate new tokenボタンをクリックします。

※トークン作成画面へのショートカット
https://{ドメイン}/settings/tokens/new

repoにチェックをつけて作成します。
※repoのpublic_repoにチェックをつけただけだと、internalのリポジトリを取得できない

トークンを控えておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870283/b441ce4a-63fa-24fb-0f2d-5895dbdbd5df.png)

# 環境変数の設定

うっかり公開してしまわないように環境変数にセットします。
```bash
# qiita_test
export GITHUB_PERSONAL_ACCESS_TOKEN="xxx"
```

# ライブラリのインストール

pythonのrequestsモジュールをインストールします。
```bash
python -m pip install requests
```

ちなみにpython3.7の環境を使用しています。
```bash
$ python --version
Python 3.7.9
```

# オーガナイゼーションの一覧を取得

ソースコード
```python organizations.py
import os
import requests

GITHUB_TOKEN = os.environ['GITHUB_PERSONAL_ACCESS_TOKEN']


def get_orgs_as_json():
    """
    https://docs.github.com/ja/rest/orgs/orgs
    """

    url = "https://{ドメイン}/api/v3/organizations?per_page=100"

    header = {
        "Accept": "application/vnd.github+json",
        "Authorization": f"Bearer {GITHUB_TOKEN}"
    }

    response = requests.get(url, headers=header)
    response.raise_for_status()

    return response.json()


def output_list(file_name: str, org_list: list) -> list:
    """
    ファイル出力
    """
    with open(file_name, 'w') as f:
        for row in org_list:
            f.write(f'{row[0]}\t{row[1]}\n')


def main():
    org_list = []
    for row in get_orgs_as_json():
        id = int(row['id'])
        name = row['login']
        org_list.append((id, name))
    output_list('org_list.tsv', org_list)


if __name__ == '__main__':
    """
    メイン処理
    """
    print('Process start')
    main()
    print('Process end')

```

実行
```bash
python organizations.py
```

出力イメージ
```org_list.tsv
1	org_name_a
2	org_name_b
3	org_name_c
```

# リポジトリの一覧を取得

ソースコード
```python repositories.py
import os
import requests
import time

GITHUB_TOKEN = os.environ['GITHUB_PERSONAL_ACCESS_TOKEN']

ignore_organization_list = [
    'aaa',
    'bbb',
    'ccc',
]


def get_orgs_as_json():
    """
    https://docs.github.com/ja/rest/orgs/orgs
    """

    url = "https://{ドメイン}/api/v3/organizations?per_page=100"

    header = {
        "Accept": "application/vnd.github+json",
        "Authorization": f"Bearer {GITHUB_TOKEN}"
    }

    response = requests.get(url, headers=header)
    response.raise_for_status()

    return response.json()


def get_org_names() -> list:
    """
    オーガナイゼーション名のリストを取得
    """
    org_name_list = []
    for row in get_orgs_as_json():
        name = row['login']
        org_name_list.append(name)
    return org_name_list


def get_repositories_as_json(organization_name: str, page: int) -> list:
    """
    https://docs.github.com/ja/rest/repos/repos
    """

    url = f"https://{ドメイン}/api/v3/orgs/{organization_name}/repos?per_page=100&page={page}"

    header = {
        "Accept": "application/vnd.github+json",
        "Authorization": f"Bearer {GITHUB_TOKEN}"
    }

    response = requests.get(url, headers=header)
    response.raise_for_status()

    return response.json()


def get_repositories(organization_name: str) -> list:
    """
    リポジトリのリストを取得
    """
    repositories = []
    page = 0
    while True:
        page += 1
        part_repositories = get_repositories_as_json(organization_name, page)
        if len(part_repositories) == 0:
            break
        repositories.extend(part_repositories)
    return repositories


def output_list(file_name: str, repository_list: list) -> list:
    """
    ファイル出力
    """
    with open(file_name, 'w') as f:
        for row in repository_list:
            f.write(f'{row[0]}\t{row[1]}\n')


def main():
    repository_list = []
    for organization_name in get_org_names():
        print(organization_name)
        if organization_name in ignore_organization_list:
            continue
        for row in get_repositories(organization_name):
            repository_name = row['name']
            archived = bool(row['archived'])
            if archived:
                continue
            repository_list.append((organization_name, repository_name))
        time.sleep(0.1)
    # organization_name, repository_name でソート
    sorted_repository_list = sorted(repository_list, key=lambda x: (x[0], x[1]))
    output_list('repository_list.tsv', sorted_repository_list)


if __name__ == '__main__':
    """
    メイン処理
    """
    print('Process start')
    main()
    print('Process end')
```

実行
```bash
python repositories.py
```

出力イメージ
```repository_list.tsv
org_name_a	repo_name_a
org_name_b	repo_name_b
org_name_c	repo_name_c
```

# まとめ
Githubリポジトリの一覧を出力することができました！
リポジトリは日々増えていくので変化が見えて楽しいです。

ではでは。