TalentX Tech Blog

Tech Blog

Devinを駆使したコードレビューの効果的な活用方法

MyTalentチームの穴原です。
TalentXではDevinを活用して開発を行っています。

devin.ai

本記事では、Devinを活用して開発を行うだけでなく、品質向上に繋がるコードレビューを実施してもらうために工夫した内容を紹介します。

Devinによるコードレビューへの期待

Devinは自律型AIソフトウェアエンジニアです。

Devinは開発を行いプルリクエストを作成してもらうだけでなく、プルリクエストのレビューも実施できます。
開発と同じくレビューもプロンプトを通じて依頼します。

開発内容や背景をプロンプトに含めることで、その内容を基にレビューを行ってくれるのではないかと期待しました。

マージ後のテストで期待と異なる実装が発覚することがあるため、Devinのレビューを挟むことで早期に検知を行いたいです。

他AIコードレビューサービスは使用しないのか?

TalentXでは現在GitHub Copilot code reviewも活用しています。
GitHub Copilot code reviewは可読性・セキュリティ・性能の観点で質の高いレビューを行ってくれますが、開発内容や背景を踏まえずにレビューを行うため、期待どおりに動作しないコードであっても指摘が漏れることがあります。

そこで、AIによるコードレビューをDevinに全面的に切り替えるのではなく、それぞれの強みを活かして使用していく方針です。

Devinに対し、簡易的にレビュー依頼を行う

Devinに対し、以下のようなプロンプトでレビュー依頼をリクエストするとプルリクエストに対してレビューを実施してくれます。

プルリクエストをレビューし、github上にコメントしてください。
レビューの観点として、要求に合った実装を行っているか確認してください。
要求は以下になります。
{要求内容}
プルリクエストはこちらです。{プルリクエストURL}

上記プロンプトをプルリクエスト毎に都度作成し、依頼するのは効率が悪く活用が難しいです。そのため簡易的にレビュー依頼を行える仕組みを作りたいと思います。

TalentXではJiraを活用してプロジェクト管理を行っているため、GitHub ActionsにてJiraから開発内容を取得しDevinにレビュー依頼を行うまでを自動化したいと思います。

GitHubのプルリクエストより簡易的にレビュー依頼を行う

前提

開発ブランチ名にはJiraの課題番号を含めてください。
例:feature/PK-123

GitHub Actionsの実装

プルリクエストへの「devin-review」ラベルの付与をトリガーに、GitHub ActionsにてDevinにレビュー依頼を行う仕組みを作成しました。

Github Actionsの実装内容は以下になります。

devin-review.yml

以下の処理を行っています。

  • 「devin-review」ラベルがプルリクエストに付与されたのをトリガーに起動
  • Pythonファイル .github/scripts/devin_review.pyの実行
name: Devin Review

on:
  pull_request:
    types: [labeled]

jobs:
  devin-review:
    runs-on: ubuntu-latest
    if: github.event.label.name == 'devin-review'
    
    env:
      PROJECTKEY: "PK"
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install requests
      
      - name: Run Devin Review
        env:
          PROJECTKEY: ${{ env.PROJECTKEY }}
          JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
          JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
          JIRA_CLOUD_ID: ${{ secrets.JIRA_CLOUD_ID }}
          DEVIN_API_KEY: ${{ secrets.DEVIN_API_KEY }}
          GITHUB_HEAD_REF: ${{ github.head_ref }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          python .github/scripts/devin_review.py

.github/scripts/devin_review.py

JiraのREST APIのレスポンスには特殊文字が含まれている場合があり、コマンドのみで処理を行うと煩雑になるためPythonで処理を行うことにしました。

以下の処理を行っています。

  • ブランチ名よりJiraのストーリー番号を取得
  • JiraのREST APIを利用してストーリー内容を取得
  • Devin APIにて、ストーリー内容を含めたレビュー依頼のプロンプトを作成し、リクエストを送信
#!/usr/bin/env python3

import os
import re
import requests
import sys

def get_issue_from_branch(branch_name, project_key):
    # PK-123みたいなパターンを探す
    pattern = f'{project_key}-(\d+)'
    match = re.search(pattern, branch_name)
    return f'{project_key}-{match.group(1)}' if match else None

def fetch_jira_description(issue_num):
    url = f"https://api.atlassian.com/ex/jira/{os.getenv('JIRA_CLOUD_ID')}/rest/api/2/issue/{issue_num}"
    
    resp = requests.get(
        url, 
        auth=(os.getenv('JIRA_EMAIL'), os.getenv('JIRA_API_TOKEN')),
        headers={'Accept': 'application/json'}
    )
    
    if resp.status_code != 200:
        print(f"JIRA API failed: {resp.status_code}")
        sys.exit(1)
    
    desc = resp.json()['fields']['description']
    if not desc or desc == 'null':
        print("No description found")
        sys.exit(1)
    
    return desc

def call_devin(description, pr_url):
    payload = {
        'prompt': f"""プルリクエストをレビューし、github上にコメントしてください。
レビューの観点として、要求に合った実装を行っているか確認してください。
要求は以下になります。
{description}
プルリクエストはこちらです。{pr_url}"""
    }
    
    resp = requests.post(
        'https://api.devin.ai/v1/sessions',
        json=payload,
        headers={
            'Authorization': f"Bearer {os.getenv('DEVIN_API_KEY')}",
            'Content-Type': 'application/json'
        }
    )
    
    if resp.status_code != 200:
        print(f"Devin API failed: {resp.text}")
        sys.exit(1)
    
    return resp.json()

if __name__ == '__main__':
    project_key = os.getenv('PROJECTKEY')
    branch = os.getenv('GITHUB_HEAD_REF')
    
    issue = get_issue_from_branch(branch, project_key)
    if not issue:
        print(f"No {project_key} issue found in branch name: {branch}")
        sys.exit(0)
    
    print(f"Found issue: {issue}")
    
    desc = fetch_jira_description(issue)
    pr_url = f"https://github.com/{os.getenv('GITHUB_REPOSITORY')}/pull/{os.getenv('PR_NUMBER')}"
    
    result = call_devin(desc, pr_url)
    print("Devin review requested successfully")

実際に動かしてみた

JiraにはGood morningを返却するAPIを作成する旨のストーリーを作成しました。

コードはGood nightを返却する、ストーリーの意図とは異なる挙動をするAPIを開発しました。

「devin-review」ラベルを付与後、レビューが終わるまで待機します。

実装が誤っている旨のコメントが投稿されました。

注意事項

  • Devinでのレビューは開発と同じくACUが消費されます。
  • 他AIサービスと同様、誤ったコメントをする可能性があります。

業務活用した際にDevinが投稿したコメント紹介

業務で利用し、Devinがプルリクエストに対してコメントした内容を紹介します。
要求に合った実装となっているか確認を行う旨のプロンプトでレビュー依頼を行っていますが、他観点でもコメントをしてくれました。

実装内容が要求に適したプログラムであることをコメント

Devinのレビューに期待していた「要求内容や背景に合ったプログラムとなっているか」を確認し、適した開発内容であることをコメントしてくれました。

修正漏れに対して指摘コメント

API定義のレスポンス項目からPV/UUを削除する修正では、ソート項目にPV/UUが残っている指摘をしてくれました。

品質観点でのコメント

エラーハンドリングや単体テストのためのモックが用意されているか等、プログラムの品質に対してコメントしてくれました。

チームメンバーのレビュー内容を把握してコメント

チームメンバーがレビューした後にDevinがレビューを行うと、チームメンバーのレビューコメントを把握した上でコメントしてくれました。

まとめ

Devinでのコードレビュー活用方法を紹介しました。

プログラムの品質だけでなく、開発内容に適した実装となっているかDevinがレビューを行うと、一人のエンジニアからレビューしてもらっている体験に近かったです。品質向上だけではなく、以前より自信を持ってチームメンバーにレビュー依頼を出せるようになりました。

Devinを開発で利用している方はレビューでの活用も試してみてください。

最後に

現在、TalentXでは一緒に働く仲間を募集しております。

talentx.brandmedia.i-myrefer.jp

カジュアル面談も行っておりますので、ぜひご応募ください!

i-myrefer.jp