Pythonでbitbucketのレポジトリ一覧を取得する

# はじめに
git pythonを利用してbitbucketのプライベートレポジトリの一覧を取得します。
参考： [シェルスクリプトでの取得方法](https://qiita.com/monoqlock/items/8a9f4cd7122eca5e7a77)
## 用途
こちらのエントリ[開発チームの生産性・健全性を客観的に知るためにリポジトリ履歴から機械的に可視化するツールを作った](https://qiita.com/hirokidaichi/items/ceece347f808cc9d14dd)を読んで会社の中でもこの可視化ツールを使ってレポジトリも横並びで評価したいなと考えています。この時にbitbucketのプライベートレポジトリの一覧をpython経由で取得できると便利だったので、紹介します。
## 作成したスクリプト
```python:main.py

import os
from os.path import join, dirname
from dotenv import load_dotenv
import requests
import json
from git import Repo, NoSuchPathError
import logging

load_dotenv(verbose=True)

class GitConnector:

    LOGGER = logging.getLogger('GitActivity')

    def __init__(self):
        self._dotenv_path = join(dirname(__file__), '.env')
        load_dotenv(self._dotenv_path)
        self._user_name = os.environ.get("BITBUCKET_USER_NAME")
        self._password = os.environ.get("BITBUCKET_PRIVATE_ACCESS_TOKEN")
        self._remote_workspace = os.environ.get("REMOTE_WORK_SPACE")
        self._work_dir = os.environ.get("WORK_DIR")
        self.git_repo = None

    def get_repositories(self):
        url = 'https://api.bitbucket.org/2.0/repositories/%s' % self._remote_workspace
        params = {'pagelen': 100, 'page': 1, 'sort': 'name'}
        auth = (self._user_name, self._password)
        response = requests.get(url=url, params=params, auth=auth)
        text = json.loads(response.text)
        repositories = [value['name'] for value in text['values']]
        return repositories

    def clone(self, repo):

        try:
            self.git_repo = Repo(join(self._work_dir, repo))
            self.LOGGER.warning("%s exists, skip cloning.", repo)

        except NoSuchPathError:
            self.LOGGER.info("%s doesn't exist, cloning... it will take a while... ", repo)
            self.git_repo = Repo.clone_from(url='https://' + self._user_name + ':' + self._password + '@bitbucket.org/'
                                                + join(self._remote_workspace, repo),
                                            to_path=join(self._work_dir, repo))
        return self.git_repo, self._work_dir + repo


def main():
    git_activity = GitConnector()
    repositories = git_activity.get_repositories()
    for repo in repositories:
        git_repo, path = git_activity.clone(repo)

if __name__ == '__main__':
    main()
```

## 手順解説
### bitbucketのユーザ名、パスワードの設定
まず、`git_activity = GitConnector()`で環境変数の取得・初期化を行います。今回は、環境変数を別途`.env`として用意してパスワードなどの設定値を読み込みます。

```:.env
BITBUCKET_USER_NAME=username
BITBUCKET_PRIVATE_ACCESS_TOKEN=password
WORK_DIR=/dir/for/clone
REMOTE_WORK_SPACE=your_work_space_name
```

- BITBUCKET_USER_NAME
    - bitbucketのユーザ名です。ログイン時のユーザ名を使用してください
- BITBUCKET_PRIVATE_ACCESS_TOKEN
    - pythonからbitbucketへ接続するために必要なパスワードで、bitbucket cloudの個人設定から発行します
    - [パスワードの追加方法(公式)](https://ja.confluence.atlassian.com/bitbucket/app-passwords-828781300.html)
- WORK_DIR
    - クローンしたいフォルダを設定します
- REMOTE_WORK_SPACE
    - ワークスペース名（`https://bitbucket.org/hogehoge/` の`hogehoge`部分）


### レポジトリ名一覧の取得
bitbucketのワークスペースの情報のリクエスト結果をjson形式でロードしてレポジトリ名のみ抜き出してリストへ保存します。レスポンスの内容は[API reference](https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D)を参照ください。

```python
    def get_repositories(self):
        url = 'https://api.bitbucket.org/2.0/repositories/%s' % self._remote_workspace
        params = {'pagelen': 100, 'page': 1, 'sort': 'name'}
        auth = (self._user_name, self._password)
        response = requests.get(url=url, params=params, auth=auth)
        text = json.loads(response.text)
        repositories = [value['name'] for value in text['values']]
        return repositories
```

### レポジトリをクローン
レポジトリをgitpythonでクローンします。レポジトリが既に存在する場合はクローンをスキップしています。


```python
    def clone(self, repo):
        try:
            self.repo = Repo(join(self._work_dir, repo))
            self.LOGGER.warning("%s exists, skip cloning.", repo)
        except NoSuchPathError as err:
            self.LOGGER.info("%s doesn't exist, cloning... it will take a while... ", repo)
            self.repo = Repo.clone_from(url='https://' + self._user_name + ':' + self._password + '@bitbucket.org/'
                                            + join(self._remote_workspace, repo),
                                        to_path=join(self._work_dir, repo))
        return self.repo, self._work_dir + repo
```

## 実行結果
bitbucket内にあるレポジトリが全てローカルの指定したフォルダへとクローンされます。


## 最後に
今後はクローンしたレポジトリを[冒頭で説明したパッケージ](https://qiita.com/hirokidaichi/items/ceece347f808cc9d14dd)で可視化して、プロダクトごとの生産性を定量的に測れるようにしたいなぁ。