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 allJSONで出力する
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
urlJSONで出力する場合は、出力するフィールドを指定する必要があるようです。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.csvjqコマンドの調査(2023年5月13日追加)
jqオプションに指定する整形・加工方法を調べるのにChatGPTを使いました。そのときの調査過程も含めて記事にしました。

まとめ
GitHub CLIを使って、イシュー取得→JSON→CSV という流れでGitHubのイシューをCSVに書き出すことができました。筆者が今回移行したかったリポジトリはたまたまイシューの個数が少なかったので、この記事に書いた方法で問題ありませんでした。
しかし、イシューの個数がgh issue listの1回に書き出せる個数を超えてしまう場合には、複数回に分割する必要があるでしょう。
また、コメントは複数な上に入れ子になるのでCSVに変換するのは無理があります。コメントも書き出しておきたい場合にはJSONで書き出すのが良いと思います。











