在 GitHub 的 PR Trigger Action中,使用 AI 進行自動化 Code Review

過去我曾介紹過 在 Azure DevOps 中,使用 LLM 進行 code review 以及程式碼品質掃描(在 [here] & [here]),得到許多回響,有不少朋友問,是否在 GitHub Repo 中也可以? 答案是…當然可以!

透過 GitHub Actions,我們可以輕鬆整合 OpenAI API 或其他大型語言模型(LLM)服務,打造出自動化的程式碼審查流程。這不僅能協助團隊在每次 Pull Request(PR)時即時分析程式碼品質,還能提供風格建議、安全性提醒,揭露潛在的技術債,使得 AI code review 不再只是理想,而是落地實踐的 DevOps 一環。

要實現這個功能,我們只需要幾個關鍵步驟,即可在 GitHub 的 PR 流程中,部署一個基於 LLM 的程式碼品質掃描機制。

首先,建立一個 GitHub Action workflow,觸發時機設定為 pull_request。接著,我們可以撰寫一個 yaml 腳本,在 PR 被觸發時,讀取變更的程式碼(commit changes)並送出給 LLM API(例如 OpenAI 的 GPT-4)。最後,將分析結果格式化為 comment,自動撰寫在 PR 回覆中,讓開發者即時收到建議。

我們先來看執行的效果。

底下 repo 中原本有一段程式碼,是計算BMI用的:

public void OnPost()
{
    if (Weight.HasValue && Height.HasValue && Height > 0)
    {   
        Height = Height / 100; // Convert height from cm to m
        BMI = Weight / (Height * Height); 
    }
}

我在分支中將其修改如下,請注意,其中有很多明顯的bug和不當的寫法:

public void OnPost()
{
    if (Weight.HasValue && Height.HasValue && Height > 0)
    {
        int para1=12;

        para1=para1/0;
        
        Height=(int)Height / 100; // Convert height from cm to m
        BMI = Weight / (Height * Height);

        //todo: 尚未完成
    }
}

當我們將這段程式碼變更 commit 之後,可以建立一張 PR 單,在該 PR 中,會觸發我們事前撰寫好的 action:
enter image description here
當 PR Trigger 的 Action 觸發後,將會在PR過程中,自動執行 AI 程式碼掃描的流程:
enter image description here

完成後,會直接把建議寫在PR單上:
enter image description here

要實現這樣的 PR Trigger Action 非常簡單,底下是 yaml script:

name: PR CI - ASP.NET Core WebApp

on:
  pull_request:
    branches:
      - main

jobs:
  build-and-test:
    name: Build and Test
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'  # 根據你使用的 .NET 版本調整

      - name: Restore dependencies
        run: dotnet restore

      - name: Build
        run: dotnet build --no-restore --configuration Release
        
      - name: Get PR Diff
        id: diff
        run: |
          echo "Getting diff for PR #${{ github.event.pull_request.number }}"
          git fetch origin main
          git diff origin/main > diff.txt
      
      - name: Call OpenAI for Review
        id: openai_review
        run: |
          echo "Calling OpenAI API to analyze code diff..."
      
          DIFF_CONTENT=$(cat diff.txt | head -c 6000 | jq -Rs .)
      
          REQUEST_DATA=$(jq -n \
            --arg model "gpt-4o" \
            --arg system_msg "你是一位資深程式碼審查員,專長在於找出技術債、重構建議與 clean code 和 SOLID 原則。" \
            --arg user_msg "以下是 pull request 的程式碼差異,請指出是否有技術債、壞味道、維護風險、安全性問題,並給出重構建議:\n\n$(cat diff.txt | head -c 6000)" \
            '{
              model: $model,
              temperature: 0.7,
              messages: [
                { role: "system", content: $system_msg },
                { role: "user", content: $user_msg }
              ]
            }')
      
          echo "🟡 Sending this request to OpenAI:"
          echo "$REQUEST_DATA" | jq .
      
          RESPONSE=$(curl https://api.openai.com/v1/chat/completions \
            -s \
            -H "Content-Type: application/json" \
            -H "Authorization: Bearer ${{ secrets.OPENAI_API_KEY }}" \
            -d "$REQUEST_DATA")
      
          echo "🟢 OpenAI 回應內容:"
          echo "$RESPONSE" | jq .
      
          echo "$RESPONSE" | jq -r '.choices[0].message.content' > review.txt

          REVIEW_CONTENT=$(cat review.txt | perl -pe 's/\\n/\n/g')
          echo "review<<EOF" >> $GITHUB_OUTPUT
          echo "$REVIEW_CONTENT" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Comment on PR
        uses: peter-evans/create-or-update-comment@v3
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ github.event.pull_request.number }}
          body: |
            🤖 **AI 程式碼審查意見**
            
            以下是 OpenAI GPT-4o 對此 PR 的分析與建議:

            ${{ steps.openai_review.outputs.review }}

      - name: Run tests
        run: dotnet test --no-build --configuration Release --logger "trx"

上面這段 yaml,將會把我們的程式碼差異,送給 LLM 以 gpt-4o 進行code review,重點在 Get PR Diff 開始的區段,其中 Call OpenAI for Review 用到的 prompt 很簡單:

你是一位資深程式碼審查員,專長在於找出技術債、重構建議與 clean code 和 SOLID 原則。
以下是 pull request 的程式碼差異,請指出是否有技術債、壞味道、維護風險、安全性問題,並給出重構建議:
...

透過這樣的提示詞設計,我們可以有效引導 LLM 從「程式碼差異」中抽絲剝繭,辨識出潛藏的設計問題與可優化的區塊。

GPT-4o 作為新一代模型,在理解上下文與邏輯關聯上具備卓越的語意分析能力,使其在 Code Review 任務中表現得更為精準且具建設性。尤其當團隊缺乏專職審查人力時,這樣的 AI 助理能在第一時間提供可讀性與維護性的建議,成為 Pull Request 中不可或缺的AI助手。


參考 課程:
敏捷開發與Azure DevOps實戰

留言

這個網誌中的熱門文章

使用LM Studio輕鬆在本地端以API呼叫大語言模型(LLM)

使用 Dify 以No Code方式建立記帳機器人

實際嘗試使用DeepSeek API

使用 Dify API 快速建立一個包含前後文記憶的對談機器人

使用 Dify 建立企業請假機器人