GitHubでまとめてIssueを閉じたりする場合、数が少ないなら手動でポチポチ行えば良いです。
ただ、Issueが数百ある場合は面倒なので工夫をしたいです。
今回使われなくなった社内のリポジトリをアーカイブする作業があり、その前にIssueを全て閉じる作業を行うためのスクリプトを作成してみました。
アクセストークンの準備
まずスクリプトなどを利用してGitHubの操作を行う場合、アクセストークンを発行する必要があります。
GitHubにアクセス・ログインし、今回は右上の自分のアイコンをクリック -> Settings
-> Developer Settings
-> Personal access tokens
-> Fine-grained tokens
と辿っていきます。
Fine-grained personal access tokens
のページに到達したら、Generate new token
をクリックし、トークンの作成画面にジャンプします。
トークンの作成画面では、以下を記入・変更します。
- Token name
- 用途に適した名前を記入する
- Expiration
- お好みで選択
- Description
- 書きたいことがあれば記入
- Repository access
-
All repositories
かOnly select repositories
にする -
Only select repositories
にした場合は変更対象のリポジトリを選択する
-
- Permissions
- Issuesを
Read and write
にする-
Repository access
の設定がデフォルトのPublic Repositories (read-only)
だと出ないので注意
-
- Issuesを
作成されたアクセストークンは一旦保管しておきます。
gemのインストール
今回はGemfileを利用して2つのgemをインストールしています。
# frozen_string_literal: true
source 'https://rubygems.org'
gem 'dotenv'
gem 'faraday-retry' # インストールしないと警告が出てうるさいので追加
gem 'octokit'
メインは.env
ファイルから環境変数を取得するためのdotenv、GitHubのAPIラッパーであるoctokit.rbです。faraday-retryは後述するプログラムを実行した際、以下のメッセージが出てしまうため素直に従っています。
To use retry middleware with Faraday v2.0+, install `faraday-retry` gem
環境変数の設定
.env
ファイルを作成し、環境変数を埋めていきます。
https://github.com/Umekawa/issue_closer には.env.sampleが存在するのでコピーするのが良いでしょう。
以下は https://github.com/Umekawa/issue_closer のissueを全てクローズする場合の例です。
リポジトリの設定やクエリは適宜変更してください。
ちなみにIssueの取得で使うPER_PAGEは、30がデフォルトなのでそのまま仮置きしています。(参考)
GITHUB_TOKEN=先ほど取得したGitHubのアクセストークン
GITHUB_ID=Umekawa
REPOSITORY_NAME=issue_closer
SEARCH_QUERY='is:issue is:open'
PER_PAGE=30
スクリプトの作成
それでは実際にスクリプトを作成します。
# frozen_string_literal: true
require 'octokit'
require 'dotenv'
Dotenv.load
client = Octokit::Client.new(access_token: ENV['GITHUB_TOKEN'])
per_page = ENV['PER_PAGE'] || 30
search_result = nil
while search_result.nil? || search_result.items.size.positive?
search_result = client.search_issues("repo:#{ENV['GITHUB_ID']}/#{ENV['REPOSITORY_NAME']} #{ENV['SEARCH_QUERY']}",
page: 1, per_page:)
search_result.items.each do |issue|
client.close_issue("#{ENV['GITHUB_ID']}/#{ENV['REPOSITORY_NAME']}", issue.number)
puts "#{issue.title} (Issue ##{issue.number}) has been closed."
sleep 1
end
sleep 1
end
構成としてはすごくシンプルで、以下のようになっています。
- アクセストークンによる認証
- Issueの取得
- 今回の環境変数の例ではクエリが
repo:Umekawa/issue_closer is:issue is:open
)で https://github.com/Umekawa/issue_closer の全てのOpenしているIssueを取得します
- 今回の環境変数の例ではクエリが
- IssueのClose
- リポジトリとIssueの番号(ID)を指定することでcloseすることができるので、第一引数にリポジトリ名、第二引数にissue.numberを引数に入れています
- GitHubのサーバーに負荷をかけすぎないよう、1秒のsleepを挟むようにしています
- Issueの再取得
- 0件になるまでループさせています
- pageが1固定なのは、1ページを全てcloseするので、それまでの2ページ目が1ページ目に変わるためです
このプログラムを実際にPER_PAGE
を変えたりして、https://github.com/Umekawa/issue_closer/ で試した限り、問題なく動作することを確認できました。
まとめ
今回、octokit gemを利用することで簡単にGitHubの操作を行うことができました。
GitHubのAPIラッパーは他の言語でも幅広く提供されているので、GUIだと辛いなという作業がある場合は好きな言語で挑戦してみるのはいかがでしょうか?