3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

coverband に「時系列」という観点を追加して、AI と繋いだ

3
Last updated at Posted at 2026-03-16

Coverband に「時系列」という観点を追加して、AI と繋いだ

私たち GLOBIS DevEx チームは、日頃から Claude Code を Workflow に取り入れ、開発体験向上を行っている。
私は Coverband のデータをもとに不要コードを定期的に提案する仕組み(ゴール: PR 自動作成)を模索していた。しかし、Coverband が教えてくれるのは「今この瞬間のスナップショット」だけ。いつ実行されたのか本当に使われていないのか を判断するには、情報が足りなかった。

Datadog APM, Logging を利用している為、最初は Datadog MCP を利用して解析を試みたが、保存期間の問題で挫折した。

image.png

課題の深掘り:Coverband だけでは分からなかったこと

Coverband は幅広く利用されている、素晴らしいツール。
本番環境で実際に実行されたコード行を記録し、デッドコードの発見に役立てられる。
しかし、実際に運用してみるとやり辛さがあった。

既存 Endpoint での /json リターンではファイル単位

WebGUI ではファイルを指定することで、行単位の実行回数を確認する事ができるが、json return の場合には File 単位のため、調査用 CLI でグリグリ回すには不便だった。

{
  "total_files": 2632,
  "lines_of_code": 52915,
  "lines_covered": 45827,
  "lines_missed": 7088,
  "covered_strength": 1428693.8249078724,
  "covered_percent": 86.60493243881697,
  "files": {
    "app/hoge/fugafuga.rb": {
      "filename": "/webapp/app/hoge/fugafuga.rb",
      "hash": "3b362c3af2c678c2d6237d73e8b02b82c35b64cd",
      "never_loaded": false,
      "runtime_percentage": 57.14,
      "lines_of_code": 28,
      "lines_covered": 16,
      "lines_runtime": 16,
      "lines_missed": 0,
      "covered_percent": 100.0,
      "covered_strength": 6785.8
    },
    ~~~~ 以下略 ~~~~

累積カウントとリセットの重み

Coverband は実行回数を累積でカウントする。
問題はカウンターをリセットしたとき、リセットは対象ファイル又は、全ファイルに影響するため、「先週までは動いていたコード」と「本当に使われていないコード」の区別がつかなくなる。

デプロイのたびに「今回のリリースで影響を受けたのはどこか」を知りたいのに、最新情報のみではそれが分からない。


「時系列で追えたら…」というひらめき

「最新情報だけじゃなくて、時系列データで追えたらいいのでは?」

元々監視データの生値をいじってたこともあり、毎時カバレッジデータを取得して差分を計算すれば、「この 1 時間で何行実行されたか」が分かる。それを積み重ねれば、「過去 90 日間、一度も実行されていないメソッド」を高い確度で特定できるのでは?と。
(Aurora MySQL Instance にデータ保存しているが1年分で 30 GB程度の為、長期間データを保存できる)

さらに、時系列データがあれば:

  • デプロイ後の影響確認:リリース前後でカバレッジがどう変わったか、利用タイミング含めて可視化が可能
  • デッドコードの確信度向上:「3 ヶ月動いていない」という根拠
  • コード品質の傾向分析:カバレッジの推移をグラフで可視化

これらを実現するには、Coverband から行レベルのカバレッジデータをプログラマティックに取得する必要があった。


Slack つぶやきからの、OSS コントリビュート の背景と翌日マージの体験

冒頭にも記載した通り、既存の Coverband では CLI では /json で Return される内容は File 単位のため、Slackで、「行単位で取れなくてつらー」と、呟いていた。

すると、我らがリーダ @technuma が光の速さで PR を出してくれました。
image.png

Coverband のコードを読むと、JSONReport クラスは既に line_coverage オプションをサポートしていた。しかし、HTTP の /json エンドポイントからはこのオプションにアクセスできなかった。

必要なのは、4 行の変更だった。

# web.rb への追加

line_coverage = request.params['line_coverage'] == 'true'

# ...

Coverband::Reporters::[JSONReport.new](http://JSONReport.new)(store, {

line_coverage: line_coverage

}).report

1 月 16 日

  • PR #601 を作成。タイトルは "Add line_coverage param to /json endpoint"。翌日にはメンテナーからレビューが入り、そのままマージされた。

1 月 20 日

  • v6.1.7 Tag が付与された

1 月 21 日

  • 弊社プロダクト本番環境で Version Up PR が Merge され、HTTP 経由で行レベルカバレッジデータを /json?line_coverage=true" で取得できるようになった。
{
  "total_files": 2632,
  "lines_of_code": 52923,
  "lines_covered": 45854,
  "lines_missed": 7069,
  "covered_strength": 1436771.0582922336,
  "covered_percent": 86.64285849252688,
  "files": {
    "app/hoge/fugafuga.rb": {
      "filename": "/webapp/app/hoge/fugafuga.rb",
      "hash": "3b362c3af2c678c2d6237d73e8b02b82c35b64cd",
      "never_loaded": false,
      "runtime_percentage": 57.14,
      "lines_of_code": 28,
      "lines_covered": 16,
      "lines_runtime": 16,
      "lines_missed": 0,
      "covered_percent": 100.0,
      "covered_strength": 6848.4,

      ##### 各行が何回実行されたかを List 形式で取得 #####
      "coverage": [ 
        null,
        null,
        15638,
        15638,
        15638,
        null,
        15638,
        null,
        15638,
        12,
        12,
        12,
        null,
        12,
        null,
        null,
        15638,
        12,
        12,
        12,
        12,
        null,
        null,
        12,
        null,
        null,
        15638,
        null
      ]
    },
    ~~~~ 以下略 ~~~~

社内にはエンジニアが検証に自由に使える AWS アカウント (SUNABA) が存在するので、ひとまず EventBridge, Lambda, RDS を用意して毎時 Json を取得し MySQL に保存しデータ蓄積を始めた。

2 週間で作った coverband-timeline:開発タイムライン

PR がマージされた 1 ヶ月後、プロダクト開発の傍ら隙間時間で Claude Code と共に coverband-timeline の開発を始めた。

開発の時系列

日付 内容
2/27 初回コミット。基本構成(バッチ + ビューア)を実装
3/2〜6 インフラ整備。GitHub Actions、ECR、k8s、ドメイン設定
3/9 README 整備、社内共有開始
3/11 コードビュー追加、git 履歴表示、MCP 機能追加
3/12 Prism AST パーサによるメソッドレベルカバレッジ追加
3/13 メソッド単位 git blame 連携、リモート MCP 対応
3/16 リモート MCP マージ。完成形に

約 2 週間で、MCP サーバー付きの時系列カバレッジ分析ツールが完成した。

image.png
image.png


アーキテクチャ解説:図解付きで構成を説明

coverband-timeline は、大きく 2 つのコンポーネントで構成される。

全体構成

image.png

今回相乗りさせた Schema/Table 情報
CREATE DATABASE IF NOT EXISTS coverband_timeline CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE coverband_timeline;

CREATE TABLE coverage_records (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  filename VARCHAR(512) NOT NULL,
  file_hash VARCHAR(40) NOT NULL,
  never_loaded BOOLEAN NOT NULL,
  runtime_percentage DECIMAL(6,2) NOT NULL,
  lines_of_code INT NOT NULL,
  lines_covered INT NOT NULL,
  lines_runtime INT NOT NULL,
  lines_missed INT NOT NULL,
  covered_percent DECIMAL(6,2) NOT NULL,
  covered_strength DECIMAL(16,2) NOT NULL,
  raw_coverage JSON NOT NULL COMMENT '差分計算用の生データ(累積値)',
  diff_coverage JSON NOT NULL COMMENT '前回との差分(初回は0/null)',
  created_at DATETIME NOT NULL,
  UNIQUE INDEX idx_file_hash_time (filename, file_hash, created_at)
) ENGINE=InnoDB;

技術的な工夫

1. 差分計算ロジック

Coverband のカウントは累積値なので、前回取得時との差分を計算して「この 1 時間で何行実行されたか」を記録する。

2. file_hash によるファイル変更検知

ファイルが変更されると行番号がずれる。Coverband が返す file_hash を監視し、hash が変わったら旧データを物理削除して初回扱いにする。

3. Prism AST パーサによるメソッドレベル分析

Ruby 3.3 の Prism パーサを使い、ソースコードから各メソッドの開始行・終了行を抽出。行単位のカバレッジデータと突き合わせて、メソッドごとの active/dead 判定を行う。

4. git blame 連携

メソッド単位で最終コミット情報を取得(4 並列で高速化)。「90 日以上コミットがない dead method」のような期間指定フィルタを実現。

5. 本番デプロイに合わせて最新 Code, Commit 情報取り込み Deploy
coverband-timeline では内部にプロダクト Code と、Git Commit 情報を抱えてる。
これは Viewer や MCP で利用する時に Json で得られる行番号に対して Code を当てる際に利用。
その為、本番デプロイ時に GitHub Apps 経由で coverband-timeline の GHA を Kick し、Code 更新に合わせてデプロイ。

6. 応答性能調整
API Request 時に行計算や、Commit 情報を検索すると API Return が重くなるため、CD の中で全部のデータを集約、Container に保存しておく事で Viewer や MCP 利用時の API Return 性能を確保


AI との連携:MCP サーバーで Claude Code と繋ぐ

coverband-timeline のメイン機能は、MCP(Model Context Protocol)サーバーの組み込み。

MCP とは

MCP は、AI アシスタントが外部ツールやデータソースにアクセスするための標準プロトコル。Claude Code は MCP サーバーに接続し、定義されたツールを呼び出せる。

提供ツール一覧

ツール名 機能
coverband_stats カバレッジ統計サマリー
coverband_files ファイル一覧(検索・フィルタ・ソート)
coverband_file_timeline 特定ファイルのカバレッジ時系列推移
coverband_file_coverage 行レベルカバレッジ差分
coverband_file_source ソースコード取得
coverband_git_info デプロイ済みコミット情報
coverband_file_methods メソッド別カバレッジ + git 情報
coverband_dead_methods 複数ファイル横断の dead method 検索

実際の活用シーン

Claude Code に「dead method を探して削除 PR を作って」と指示すると:

  1. coverband_dead_methods で dead method 一覧を取得
  2. coverband_file_methods で各メソッドの git 情報を確認
  3. coverband_file_source でソースコードを取得
  4. 削除しても安全か判断し、PR を作成

これにより、「coverband のデータをもとに不要コードを定期提案(PR 自動作成)」という当初の目標が、AI との対話形式 で実現。

しかし、機能開発途中の今後1,2週間で導線が用意される機能や、来季から公開される機能などは Count UP されないので、Dead Code 対象として検知される
精度向上のためにも、もう一工夫が必要な状況
Schema/Table が利用可能な為、何かしら永続的なデータを保存しておくことで対応できないか手探り中。


得られた効果・気づき

デッドコード削除の確信度が上がった

「過去 90 日間、1 度も実行されていない」「最後のコミットは 1 年前」という情報があれば、自信を持って削除できる。月次バッチの罠にも引っかからない。

デプロイの影響が可視化された

リリース前後のカバレッジ推移を見れば、「新機能が本番で使われ始めた」「この変更で既存コードのカバレッジが下がった」が分かる。

学び:小さな観点追加の力

既存の OSS に「時系列」という 1 つの観点を追加しただけで、できることが大きく広がった。


既存ツールに観点を追加して拡張するアプローチ

今回のプロジェクトで学んだことは 3 つ。

  1. 既存 OSS に欠けている観点を見つけ、自分で埋める
    Coverband は素晴らしいツールだが、「時系列」という観点が欠けていた。それを追加することで、新しい価値が生まれた。
    当初、時系列データの話をしたら OSS に直に PR を出すんだ。と言われたがチキンな私にはかなりハードルが高かったので fork することも検討したが、メンテナンスが大変なので挫折。
    Endpoint 利用の形で切り出す事で、自由度が増した。

  2. 小さな OSS コントリビュートでも、大きな影響を与えられる
    4 行の PR が、外部ツール連携の扉を開いた。完璧な大機能より、小さくても意味のある変更を。

  3. AI との連携は、MCP で簡単に実現できる
    MCP サーバーを組み込むことで、開発ツールが「AI の目と手」になる。
    今回初めて Remote MCP を用意、利用したが、便利すぎた。


GLOBIS DevEx チーム

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?