大規模リポジトリの GitHub Actions ワークフロー検索性を改善する Chrome 拡張機能の開発

こんにちは!カイポケリニューアルの開発推進チームでエンジニアをしている @_kimuson です。

カイポケリニューアルのプロジェクトでは、CI/CD ツールとして GitHub Actions を主に利用しています。モノレポを採用していることから、ワークフローファイル数が膨大になっており、手動実行したいワークフローの検索性が課題となっていました。本記事では、この課題を Chrome 拡張機能で解決した方法について紹介します。

問題

GitHub Actions には、ワークフローを手動を実行する機能が提供されていて、わかりやすい例だと deploy などのワークフローでよく利用します。通常、これらのワークフローは以下の流れで実行します。

  1. GitHub Actions のページ(https://github.com/<owner>/<repo>/actions)に遷移する
  2. ワークフローの一覧から手動実行したいワークフローのリンクをクリック
  3. ワークフロー個別のページに遷移し、「run workflow」を押す

しかし、ワークフローの一覧については「初期表示では 10 件のワークフローしか表示されず、Show more workflows ボタンを押すことで 30 件ずつ追加表示される」という仕組み上、workflow 数が多くなるリポジトリでは目的のワークフローを見つけることが非常に困難になります。

実際、モノレポの方針を採用し 150 件以上のワークフローが存在するカイポケリニューアルのプロジェクトでは、目的のワークフローを見つけるには 5 回の追加読み込み+ページ内検索が必要です。

GitHub はこの問題に対してピン留め機能を提供していますが、チーム共有型で上限が 5 件という制限があり、カイポケリニューアルの規模では十分な解決策とはなりませんでした。

Chrome 拡張機能 による解決

これらの課題を解決するため、Chrome 拡張機能を開発し、GitHub Actions ページに新しい UI を追加しました。

主な機能は以下の 2 つです:

  1. ワークフローのインクリメンタルサーチ機能
  2. 個人単位でのピン留め機能

GitHub の REST API ではなく internal な API を利用して情報を取得することで、Personal Access Token(PAT)の発行なしで利用できる設計で実装しました。

ワークフロー検索機能

本拡張機能の核となる機能はワークフローの検索機能です。

検索機能は以下の方針で実装しています:

  • GitHub 上で .github/workflows ディレクトリのファイルツリーを閲覧するページで使われている API を利用して、ワークフローファイルの一覧を取得する
  • この一覧に対してインクリメンタルサーチを実装する

これにより、ワークフロー名の一部分を入力することで、目当てのワークフローを即座に見つけられるようになりました!

ただし、正規の workflow 一覧を取得しているわけではないので

  • Dependabot Alerts のようなワークフローファイルが存在しないものは検索できない
  • (把握できていませんが) 何らかのルールで workflow の出力が制御されている場合、追従できない

といった制約があります。 しかし、実際の利用シーンでは概ね困らないだろうなということで許容しています。

個人用ピン留め機能

検索機能に加えて、個人単位でのピン留め機能も実装しました。この機能では、拡張機能の検索結果から特定のワークフローをピン留めすることができます。

チーム全体でよく使用するワークフローは概ね共通していますが、カイポケリニューアルのような複数チームが関わるプロジェクトでは、各メンバーが頻繁に利用するワークフローは異なります。個人単位でのピン留め機能により、このような個別のニーズにも対応できるようになりました。

技術的に気をつけたポイント

UI のテーマを GitHub に揃える

私は GitHub のダークテーマを普段使いしているのですが、PoC を作って他の開発者に試してみてもらったところ、デフォルトテーマでは文字が見えないという問題が発生しました。

拡張機能自体でテーマを用意すると煩雑になるので、GitHub のスタイル設定を活用する方針を選択しました。具体的には、以下のような変数を用意してスタイルの適用に利用しています。

export const colors = {
  textColor: "var(--fgColor-default)",
  backgroundColor: "var(--bgColor-default, var(--color-canvas-default))",
  buttonBackgroundColor:
    "var(--button-default-bgColor-rest, var(--color-btn-bg))",
  buttonBorderColor:
    "var(--button-default-borderColor-rest, var(--color-btn-border))",
} as const

それぞれの値は GitHub の UI 上で実際に利用されている CSS 変数です。 このアプローチにより、GitHub のテーマ設定を自動的に反映し、統合されても違和感の少ない UI を実現しました。

読み込みは GitHub 全体で行い、MutationObserver でページ遷移を検知する

この拡張機能の読み込み設定は以下のようになっています:

{
  "content_scripts": [
    {
      "matches": ["https://github.com/*"],
      "js": ["src/content/index.ts"]
    }
  ]
}

当初は https://github.com/*/*/actions のパターンのみを対象としていましたが、GitHub の別のページにアクセスしてから遷移すると発火しないので全体に適用する今の形に変更しました。

ただし、別の GitHub のページで拡張機能を読み込むと、読み込み時に DOM を初期化できないので工夫が必要です。MutationObserver を利用してページ遷移を検知するようにしました。

let oldUrl = ''

const observer = new MutationObserver(() => {
  if (oldUrl !== window.location.href) {
    oldUrl = window.location.href
    window.dispatchEvent(new CustomEvent('urlChange'))
  }
})

export const observeUrlChange = () => {
  observer.observe(document.body, {
    subtree: true,
    childList: true,
    attributes: true,
    characterData: true,
  })
}
observeUrlChange()

window.addEventListener('urlChange', () => {
  // DOM の初期化処理
  // https://github.con/<owner>/<repo>/actions/* の形式なら初期化する
})

これにより、Actions ページへの遷移を検知したタイミングで React コンポーネントをマウントできるようにしています。

SPA 的な遷移を行うサイトに UI を拡張機能で追加する場合には、こういった対応をする必要がありそうです。

まとめ

本記事では、大規模リポジトリにおける GitHub Actions ワークフローの検索性の課題を、Chrome 拡張機能で解決した事例を紹介しました!

  • GitHub の内部ファイルツリーAPI等を利用することで、実装コストを抑えてかつ 別途 PAT を発行せずに利用できる
  • GitHub のテーマの仕組みをそのまま利用することで、GitHub に調和したUIを実現

という感じで、割と使いやすい Chrome 拡張機能になったんじゃないかなと思います。

この拡張機能は「github-actions-search」として公開しています。

Chrome Web Store: https://chromewebstore.google.com/detail/github-actions-search/dpcfpkccefabmlfokoilfejeinconhjm?authuser=1&hl=ja

リポジトリ: https://github.com/d-kimuson/github-actions-search

利用もコントリビューションも歓迎なので、同様の課題を持つ方はぜひご利用いただければと思います!