🏓

GitHubのProjectsのDraftIssueを一括でIssueに変換するツール作った

2024/09/06に公開

作ったもの

GitHubのProjectsのDraftIssueをまとめてIssueに変換するCLIツール作ってみました。Ruby製です。

https://rubygems.org/gems/gh_draft_issues_converter

https://github.com/kuredev/gh_draft_issues_converter

実行すると、これが

こうなります。(DraftIssueがIssueになる)

使い方

Rubyが実行できる環境が必要です。(開発時は3.2系で動作確認)

インストール

% gem install gh_draft_issues_converter

事前準備

  • 変更元DraftIssueのあるProjectsの番号 ( -p で指定 )
  • 変更先のIssueのリポジトリ名(owner/repositoy)( -r で指定)
  • GitHub のPersonal Token( GITHUB_KEY に登録しておくこと)

コマンド例

% gh_draft_issues_converter -p 1 -r kuredev/gh-draft-issues-converter   

主な制約

  • カスタムフィールドでは単一選択の物のみ移行されます
  • 標準のフィールドは、assignのみ移行されます
  • Projectsとリポジトリは同じオーナーの物が対象となります

作った動機

業務で、開発案件のタスク管理をGitHubのProjectsを使用しており、テンプレート機能を用いています。テンプレート内のアイテムはDraftIssueとして管理されるため、実プロジェクトに展開したとき、大量のDraftIssueが生成されることとなります。実際のタスクとしてはIssueで管理するため、DraftIssueからIssueへの変換が必要でした。

Webからは1個1個コンバートする機能はあるのですが、まとめてコンバートする機能が見当たらなかったので、勉強がてら作ってみました。

技術的なメモ

GitHubではREST APIとGraphQL APIが提供されていますが、GitHubのProjectsはGraphQLからしか操作できないようだったので、今回GraphQLを全面的に用いました。

APIでは「コンバートする」という操作が無いようだったので、以下の流れを実装しました。

  • DraftIssueのデータを取得
  • Issueを作成
  • DraftIssueを削除

今回もっともハマったのはフィールドオブジェクトのID周りです。フィールドとはアイテムの属性値です。コンバート処理ではアイテムごとのDraftIssueのフィールド値を取得した後、Issueにも同じフィールド値を設定する必要があります。
https://docs.github.com/ja/graphql/reference/objects#projectv2itemfieldsingleselectvalue

上記リンクをみると分かるように属性値には「ID」と「optionId」の2つの識別子のようなものがあります。説明を読んでもいまいち分からなかったのですが、どうやら前者は今のアイテムに紐づいている状態としてのID、optionIdはこのフィールド値そのもののIDということになるようです。
したがって、作成後のIssueにフィールド値を紐づけるときは後者のIDを指定する必要があります。

ちなみに後者のフィールド値自体のIDは以下のフィールドのオブジェクトからも参照できます。
https://docs.github.com/ja/graphql/reference/objects#projectv2singleselectfield

その他備考

以下のコメントを参考に、レートリミットを避けるために、CreateIssueAPIの実行間隔として、デフォルトで25秒間のインターバルを設けています。
https://github.com/cli/cli/issues/4801#issuecomment-1431812916

本ツール内では、この間隔は -i オプションで変更可能としています。

感想

最初はGraphQLの指定方法が分からず、ChatGPTと公式ドキュメントをにらめっこしながら調整していきましたが、いくつもサンプルのクエリを書いていくうちに徐々に書き方のコツが掴めて来た気がします。書き方は少しむずかしいものの、オブジェクト型が定義されているのがRESTと比べて表現力が大きいので、面白いところだなと思いました。

Discussion