GPT-4にバグ修正のコミットメッセージを分析させてみた

この記事はGoodpatch Advent Calendar 2023 20日目の記事です。

Goodpatch の運営する ReDesigner で、フロントエンドの開発を行っております、かずです。

みなさんがそうであるように(?)、アドベントカレンダーに何書いたらいいんだろう? とウンウン悩んでいたところ、ふと「コミット履歴をGPTに食わたらどうなるんだろうなぁ」と思いつきをやってみたという記事になります。何かの参考になれば幸いです。

背景

現在のコミットルール

コミットメッセージになんらかのprefixを付けるルールはかなり一般的だと思いますが、私はフロントエンドリポジトリにおいて、emoji prefixを使っています。

goodpatch.com

ReDesignerでは、具体的には以下のような emoji を使っています。

🐛 :bug: バグ修正
✨ :sparkles: 機能追加
👍 :+1: 機能改善
♻️ :recycle: リファクタリング
🔥 :fire: 不要な機能・使われなくなった機能の削除
👕 :shirt: lintエラーの修正

また、 バグ修正のコミットであっても、何を修正したかを必ず書くことにしています。(当然?)

[実際のバグ修正コミットの一部]
RFSSN-3785 🐛 「必須」「任意」のラベルがスマホ実機だと折り返してしまう問題を修正
RFSSN-3783 🐛 PCでオーバーレイ部分をクリックしても閉じない部分がある問題を修正
RFSSN-3769 🐛 参加したイベントがあっても表示されてしまっていた問題を修正
RFSSN-3748 🐛 PCでシェイプが切れてしまう問題を修正
RFSSN-3748 🐛 SPで横スクロールが出る問題を修正
RFSSN-3770 🐛 申し込み終了・終了したイベント詳細ページでアンケートを取得しようとしてエラーになる問題を修正

バグの内容がメッセージに含まれているので、メッセージを分析すれば何か傾向などが見られるのではないか? と考えました。

GPT-4での分析

分析方法について

OpenAIのAPIで、GPT-4を使って分析することにしました。 openai.com

分析対象としては、バグコミットのコミットメッセージとすることにしました。

(コミットのdiffも入れたいなと思ったのですが、 今回はgit log コマンドを使って簡単に出力できるもの利用しました。)

実行環境

  • Node.js 18.16.1

環境準備

以下を分析する対象のリポジトリか、分析コードのリポジトリで実行し、必要なパッケージをinstallします。

$ npm i openai

コード

作成したコードは以下です。

/*
* git-bug-analysis.js
*/

#!/usr/bin/env node

const { exec } = require('child_process');
const { OpenAI } = require('openai');

const openai = new OpenAI();

// Git コミットログを取得する関数
function getGitCommitLogs() {
  return new Promise((resolve, reject) => {
    exec('git log --pretty=format:"%s"', (err, stdout) => {
      if (err) {
        reject(err);
      } else {
        const filteredLogs = stdout
          .split('\n')
          .filter(log => log.includes('🐛') || log.includes(':bug:'))
          .join('\n');
        resolve(filteredLogs);
      }
    });
  });
}

// OpenAI API にリクエストを送信する関数
async function analyzeWithGPT4(text) {
  try {
    const prompt = `以下は、とあるgitリポジトリのバグ修正コミットのメッセージ一覧です。バグの種類や特徴を分析してください。
\`\`\`
${text}
\`\`\``;

    const response = await openai.chat.completions.create({
      model: 'gpt-4-1106-preview',
      messages: [
        {
          role: 'user',
          content: prompt,
        },
      ],
      temperature: 1,
      max_tokens: 4096,
      top_p: 1,
      frequency_penalty: 0,
      presence_penalty: 0,
    });
    return response;
  } catch (error) {
    console.error('Error calling OpenAI API:', error);
    throw error;
  }
}

// メインロジック
async function main() {
  try {
    const commitLogs = await getGitCommitLogs();
    const analysis = await analyzeWithGPT4(commitLogs);
    console.log(analysis.choices[0].message);
  } catch (error) {
    console.error('Error:', error);
  }
}

main();

実行

作成したjsファイルを、OpenAIのトークンを指定して実行します。

$ OPENAI_API_KEY={トークン} node git-bug-analysis.js

実行結果

上記のコードを使って、2つのリポジトリに適用してみました。

企業向けサイト フロントエンドリポジトリ

企業向けに提供しているWebサイトのフロントエンドコードリポジトリに適用してみました。 このリポジトリは、Nuxt2 + JavaScriptから、Nuxt3 + TypeScriptに書き換えたものです。

出力

ユーザーインターフェイスの問題:
・レイアウト崩れ: メニューやモーダル、ナビゲーションのレイアウトが崩れる問題。
・表示バグ: エンプティ状態が表示されない、svgiconの表示不具合など、ユーザに適切な情報が表示されないケースがある。
・フォームの問題: 入力バリデーションの間違い、企業名や職種が適切に表示されない、フォームの保存ができない等。
・スクロール: ページのスクロールフラグ調整、ページ遷移時のスクロール位置の保持が行われていない問題。
・ページ遷移: ページ間の遷移時の問題やステータスの切り替わりがない問題。

フロントエンドのロジック問題:
・コンポーネントの挙動: コンポーネントが意図した通りの動作をしない問題が修正されている。
・適用されない設定/選択: スタイルが指定されていなかった点の修正や選択肢が正しく適用されない。

バックエンドの問題:
・APIの問題: APIクラスの分割による問題、郵便番号検索などの問題。
・データ保存問題: ローカルストレージの利用、保存状態の永続化。

ビルド・デプロイメント問題:
・環境依存問題: タグが環境情報を含んでおらず、デプロイ対象の取り違えの可能性。
・ビルドエラー: typescriptやVueのビルドエラー、productionビルド時の参照エラーなど。

セキュリティやパフォーマンスの問題:
・ファイルタイプ制限: アップロードできるファイルタイプが制限されていない問題の修正。
・パフォーマンス: ローディングの改善、無限ローディングの問題。

その他の問題:
・タイポや不要なコードの削除: typoの修正や不要とされるコードの削除。
・バリデーション修正: 入力のバリデーションルールの修正。
・asyncデータの問題: asyncデータのキーが誤っていた問題。

以上の分析から、このリポジトリ内で修正されているバグは、フロントエンドのUI/UX問題、バックエンドのデータ処理、ビルドに関する技術的な問題など広範囲に及んでいることがわかります。また、特定の機能に関連する複数の修正が異なるタイミングやコミットで行われており、継続的な改善が行われていることが示されています。コードベースのメンテナンスと品質向上に注力されており、バグ追跡番号の使用から、きちんと追跡されることでチーム内のコミュニケーションと作業の整理が意識されていると推測されます。

出力について

フロントエンドリポジトリであることはプロンプトでは特に指定していませんが、UIやインターフェースについてのバグが多いことが出力されています。

実際のデータを良く表しているな、と思ったのは ページ遷移: ページ間の遷移時の問題やステータスの切り替わりがない問題。 の部分で、こちらは Nuxt3 の useAsyncData の挙動がよくわからなかったときに、何度も修正したからです。

また、 ビルドエラー: typescript についても、TypeScript導入がはじめてのリポジトリだったこともあり、コミットにそれが表われていることがわかります。

学生向けサイト フロントエンドリポジトリ

こちらは、学生向けサイトの フロントエンドリポジトリです。 Nuxt2 + JavaScript を使用しています。

出力

このリストを分析すると、様々な種類のバグ修正が行われており、以下のような特徴やカテゴリが識別可能です。

UI(ユーザーインターフェース)関連のバグ:
・モーダルウィンドウ関連のバグ(位置調整、背景透過問題、閉じる挙動など)
・スクロール問題(横スクロールの発生、スクロールロックなど)
・表示問題(文言が逆、画像の切れ、レイアウトの崩れなど)
・要素の表示・非表示の切り替え(ボタンが見えない問題、サムネイルURLの誤りなど)

レスポンシブ/クロスブラウザ問題:
・特定ブラウザで動作しない、特定のデバイスでのレイアウト崩れ

機能性のバグ:
・イベントハンドリング(クリックしても反応がない、ドロップダウンが動作しないなど)
・フォーム関連(入力値の検証問題、submitの挙動、入力フィールドの準備不足など)
・データの取得と表示(イベント詳細の取得エラー、フォロー状態の反映など)
・状態管理(if-elseの不具合、状態によるテキスト分岐の逆転など)

エラーハンドリングと例外処理:
・非ログイン時に動作しない機能、ログイン必須の操作などの問題
・undefined や null の参照エラー

文言関連:
・誤植やタイポの修正
・テキストの間違いや不正確な用語の使用
・ローカライゼーション/翻訳エラー

パフォーマンス:
・アニメーションのガクツキ、ローディング問題など

セキュリティ:
・直リンク時のトークンの扱い

コードの整合性とリファクタリング:
・命名変更に伴うコンポーネントの入れ替え漏れ
・不要なコードの削除や構造の改善
・シンタックスエラーや使われていない変数の修正

全体的に、フロントエンドのコンポーネント、スタイリング、ユーザーインタラクティビティ、クロスプラットフォームの互換性など、ユーザーが直接触れる箇所のバグにフォーカスが当てられていることが分かります。また、細かいタイポや文言の修正が多々行われていることから、カスタマーエクスペリエンスの向上も重点的に行われているようです。コードのリファクタリングや整合性の確保は、バグを減らすための予防的措置としても機能しています。

出力について

特徴的なのは、レスポンシブ/クロスブラウザ問題undefined や null の参照エラー です。 このリポジトリはレスポンシブ対応のWebサイトで、各画面幅での見え方で問題があり何度も手を入れました。

また、JavaScriptで型チェックなどができないため、 undefined や null の参照エラーがランタイム時によく起きていました。

上記のような、リポジトリの特徴が出力に表われてると思いました。

感想

振り返りにつかえそう

修正したバグの内容が網羅的になっているので、振り返りの機会にメンバーなどと共有することで今後どのようなバグに注意すればよいかということがわかりそうです。 実際に発見・修正したバグから分析をかけているので、一般的なバグカテゴリを参照するより、より注意すべき点がわかりやすいと思いました。

知らないリポジトリを読むのにつかえそう

振り返りに使えそうとは上に書きましたが、自分が開発していたリポジトリで起こったバグなどはなんとなく記憶しているものです。 それよりも、まださわったことのないリポジトリの情報をサマライズしてみることで、そのリポジトリで気を付けなければならないことなどが、ざっくりと理解できるのではないかと思いました。

新しくジョインしたプロジェクトでこれと同じことをするのはさまざまな面で難しそうですが、メンバーの受け入れ側として、この出力結果と具体的な修正コミット例などを提示するのは良さそうだと思いました。プロンプトを調整すれば GitHub上 でのコミットURLを例示するなどもできそうです。

そもそもコミットログを眺めると色々わかる

これはまったくAIと関係ないのですが、普段GUIで git を操作しているため、あまり git log でコミットを追ったことがありませんでした。 出力された過去のコミット一覧を眺めるだけで「こんなこともあったな」「このバグ何回もやってるな」などといった記憶がよみがえってきました。 過去のコード修正履歴をピックアップしてみて、「今ならこうする」といった振り返りに使うのもよさそうです。

まとめ

記事ネタ目的で、思い付きでとりあえずやってみたのですが、色々と発見があり面白かったです。

今回、特にプロンプトやデータの渡し方を調整せず、えいやで渡しているので、他にも色々なことができそうだなと思いました。 (分析対象やパラメータ調整、diffも含めて1コミットずつ分析した結果をさらに集計したりなど、etc)

本記事が何かのヒントになれば幸いです。 お読み頂きありがとうございました!


Goodpatchではデザイン好きなエンジニアの仲間を募集しています。 少しでもご興味を持たれた方は、ぜひ一度カジュアルにお話ししましょう!