← 記事一覧に戻る
テクノロジー

過去のバグをLintルールにして再発を止める

過去のバグをLintルールにして再発を止める

バグを直したあと、振り返りに「今後は気をつける」と書いて終わっていませんか。気をつけるだけの対策は、メンバーが入れ替わったり忙しくなったりすると効かなくなります。同じ書き方をした瞬間に機械が止めてくれる仕組みにすれば、人の注意力に頼らずに再発を防げます。この記事は実装工程の話で、テストを足すより手前の「コードを書いた時点」で止める方法を扱います。

ルール化に向くバグ、向かないバグ

すべてのバグがLintルールになるわけではありません。コードの見た目だけで「これは危ない」と判定できるものが向いています。

  • 向く: 特定の関数を特定の使い方で呼ぶ(引数なしの toLocaleString()、parseInt の基数省略など)、禁止したいAPIやimportを使う、必須の処理が抜ける(await 忘れなど)
  • 向かない: 業務ロジックの誤り、データの組み合わせで初めて起きるバグ、画面の見た目の崩れ。これらはテストや受入条件で防ぎます

見分ける質問は一つです。「そのバグの原因になった1行を、別のメンバーがコードだけ見て危ないと指摘できるか」。できるならルールにできます。

既存ルールで足りるか、カスタムルールが要るか

最初からカスタムルールを書く必要はありません。次の順で確認します。

  1. 既存のルールやプラグインに同じ検査がないか探す(no-floating-promises など)
  2. ESLint標準の no-restricted-syntax や no-restricted-imports で書けないか考える
  3. それでも足りないときだけ、カスタムルールを書く

例1: 設定だけで止める

過去のバグ: 引数なしの toLocaleString() が実行環境の言語設定で表示を変え、画面ごとに日付の形式がばらついた。これは設定だけで止められます。

// eslint.config.js
{
  rules: {
    'no-restricted-syntax': ['error', {
      selector: "CallExpression[callee.property.name='toLocaleString'][arguments.length=0]",
      message: 'toLocaleString にはロケールを渡す(過去の表示ずれ対策)',
    }],
  },
}

メッセージに「なぜ禁止か」を一言入れるのがコツです。ルールに引っかかった人が、理由を調べに行かなくて済みます。

例2: カスタムルールを最小で書く

設定で表現できない検査は、ルールを1つ書きます。次は、自社の legacyFetch を呼んだらエラーにする最小のルールです。

// rules/no-legacy-fetch.js
export default {
  meta: {
    type: 'problem',
    messages: { used: 'legacyFetch は廃止予定。apiClient を使う' },
    schema: [],
  },
  create(context) {
    return {
      CallExpression(node) {
        if (node.callee.type === 'Identifier' && node.callee.name === 'legacyFetch') {
          context.report({ node, messageId: 'used' });
        }
      },
    };
  },
};

読み込みは、設定ファイルの plugins にローカルのプラグインとして登録するだけです。ルールのテストには ESLint の RuleTester を使い、「引っかかる例」と「引っかからない例」を1つずつ書きます。

運用で失敗しないために

  • 過去のバグ1件につき1ルールにし、ルールの説明に元のIssue番号を書く
  • 既存コードが大量に引っかかるときは、いきなりエラーにせず警告から始め、段階的にエラーへ上げる
  • 誤検知が出たら、無効化コメントを乱用せず、ルール側の条件を直す
  • 半年に一度、一度も引っかからないルールを見直して削除する

Bugoon での実践

ルール化の出発点は「どのバグが、どのコードの書き方から生まれたか」を特定することです。Bugoon のウィジェットでは、報告時にスクリーンショットと操作ステップ、コンソールエラーが一緒に記録され、GitHub Issueとして残ります。再発しやすいバグを探すときは、Issueの原因欄から同じ書き方が繰り返されていないかを見直すと、ルール化の候補が見つかります。MCPサーバー経由でClaude CodeやCursorにIssueを読ませ、「この原因を検出するLintルールを書いて」と頼む使い方もできます。

チームのバグ報告を、もっとスムーズに。

Bugoon は無料で始められます。サイトにタグを 1 行追加するだけで、QA と開発の往復がなくなります。

無料で始める