GitHubのイシューを他のイシュー管理システムに取り込みたいときには、GitHub CLIを使ってイシューをファイルに書き出し、そのファイルを別のイシュー管理システムで読み込みます。
筆者はJIRAに取り込みたいと思い、JIRAにはどのような取り込み方法があるか確認すると、CSVファイルを読み込むのが最も簡単そうに思いました。そこで、GitHubのイシューをCSVファイルに書き出すことにしました。
この記事はそのときに行ったCSVファイルへの書き出し方法と、そこに辿り着くまでの試行錯誤を共有します。
この記事で紹介している方法を実行するには、先にGitHub CLIをインストールする必要があります。GitHub CLIのインストール方法について次の記事をご覧ください。
イシューはリポジトリ単位である
JIRAのようなイシュー管理専用のシステムとは異なり、GitHubのイシューはリポジトリ単位になっています。そのため、書き出すときもリポジトリ毎に作業します。
リポジトリをクローンする
書き出すイシューを持ったリポジトリをクローンします。クローン時に特別なオプションなどは不要で通常と同じようにクローンします。
% gh repo clone ExampleUser/ExampleRepo
クローンが完了したら、リポジトリのディレクトリに入ります。
% cd ExampleRepo
イシューを書き出す
イシューを書き出すには、GitHub CLIを使用してイシューを取得します。筆者はイシューの書き出しは初めてでしたので色々試行錯誤しました。今回の記事では「基礎から学ぶARKit」という私の著書のリポジトリのイシューを例に行っています。
イシューを一括取得する
イシューをまとめて一括で取得するには、gh issue list
を実行すれば良いようです。まずは実行してみました。
% gh issue list
Showing 1 of 1 open issue in akirark/LearnARKit
#34 読者質問への回答を行う about 3 minutes ago
状態を指定する
確かにイシューを取得できたのですが、件数が少ないです。というよりもオープン状態のイシューしか出力されていません。gh issue list
のオプションを調べるとstate
オプションで出力するイシューの状態を指定できることがわかりました。
使用できる値は以下の3つです。
- open : オープン状態のイシューのみ
- closed : クローズ済みのイシューのみ
- all : どちらの状態のイシューも出力する
CSVファイルに書き出すときは、オープン状態のイシューとクローズ済みのイシューを別ファイルに書き出したいので、open
やclosed
を使用することになりますが、まずはシェルに表示したいのでall
を使いました。
% gh issue list --state all
Showing 26 of 26 issues in akirark/LearnARKit that match your search
#34 読者質問への回答を行う about 10 minutes ago
#32 CHAPTER01/00_Assets/Chairフォルダを... bug about 5 months ago
...
このリポジトリはイシューの数はそもそも少ないのですが、状態に関わらず出力されました。
件数を指定する
このリポジトリはイシューの個数が少ないので指定する必要がないのですが、大きなリポジトリではlimit
オプションで出力最大数を指定しないと30件しか出力されません。例えば、次のように指定すると最大1000件まで出力されます。
% gh issue list --limit 1000 --state all
JSONで出力する
CSVファイルに書き出す前に、gh
からイシューをJSONで出力するようにします。JSONで出力するにはjson
オプションを使用します。
% gh issue list --limit 1000 --state all --json
実行すると、次のようにエラーが表示されてしまいました。
Specify one or more comma-separated fields for `--json`:
assignees
author
body
closed
closedAt
comments
createdAt
id
labels
milestone
number
projectCards
projectItems
reactionGroups
state
title
updatedAt
url
JSONで出力する場合は、出力するフィールドを指定する必要があるようです。CSVに含めたい情報を書き出せば良いので、筆者は以下のフィールドを書き出すことにしました。
- number : イシューID
- title : タイトル
- body : 説明
- state : 状態
- createdAt : 作成日時
- updatedAt : 更新日時
- milestone : マイルストーン
次のように実行します。
% gh issue list --limit 1000 --state all --json 'number,title,body,state,createdAt,updatedAt,milestone'
[
{
"body": "読者質問があったので回答する。\r\nOSのバージョンが上がった影響があった様子である。\r\n",
"createdAt": "2023-05-12T13:23:49Z",
"milestone": {
"number": 1,
"title": "support_revision_1",
"description": "",
"dueOn": null
},
"number": 34,
"state": "OPEN",
"title": "読者質問への回答を行う",
"updatedAt": "2023-05-12T13:51:16Z"
},
...
JSONでイシューが出力されました。
CSVに加工する
gh
はjq
オプションでJSONを加工できます。JQはJSONの加工・整形ツールでgh
にjq
に使用可能な加工・整形方法を指定すると、指定された方法で加工・整形した結果を出力します。
これを使って、JSONをCSVに変換します。CSVに変換するコードは次の通りです。
map([.number, .state, .createdAt, .updatedAt, .milestone.title, .title, .body] | @csv) | join("\n")
これをgh
にjq
オプションで指定します。
% gh issue list --limit 1000 --state all --json 'number,title,body,state,createdAt,updatedAt,milestone' --jq 'map([.number, .state, .createdAt, .updatedAt, .milestone.title, .title, .body] | @csv) | join("\n")'
34,"OPEN","2023-05-12T13:23:49Z","2023-05-12T13:51:16Z","support_revision_1","読者質問への回答を行う","読者質問があったので回答する。
OSのバージョンが上がった影響があった様子である。
"
...
後はシェルではなく、ファイルに保存するようにリダイレクトします。JIRAに取り込むときに便利なように状態がopen
とclosed
をそれぞれ別々のファイルに書き出すようにしました。
% gh issue list --limit 1000 --state open --json 'number,title,body,state,createdAt,updatedAt,milestone' --jq 'map([.number, .state, .createdAt, .updatedAt, .milestone.title, .title, .body] | @csv) | join("\n")' > issues_open.csv
% gh issue list --limit 1000 --state closed --json 'number,title,body,state,createdAt,updatedAt,milestone' --jq 'map([.number, .state, .createdAt, .updatedAt, .milestone.title, .title, .body] | @csv) | join("\n")' > issues_closed.csv
jqコマンドの調査(2023年5月13日追加)
jq
オプションに指定する整形・加工方法を調べるのにChatGPTを使いました。そのときの調査過程も含めて記事にしました。
まとめ
GitHub CLIを使って、イシュー取得→JSON→CSV という流れでGitHubのイシューをCSVに書き出すことができました。筆者が今回移行したかったリポジトリはたまたまイシューの個数が少なかったので、この記事に書いた方法で問題ありませんでした。
しかし、イシューの個数がgh issue list
の1回に書き出せる個数を超えてしまう場合には、複数回に分割する必要があるでしょう。
また、コメントは複数な上に入れ子になるのでCSVに変換するのは無理があります。コメントも書き出しておきたい場合にはJSONで書き出すのが良いと思います。