ローカルのGitBucketをGitHubに移行する(その2)
- ローカルサーバのGitBucketで管理していたリポジトリをGitHubに移行したい
- その1では、リポジトリ本体とユーザ情報、タグなどの移行を行った
- 今回は、データベースで管理されている Issue を GitBacket からダンプする
その1はこちら。
その3はこちら。
背景
過去記事参照。
GitBucket から Issue を取り出す
アプリケーショントークンの取得
GitBucket は GitHub REST API v3 のサブセット*1を実装しているので、直接 H2 や PostgreSQL の中身を覗かなくてもある程度はなんとかなる。
REST API なので python なり perl なりでスクリプトでサクッとおわらせたい。そのためにまずはアプリケーショントークンを取得する。
- GitBucket にログイン
- Account settings を選択
- Applications を選択
- Generate new token の Token description にテキトーな説明を入れる
- Generate token を選択
するとトークンが表示されるのでメモっておく。
Issue と Pull Request の取得
アプリケーショントークンを使って、http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/issues
に対して、APIをコールしてやれば以下のような JSON で降ってくる。
{ 'number': 2, 'title': 'Issueのタイトル', 'user': { 'login': 'USERNAME', 'email': 'USERNAME@example.com', 'type': 'User', 'site_admin': True, 'created_at': '2018-08-08T12: 51: 17Z', 'id': 0, 'url': 'http://GITBACKET_SERVER_URL/api/v3/users/USERNAME', 'html_url': 'http://GITBACKET_SERVER_URL/USERNAME', 'avatar_url': 'http://GITBACKET_SERVER_URL/USERNAME/_avatar' }, 'assignee': { userと同じ key の集まり (valueは異なる) }, 'labels': [ { 'name': 'enhancement', 'color': '84b6eb', 'url': 'http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/labels/enhancement' } ], 'state': 'closed', 'created_at': '2018-08-13T14:33:25Z', 'updated_at': '2020-10-10T06:34:36Z', 'body': 'Issueのメッセージ本文', 'id': 0, 'assignees': [ { user や assignee 同じ key の集まり (valueは異なる) } ], 'comments_url': 'http://GITBACKET_SERVER_URL/api/v3/repos/USERNAME/REPONAME/issues/2/comments', 'html_url': 'http://GITBACKET_SERVER_URL/USERNAME/REPONAME/issues/2' }
さらに、Issue 内のコメントは、降ってきた comments_url に対してAPIをコールしてやれば、これまた JSON で手に入る。
[ { "id": 3, "user": { "login": "USERNAME", "email": "USERNAME@excample.com", "type": "User", "site_admin": true, "created_at": "2018-08-08T12:51:17Z", "id": 0, "url": "http://GITBACKET_SERVER_URL/api/v3/users/USERNAME", "html_url": "http://GITBACKET_SERVER_URL/USERNAME", "avatar_url": "http://GITBACKET_SERVER_URL/USERNAME/_avatar" }, "body":"Issueのコメント本文" } ]
Pull Request と Issue はAPIのエントリポイントが異なるだけで、全く同じ手順でダンプできる。なので、Issue と Pull Request はメソッドを共通化できる。やっつけだが、概ね以下の通り。
【2020/10/20修正】ちょっとやっつけすぎたので、少しリファクタリング。
import os import requests GITBUCKET_API_BASEURL='http://gitbucket.example.com/api/v3/repos/USERNAME/REPONAME' GITBUCKET_APP_TOKEN='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # GitBucket から issue を取得する def get_issues (base_url, token): headers = {'Authorization': 'token ' + token} issues = [] # issue for issue_type in ('issues', 'pulls'): url = '%s/%s' % (base_url, issue_type) for state in ('open', 'closed'): for page in range(1, 10000): payload = {'state': state, 'page':page} response = requests.get(url, headers=headers, params=payload) new_issues = response.json() if not len(new_issues): break issues.extend(new_issues) issues.sort(key=lambda x: x['number']) # issue comment for issue in issues: response = requests.get(issue['comments_url'], headers=headers) issue['comments'] = response.json() return issues if __name__ == '__main__': issues = get_issues(GITBUCKET_API_BASEURL, GITBUCKET_APP_TOKEN) print(issues)
ハマりポイントとしては2点。
- GitBucket の issues API は GitHub では使える state=all が使えないので、state=openとstate=closedを使って結果を結合しないとダメ。
- またper_page=N も使えず、25個ずつしか取ってこれないので、page=N を順繰りに増やし、空配列しか降ってこなくなるまで取得し続けないとダメ。
これで、issue と Pull Request を一通りぶっこ抜けるようになったので、今度はこれを同じく GitHub API を使って GitHub に突っ込んでいく。
次回予告
- GitBucket からぶっこ抜いた Issue と Issue comment を GitHub に入れていきます。
*1:サブセットなので、いろいろと実装が足りなくてハマりポイント多数。ちゃんとしたドキュメントが欲しい