🧩

React × Viteでコードレビュー効率化のためのChrome拡張機能を作った話

に公開

はじめに

こんにちは。
今回は、自身がレビュワーに設定されているPRを一覧で確認することができるChrome拡張機能を開発したので、その内容についてお話ししたいと思います。
また、この拡張機能はGitHubでのPRレビューを効率化したいという思いがあり、業務では拡張機能の開発をしていますが、個人では開発したことがなかったので良い機会だと思い、成果物を Chrome Web Store に公開するところまで行いました。

拡張機能は以下のURLからインストールできますので、ぜひ試していただけると幸いです。
https://chromewebstore.google.com/detail/github-pr-review-checker/cmkicagmppjdncgcpkkobdkooggleknf?authuser=0&hl=ja

エンジニアは日常業務において毎日のようにコードレビューを行なっていると思いますが、
以下のような課題があり、どうにか解決できないかと考えていました。

  • レビューの見逃しでレビューが遅れてしまう
  • レビュー待ちのPRを確認するのが手間
  • 承認状況や作成からの経過時間を視覚的に確認したい

そこで、Chrome拡張機能として、自分がレビュアーに設定されているPRを簡単に一覧表示し、バッジで件数を常時可視化できるようにしました。
それによって、レビューの見逃しが少なくなり、効率的にレビューを行うことができるのではないかと考えました。

技術スタック

フロントエンド

  • React
  • TypeScript
  • Vite

Chrome拡張機能API

  • chrome.storage API(個人アクセストークンの保存)
  • chrome.action API(バッジ表示)
  • chrome.alarms API(定期的な更新処理)
  • chrome.idle API(ブラウザの状態監視)
  • chrome.runtime API(メッセージ通信)

外部API

  • GitHub GraphQL API(PR 情報の取得)

主な機能

個人アクセストークン設定

拡張機能の設定画面から、個人アクセストークンを設定することができるようにしました。
個人アクセストークンは、GitHubの設定画面から作成することができます。
リポジトリの情報にアクセスするため、repoスコープのチェックが入っている必要があります。

個人アクセストークン作成方法

  1. GitHubにログインし、右上のプロフィールアイコンをクリック
  2. メニューから「Settings」を選択
  3. 左サイドバーの一番下にある「Developer settings」をクリック
  4. 「Personal access tokens」→「Tokens (classic)」を選択
  5. 「Generate new token」→「Generate new token (classic)」をクリック
  6. トークンの説明(Note)に任意の名前(例: "PR Review Checker")を入力
  7. 有効期限(Expiration)を設定
  8. スコープの選択で「repo」にチェックを入れます(必須)
    • これはプライベートリポジトリを含むリポジトリ情報へのアクセス権限です
  9. 「Generate token」ボタンをクリック
  10. 生成されたトークンをコピー
    この画面を閉じると二度とトークンは表示されませんのでご注意ください
  11. 拡張機能の設定画面を開き、コピーしたトークンを貼り付けて保存

レビュー依頼されているPRの一覧表示

レビュー待ちのPRを一覧で表示する機能です。
GitHub GraphQL APIを利用して、レビューが依頼されているPRをモーダルに一覧で表示して直接リンクでアクセスできるようにしました。

一覧表示しているPR情報には以下のような詳細情報を含めています。

  • PRのタイトル
  • リポジトリ名
  • PR作成者
  • PR作成日時・更新日時
  • コメント数
  • 変更量(追加行数、削除行数、変更ファイル数)
  • 各レビュワーのレビュー状態
  • PR作成からの経過時間

具体的には、PRの情報を取得するために、GraphQL APIを使用しています。単一のクエリでレビュー依頼されているPRの詳細情報を取得しています。

query GetPullRequestsForReview {
  search(query: "review-requested:@me is:open is:pr", type: ISSUE, first: 100) {
    issueCount
    edges {
      node {
        ... on PullRequest {
          id
          title
          url
          number
          createdAt
          updatedAt
          state
          repository {
            nameWithOwner
            url
          }
          author {
            login
            avatarUrl
          }
          comments {
            totalCount
          }
          additions
          deletions
          changedFiles
          reviews(last: 100) {
            nodes {
              author {
                login
              }
              state
              submittedAt
            }
          }
        }
      }
    }
  }
}

GraphQL APIには、1時間あたりのリクエスト数のレート制限があります。
この拡張機能では、個人アクセストークンの設定を必須とし、基本クエリ制限は5,000ポイント毎時(実際のクエリによってポイント消費は変動)となっています。
https://docs.github.com/ja/graphql/overview/rate-limits-and-node-limits-for-the-graphql-api

フィルタリング機能

PR数が多くなった場合に、必要なPRをすぐに見つけるためにフィルタリング機能を実装しました。
とくに経過時間に関してはPRが作成されてから時間が経ってしまっているPRが視覚的に分かりやすくなり、見逃しているPRを早めに発見できるようになりました。

  • リポジトリ単位のフィルタリング: 特定のプロジェクトのPRだけを表示
  • 経過時間によるフィルタリング: 1日、3日、7日以上経過したPRを表示
  • コメント有無によるフィルタリング: コメントがあるPR、またはコメントがないPRだけを表示
  • 変更ファイル数によるフィルタリング: 変更量が少ないPRを表示
  • 承認状態によるフィルタリング: 承認済みや未承認のPRを区別して表示

ソート機能

PRを以下の基準でソートすることができます。
変更量でのソートは、短時間でレビュー可能な小さな変更を先にチェックしたいときに使用できると思い追加しました。

  • 更新日(新しい順/古い順)
  • 作成日(新しい順/古い順)
  • コメント数(多い順/少ない順)
  • 変更量(多い順/少ない順)

拡張機能のアイコンにPR件数をバッジで表示

拡張機能のアイコンに、レビュー待ちのPRの件数をバッジで表示します。
この機能は、PRの件数を常に確認できるため、レビューを忘れてしまうことが少なくなると思い実装しました。
また、PRの件数が0件の場合はバッジは表示されないようにしています。

バッジの実装詳細

バッジの実装は、chrome.action.setBadgeText APIを使用して、拡張機能のアイコンにバッジを表示することができます。

// PRの件数を取得
const pullRequestsCount = pullRequests.length;

// バッジのテキストを設定
const badgeText = pullRequestsCount > 0 ? String(pullRequestsCount) : '';
chrome.action.setBadgeText({ text: badgeText });

// バッジの背景色を設定
chrome.action.setBadgeBackgroundColor({ color: '#4285F4' });

// バッジのテキストカラーを白色に設定
chrome.action.setBadgeTextColor({ color: '#FFFFFF' });

https://developer.chrome.com/docs/extensions/reference/api/action?hl=ja#method-setBadgeText

バッジ更新タイミング

  • 拡張機能のアイコンをクリックしたとき
    chrome.runtime.sendMessage APIを使用

https://developer.chrome.com/docs/extensions/reference/api/runtime?hl=ja#method-sendMessage

拡張機能のアイコンをクリックしたときに、chrome.runtime.sendMessage APIを使用して、バックグラウンドスクリプトにメッセージを送信し、PRの件数を更新しています。

// App.tsx
if (chrome.runtime?.id) chrome.runtime.sendMessage({ action: 'popupOpened' })

// background.ts
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
  if (message.action === 'popupOpened') {
    updateBadge();
    sendResponse({ success: true });
  }
  return true;
});
  • 定期的に自動更新
    chrome.alarms APIを使用

https://developer.chrome.com/docs/extensions/reference/api/alarms?hl=ja

アラームを作成し、定期的にPRの件数を更新するようにしています。

// background.ts
chrome.alarms.onAlarm.addListener((alarm) => {
  if (alarm.name === 'updateBadge') updateBadge();
});

// アラームを作成
chrome.alarms.create('updateBadge', {
  periodInMinutes: 1
});
  • Chromeがアイドル状態、またはロック状態から復帰したとき
    chrome.idle APIを使用

https://developer.chrome.com/docs/extensions/reference/api/idle?hl=ja

状態がactiveに変化したときに、PRの件数を更新するようにしています。

// background.ts
chrome.idle.onStateChanged.addListener((state) => {
  if (state === 'active') updateBadge();
});
  1. active: ユーザーがブラウザを操作中の状態
  2. idle: 一定時間ユーザー操作がない状態(デフォルトは60秒)
  3. locked: ユーザーがブラウザを操作していない状態で、ロック画面が表示されている状態

導入手順

  1. 拡張機能をブラウザにインストール
  2. 設定画面から個人アクセストークンを設定
  3. 拡張機能のアイコンをクリックして起動

まとめ

まだこの拡張機能を開発してから1週間ほどしか使用していませんが、レビュー待ちのPRを確認する手間が減り、レビューの見逃しが少なくなったと感じています。
また、業務以外での拡張機能開発は初めてでしたが、idlealarmsなどさまざまなAPIがあることや、Chrome Web Storeへの公開までの流れを学ぶことができました。
フィードバックをもとに機能追加や改善なども行なっていけたらと思っています。

GitHubで編集を提案

Discussion