GitHub CodeQLの実行時間を20分から3分に劇的改善!〜10年越しのレガシーコード断捨離がもたらしたDXとセキュリティの向上〜

こんにちは。スタメンでCTOしております、ちゃんたく (@tnir / @takuya_stmn) です。

先日7月12日にTUNAGプロダクトは10周年を迎えました。(2026-07-12 14:41 JSTコミット)

2016年7月12日git init

私たちは当社主幹プロダクトであるTUNAGの日々の開発にGitHubをフル活用しており、コードの品質とセキュリティを高く保つための取り組みを継続しています。 その一環として、最近GA(一般提供)されたGitHubのネイティブなコードスキャンツールであるCodeQL-powered analysis for Code Qualityを導入し、高度なコードセキュリティ機能をフル活用しています。そのコア技術となっているCodeQLのおかげで、脆弱性の早期発見が可能になり、より安全なプロダクト開発が実現できるように設計しています。

しかし、CodeQLを運用していく中で、とある大きな「壁」にぶつかりました。 今回は、10年以上の歴史を持つリポジトリに約8年間潜んでいたレガシーコードを発見・分離し、実行時間を平均20分から3分へと短縮した取り組みをご紹介します。

課題:長すぎるCodeQLの実行時間(平均20分)とセキュリティ上のリスク

CodeQLは非常に強力なツールですが、私たちのメインリポジトリで実行すると、完了するまでに平均で約20分もかかってしまっていました。 20分という時間は、CI/CDパイプラインにおいて致命的です。Pull Requestを作成してから結果が出るまで長時間待たされるため、開発者のフィードバックループが遅延し、開発体験(DX)の著しい低下を招いていました。 さらに重大な問題として、平均20分も時間がかかると、Pull RequestにおけるCIステータスのクオリティゲート(必須ワークフロー)として組み込むことができないという点がありました。マージのたびに20分待たせる運用は現実的ではなかったためです。 その結果、高度なコードセキュリティ機能を導入したものの、CI/CDプロセス自体はセキュリティ対策として脆弱な状態(危険なコードのマージをCIでブロックできない状態)のまま運用せざるを得ないという本末転倒な状況に陥っていました。 私たちのリポジトリは10年以上にわたって運用されてきた歴史があり、コードベースの肥大化は認識していましたが、セキュリティクオリティゲートを正常に機能させるためにも、この20分という実行時間は絶対に解決すべき課題でした。

Datadog CI/CD Optimization (CI/CD Explorer) を用いた GitHub Code Quality (CodeQLパート) の実行時間分析

原因の特定:導入者は不在…しかし「Gitの歴史」が答えを教えてくれた

なぜこれほどまでに時間がかかっているのか、解析のログや対象ファイルを詳細に調査しました。 しかし、調査対象となったコードは、現在在籍しているエンジニアやマネージャーの誰も背景を知らないブラックボックスと化していました。大昔に導入されたものであり、当時の関係者はすでに社内に一人も残っていなかったためです。 ここで力を発揮したのが、すべての変更履歴を正確に記録し続けていたGitでした。 Gitのコミット履歴やそのblameを遡って調査した結果、約8年前にサードパーティーから購入し、リポジトリ内に配備された「管理画面用のUIライブラリ」が原因であることが判明しました。一般的な社内エンジニアが実装したJSライブラリやビジネスロジックではなく、静的ファイルとしてリポジトリ内に鎮座し続けていたベンダー製のコードでした。 CodeQLは律儀にこの約8年間放置されていた外部ライブラリの隅々まで脆弱性スキャンを行っていました。私たちが日常的に手を加えることのない古いベンダーコードの解析に、CIの貴重な時間を大量に奪われていました。

解決策:235 MBに及ぶコードの切り出しと別リポジトリでの分離運用

原因が特定できれば、やるべき方針は明確でした。 今回特定されたサードパーティー製ライブラリは、コードの分量が約100 MBにも及ぶ非常に巨大なものでした。これほど大規模なコードを、メインプロダクトの単一リポジトリ内で維持し続ける必要性はありません。 あえてモノリシックに維持するのではなく、メインプロダクトとは明確に「ライフサイクルの異なるソフトウェア」として、意図的に別リポジトリへ切り出して独立管理するのが適切であると判断しました。 そこで、メインリポジトリからはこの100 MBのUIライブラリを完全に削除し、別リポジトリとして独立させて異なるライフサイクルで管理する施策を実行しました。

驚きの結果とセキュリティクオリティゲートの実現

この235 MBのレガシーコードをメインリポジトリから削除した結果、CodeQLの実行時間は平均20分から「3分」へと劇的に短縮されました! 実行時間が3分になったことで、CodeQLをPull Requestの必須クオリティゲートとして正式に設定可能となり、セキュリティリスクを抱えたコードがマージされるのをCI上で確実にブロックできるようになりました。 開発者のフィードバックループ(DX)が飛躍的に向上しただけでなく、CI/CDパイプライン全体のセキュリティ強度を真の意味で高めることができました。

ビルドパイプライン

ビルドパイプラインは創業時の2016年7月よりRuby on Railsに付属のSprocketsベースのアセットビルドを利用していました。7年強続いたアセットパイプラインを2023年秋に見直していたため、Yarn+esbuildによる実装に修正するプロジェクトがあり、そこから3年ほどはアプリケーションレイヤーのフロントエンドアセットパイプラインを問題なく維持運用していました。

なお、ベースとなるサードパーティー製ライブラリはgulpが設定されていましたが、当該プロダクトへの導入時点よりwebpackでのビルドとして開発されていました。この点はフロントエンドパイプラインをモダナイズする上ではとても助かる点でした。

Bootstrap 4ベースのUIライブラリ

今回切り出した「サードパーティー製ライブラリ」はBootstrap 4.0.0 (alpha) ベースであり、かなりレガシーでした。筆者自身は5年以上前からBootstrap 5.0、そして、最新の5.3に関わるまで1ユーザーでもあるものの、Tailwind CSS v4.3(執筆時の最新バージョン)ベースに切り替えるプロジェクトを未着手のまま温めている状況です。

当該ページ群を使うユーザーはTUNAG全体の大規模なユーザーベースと比べると少ないのですが、いつかはやらなくてはならないタスクだと認識しており、LLMを使って一気に対処してくれるエンジニアを継続募集しています。

読者の皆様へのTakeaway(持ち帰り知識)

今回の私たちの経験から、皆さんの開発現場でも活かせるポイントをまとめました。

  1. CI実行時間の短縮は「セキュリティクオリティゲート化」の絶対条件 セキュリティスキャンツール(SAST)を導入しても、実行時間が長いとPRの必須チェックに設定できず、セキュリティプロセスが形骸化・脆弱化してしまいます。「スキャンを高速化し、必須クオリティゲートとしてCIに組み込むこと」こそが、堅牢なCI/CDセキュリティを実現する鍵となります。
  2. ライフサイクルが異なる巨大コードは別リポジトリへ分離する 200 MBを大幅に超える巨大なサードパーティー製ライブラリをメインリポジトリに含め続けると、静的解析やビルド時間のボトルネックになります。プロダクト本体とライフサイクルが異なるソフトウェアは、あえて同一リポジトリで維持せず、別リポジトリとして分離・運用することがアーキテクチャ上も有効です。
  3. Gitの履歴は属人化したナレッジを救う最強のドキュメント 当時の担当者が一人も残っていない状況でも、Gitの履歴がしっかり残っていれば「いつ・なぜ・何が導入されたのか」を正確に突き止めることができます。歴史あるリポジトリの調査において、Gitのログを辿る重要性を再確認しました。

おわりに

CodeQL-powered analysis for Code Qualityは、スキャン対象を最適化しプロジェクトの構成を適切に保つことで、本来の優れたパフォーマンスを発揮してくれます。 10年以上の歴史があるリポジトリでも、適切な棚卸しとアーキテクチャの見直しを行えば、DXとセキュリティの両立は十分に可能です。もし「CIが遅くて必須化できない」とお悩みの場合は、リポジトリ内に長年鎮座している外部コードや分離可能なモジュールがないか、ぜひ探してみてください!

また、われわれと一緒にレガシーアプリケーションの継続的モダナイズをしたいエンジニアを募集しています。詳しくは当社採用サイトをご覧ください。