実現するCLI兼Node.jsクライアントライブラリを作りました(PR/projectsの操作も実装中)
https://www.npmjs.com/package/issue-ctl
使い方
https://github.com/darai0512/issue-ctl をご覧ください
CLI
$issue-ctl migrate
posted old issue#1 to new issue#4
posted old issue#2 to new issue#5
posted old issue#3 to new issue#6
in Node.js
slackやjiraなどとbot経由で連携するのに便利かと
const {issue} = require('issue-ctl');
const main = async () => {
const issues = await issue.get('api.github.com', 'org/repo', 'username:passwd');
// ex, issues.title = prefix + issues.title + postfix;
await issue.post('your.enterprise.url', 'org/repo', 'oauth2token', issues);
};
// 申し訳ありませんがUnhandledPromiseRejectionWarningが発生します(後述)
// 現在リファクタリング中ですが、エラーハンドリングされたい方は下記を記述ください
process.on('unhandledRejection', (reason, pos) => {
console.log('at:', pos, 'reason:', reason);
});
main().catch((err) => console.error(err));
できること
- 特定のリポジトリからissue(PRを除く)を全て取得する
- 紐付くコメント、ラベル、マイルストーン、アサイン者情報も取得
- 特定のリポジトリへissueを全てPOSTする
- 紐付くコメント(順番保持)、ラベル、マイルストーン、アサイン者情報も登録
- closeしたissueなら登録後closeされる
- 新規POSTのため、移行前後でissue番号は異なる
やりたかったこと
- GitHub Enterprise(v2.11)からGitHubへ、コードの公開にあたりissueを移行したい
- その際、一般に公開できない部分のコードはラップするため、直書きされていた過去のcommit情報は移行させたくない
- 移行先は既に運用中で、新しいissueなどが作られ続けている
- リポジトリのマイグレーションはGitHubにAPIで用意されているが、commit履歴も移行されてしまうし、移行先が初期化されるので使えない
- 移行時に、従来のissueを指定フォーマット(スクラムのユーザーストーリー)に置換したい
- ex,
FEチームとして、${old_title}したい。なぜなら、業務効率化に繋がるから。
- Get時にファイルにJSONで落とすので、必要に応じて置換し、Postできるよう実装
- ex,
調査
-
https://gist.github.com/agarny/5541773
- コピー先のラベルとマイルストーンは全削除されるため、運用中のリポジトリには使用できない
-
https://qiita.com/koic/items/800bbc03281558ab93db
- 公式のマイグレーションだと、移行先のデータが全て消え、commit履歴も残ってしまう
-
https://www.npmjs.com/package/gh-issues-cli
- 認証しないとAPI叩ける回数に制限食らうよ、というのは大事な気づき
-
https://github.com/github/hub
- おそらくやりたい機能はないはず
Tips
内部実装
- Node.jsのcore APIのみで実装。ブラウザJSでは動作しません。
- getではリポジトリ内のissueとcommentを100件ずつpagingしながら全件取得します。commentの取得はissue単位ではなくリポジトリ単位で、後から紐付けています。API実行回数は最小のはずですが、利用回数制限がかかっている場合は注意ください。
- postは1秒ごとに1 issueずつ
- 紐付くコメント・closedの場合はその操作も含めて
Promise のエラーハンドリング漏れ
上述の通り、一部async/awaitでcatch漏れがあり、下記エラーが発生することがあります。
(node:111) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ***
(node:111) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
このエラーログだけではコードのどの部分でハンドリングが漏れているのかわかりません。
発生箇所特定のためには、上述のようにunhandledRejection
イベントを登録ください。
これでPromiseの包括的なエラーハンドリングが可能ですが、公式ではこれに頼ってエラーハンドリングを放棄することは推奨していません。
(理由は内部実装を見てみるとわかります、機会があれば記事化します)
これでいつも通りのスタックトレースが見れるので、原因のPromiseでcatch処理を入れれば特定可能です。よければPRお待ちしております。