본문 바로가기

개발 노트

Github Action을 활용해 Pull Request를 AI로 요약하기

728x90
반응형

개요

사이드 프로젝트에서 계속 Pull Request를 사용하다 보니 어느 “순간 작업 내역에 대한 요약을 보는 게 애매하다” 는 생각을 가지게 됐다.

 

중간중간 Commit 내역으로 하여금 무슨 작업을 했는지는 파악할 수는 있어도 2% 부족하다는 심상이었다.

 

그러던 중 Pull Request가 Open 되면 해당 작업 내역을 AI로 요약해주는 무언가를 만들면 괜찮지 않을까 싶어 조사를 했고 Github Action을 이용해 해당 부분을 처리할 수 있었다.

 

좋은 Pull Request란?

지난 글에서는 PyCharm의 Plugin을 활용해 Commit Message를 자동으로 생성하는 과정에서 “좋은 Commit Message”란 무엇일까를 고민하게 됬고 “좋은 Commit Message”는 어떻게 작성해야 하는지에 대해 다루는 많은 자료를 참고할 수 있었다.

 

이번 주제도 마찬가지로 “좋은 Pull Request”를 고민하면서 “좋은 Pull Request”는 무엇인지에 대해 조사해 봤다. 여러 글을 읽고 나서 종합했을 때 하기 항목으로 정리했다.

  1. PR은 작고 논리적인 단위로 나눠라
    1. 하나의 PR에 너무 많은 변경사항을 넣지 말 것
    2. 이상적인 PR은 리뷰어가 한 번에 이해 가능한 수준의 변경만 포함
    3. 큰 작업은 여러 단계로 나누어 PR을 보내는 것이 좋음
  2. 좋은 제목과 설명을 작성하라
    1. 변경 이유(Why), 변경 내용(What), 구현 방식(How), 테스트 방법(How to test)
  3. 리뷰어의 시간을 존중하라
    1. PR을 올리기 전에 스스로 코드를 한 번 더 읽어보고 정리하라.
    2. Dead Code, 디버깅 로그, 불필요한 파일은 제거
    3. 변경된 코드가 기존 시스템에 미칠 영향도 고려하라.
  4. 변경 사항에 대한 문맥을 제공하라
    1. 변경의 이유와 의도를 명확히 설명하여 리뷰어가 배경을 쉽게 이해하게 함
    2. 필요시, 링크, 문서 , 스크린 숏 등을 활용해도 좋음
  5. 자주 빠르게 PR을 날려라

 

위 내용은 PR을 요청하는 사람의 입장에서 정리한 내용이다. 내가 “리뷰어”라고 한다면 PR은 어떻게 바라봐야 할까?

  1. 리뷰어는 “내가 이 코드를 운영환경에서 유지보수해야 한다면?”이라는 관점으로 리뷰
  2. 피드백은 구체적이고 친절하게 전달할 것

 

Pull Request는 어떻게 작성하면 좋을까 ?

상술한 내용에서는 “좋은 Pull Request”에 대한 특징을 간단히 나열해 봤다. 이 글의 “개요”에서 언급했듯 Pull Request를 수기로 작성하기보단 AI에게 위임할 것이다. 다시 말해 해당 특징을 활용해 AI에게 Pull Request가 Open 되면 요약해달라고 할 것이다.

 

필자의 경우 다음의 양식을 통해 Pull Request를 요약해 달라고 prompt를 작성했다.

# Summary
 - 무엇을, 왜 수정했는지 간단하게 요약합니다.
         
 # What's Changed
 - 핵심 변경 사항을 취합 및 요약해주세요, bullet point를 활용해 3줄 정도로 정리해주세요
           
 # Side Effects
- 시스템에 어떤 문제 생길 수 있는지 짚어주세요.

# Suggest
- 이 PR에서 잘 처리된 부분은 무엇이고 잘 처리되지 않은 부분이 무엇인지 짚어주세요.

## 잘 처리된 부분
- 예시
    - XXX 모듈의 책임 분리 → 유지보수성과 가독성 향상
    - 불필요한 의존성 제거 → 코드 간결성 증가
    - 인터페이스 분리 및 추상화 계층 도입 → 테스트 및 확장성 고려한 설계
    
## 잘 처리되지 않은 부분
- "예시"에 맞춰서 여러 항목을 입력해도 좋습니다.
- 예시
    ---    
    문제: 어떤 부분이 잘 처리되지 않았는지 명확히 서술합니다.
    개선안: 구체적으로 어떻게 개선하면 좋을지 제안합니다.
    참고 파일/위치: 수정이 필요한 코드의 위치나 파일 경로를 명시합니다.

    추천 등급: (P1 ~ P5 중 하나 선택)        
        P1: 꼭 반영해주세요 (Request Change)
        P2: 적극적으로 고려해주세요 (Request Change)
        P3: 웬만하면 반영해주세요 (Comment)
        P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
        P5: 그냥 사소한 의견입니다 (Approve)
        등급 사유: 왜 해당 등급을 부여했는지 논리적으로 설명합니다.                
    ---

 

위 내용에서 P1~P5라고 넘버링이 붙은 부분을 확인할 수 있다. 이는 뱅크샐러드의 Pn룰을 참조했고 AI에게 이러한 부분을 짚어달라고 할 것이다.

 

AI를 활용해 Pull Request 요약 처리하기

이제 Github Action를 이용해 AI가 Pull Request를 어떻게 요약할 수 있는지 정리해보려 한다. 필자는 Gemini를 사용하고 있기에 Gemini의 API Key와 관련 라이브러리를 활용했다.

 

1. Github Action 스크립트 설정하기

Pull Request가 Open 되면 Github Action가 동작하며 이 과정에서 Pull Request를 요약해 주는 Python Script의 위치를 지정하는 방식이다.

name: Gemini PR Summary and Explanation

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  pr-summary:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9.16'

      - name: Install Python Packages
        run: |
          pip install google-generativeai

      - name: Fetch and Generate Git Diff for PR
        run: |
          git fetch origin "${{ github.event.pull_request.base.ref }}"
          git fetch origin "${{ github.event.pull_request.head.ref }}"
          git diff --unified=0 "origin/${{ github.event.pull_request.base.ref }}" > diff.txt

      - name: Generate PR Summary with Gemini
        env:
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        run: |
          python3 deployment/generate_summary.py

      - name: Format PR Review Summary for Comment
        id: store
        run: |
          COMMENT_STRING=$(cat review_result.txt)

          echo "comment<<EOF" >> $GITHUB_OUTPUT
          echo "# AI PR 요약" >> $GITHUB_OUTPUT
          echo "$COMMENT_STRING" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Post PR Summary Comment
        uses: mshick/add-pr-comment@v2
        with:
          message: ${{ steps.store.outputs.comment }}
          repo-token: ${{ secrets.GITHUB_TOKEN }}

위 스크립트 중간에 “python3 deployment/generate_summary.py”라는 라인이 이에 해당한다.

 

2. generate_summary는 어떻게 생겼는가?

generate_sumamry.py는 다음과 같이 작성되었다. 코드에서 확인할 수 있다시피 GEMINI_API_KEY가 환경변수에 등록되어있어야 한다.

import os
import google.generativeai as genai

def main():
    # Gemini API 키 읽기
    gemini_api_key = os.getenv("GEMINI_API_KEY")
    if not gemini_api_key:
        raise Exception("GEMINI_API_KEY 환경변수가 설정되지 않았습니다.")

    # Gemini API 초기화
    genai.configure(api_key=gemini_api_key)

    # diff.txt 읽기
    with open('diff.txt', 'r', encoding='utf-8') as f:
        diff_output = f.read()

    # 프롬프트 텍스트 구성
    prompt_text = f"""
    다음은 깃허브 PR 에 올라온 수정된 코드들 입니다.
    
    Git diff를 분석하고 이 PR이 뭘 변경했는지 하기 Template으로 요약해주세요.  
        
     # Recommand
     - 이 PR의 제목을 추천해주세요
     
     # Summary
     - 무엇을, 왜 수정했는지 간단하게 요약합니다.
             
     # What's Changed
     - 핵심 변경 사항을 취합 및 요약해주세요, bullet point를 활용해 3줄 정도로 정리해주세요
               
     # Side Effects
    - 시스템에 어떤 문제 생길 수 있는지 짚어주세요.
    
    # Suggest
    - 이 PR에서 잘 처리된 부분은 무엇이고 잘 처리되지 않은 부분이 무엇인지 짚어주세요.
    
    ## 잘 처리된 부분
    - 예시
        - XXX 모듈의 책임 분리 → 유지보수성과 가독성 향상
        - 불필요한 의존성 제거 → 코드 간결성 증가
        - 인터페이스 분리 및 추상화 계층 도입 → 테스트 및 확장성 고려한 설계
        
    ## 잘 처리되지 않은 부분
    - "예시"에 맞춰서 여러 항목을 입력해도 좋습니다.
    - 예시
        ---    
        문제: 어떤 부분이 잘 처리되지 않았는지 명확히 서술합니다.
        개선안: 구체적으로 어떻게 개선하면 좋을지 제안합니다.
        참고 파일/위치: 수정이 필요한 코드의 위치나 파일 경로를 명시합니다.

        추천 등급: (P1 ~ P5 중 하나 선택)        
            P1: 꼭 반영해주세요 (Request Change)
            P2: 적극적으로 고려해주세요 (Request Change)
            P3: 웬만하면 반영해주세요 (Comment)
            P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
            P5: 그냥 사소한 의견입니다 (Approve)
            등급 사유: 왜 해당 등급을 부여했는지 논리적으로 설명합니다.                
        ---
    
    결과는 반드시 한국어로 번역해주세요.
    
    <git diff>{diff_output}</git diff>
    """

    # 모델 설정
    generation_config = {
        "temperature": 0.9,
        "top_p": 1,
        "top_k": 1,
        "max_output_tokens": 2048,
    }

    # Gemini 모델 생성
    model = genai.GenerativeModel('gemini-1.5-pro', generation_config=generation_config)
    response = model.generate_content(prompt_text)

    # 결과 파일로 저장
    with open('review_result.txt', 'w', encoding='utf-8') as f:
        f.write(response.text)

if __name__ == "__main__":
    main()

 

3. 환경변수 설정하기

앞선 내용에선 “GEMINI_API_KEY”라는 환경변수가 필요하다고 언급했는데 이는 Github Action이 실행되는 와중에 참조하는 환경변수다. Github Repo의 다음 위치에서 설정할 수 있다.

Settings > Secrets and Variables > Actions

 

마치며

필자는 위 내용을 사이드 프로젝트에 적용했다. 진행 중인 사이드프로젝트가 실 사용자가 있는 상황이고 프로젝트 구조를 유출할 수 있기 때문에 스크린숏은 첨부할 수 없지만 개인적으로는 만족하며 잘 사용 중이다.

 

AI가 요약해 주는 내용을 보고 무엇을 해결하고 무엇을 그대로 가져갈지에 대해서는 늘 고민할 부분이지만 스스로 놓칠 수 있는 부분을 한번 더 점검한다는 의미에서는 이만한 도구도 없는 듯하다.

 

아쉬운 점은 Pull Request Prompt를 더 개선시켜야 하는 부분이다. 계속 다른 형식으로 요약 결과를 내기 때문에 “일관성”이 떨어지는 것이 단점이다.

 

계속 수정을 시도해 보고 맞는 방법을 찾아가 보도록 하자.

 

Reference

728x90
반응형

'개발 노트' 카테고리의 다른 글

[Arduino] WeMos D1&R2  (0) 2022.07.27
MQTT, Message Queuing Telemetry Trasnport  (0) 2022.07.17
[Postman] Cookie header 자동 셋업 끄기  (0) 2022.05.15
React && DJango 파일 업로드  (0) 2020.12.14
DRF&React로 REST API 체험기  (0) 2020.11.18