개요
팀 프로젝트가 아닌 개인 프로젝트를 진행하다보면 PR 없이 오직 push로만 코드 업데이트를 하는 경우가 꽤 있다.
이번에는 외롭지 않은 개인 프로젝트를 진행해보기 위해서
PR 요청 시 코드 리뷰를 받아볼 수 있도록 AI를 적용해보려고 한다.
시나리오
- PR이 생성되거나 업데이트되면 Github Actions가 트리거 됨.
- Github Actions는 저장소를 체크아웃하고, 파이썬 설정 및 필요한 패키지를 설치함.
review_pr.py
스크립트가 실행됨.- 스크립트는 PR에서 변경된 파일을 가져와 OpenAI API로 리뷰를 요청함.
- OpenAI API의 응답을 PR 코멘트로 작성함
워크플로우 작성
이 파일은 .github/workflows
디렉토리에 저장하자. PR이 열리거나 업데이트될 때 파이썬 스크립트를 실행하도록 설정한다.
name: Review PR
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
review:
runs-on: ubuntu-latest
steps:
- name: "1. Checkout repository"
uses: actions/checkout@v2
- name: "2. Set up Python"
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: "3. Install dependencies"
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
- name: "4. Run PR review script"
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
python review_pr.py
PR 추적
먼저 레포지토리 정보를 가져와야 한다.
g = Github(github_token)
repo = g.get_repo(repo_name)
Repository(full_name="JaehyoJJAng/pr-review-bot")
repo
변수를 출력하면 위처럼 Repository 객체 정보가 출력된다.
그리고 open된 PR 목록을 가져온 후 출력해보면
open_prs = repo.get_pulls(state='open', sort='created', direction='desc')
<github.PaginatedList.PaginatedList object at 0x746dfcd5add0>
PaginatedList 객체가 반환된다.
이걸 반복문을 사용해 PR 정보 값을 가져올 수 있는데
for pr in open_prs:
print(pr)
PullRequest(title="리뷰용 파이썬 파일", number=3)
위와 같은 데이터가 반환되며
이걸 아래와 같이 PullRequest
객체의 속성에 접근해 값을 빼올 수 있다.
for pr in open_prs:
print(pr.title, pr.number)
리뷰용 파이썬 파일 3
위 내용을 바탕으로 리뷰된 PR은 건너뛰는 예외 처리 로직을 구현하고 리뷰 수행 함수를 실행하면 된다.
for pr in open_prs:
# 이미 리뷰된 PR은 건너뜀. 예: 특정 레이블이 붙어 있는 경우
if any(label.name == "reviewed" for label in pr.labels):
continue
# 리뷰를 수행하고 해당 PR에 레이블을 추가
review_pr(repo_name, pr.number)
pr.add_to_labels('reviewed')
- 1. PR의 라벨 확인
pr.labels
는 PR에 붙어있는 모든 라벨의 리스트를 반환합니다.- 각 라벨은
label
객체이며,label.name
속성으로 라벨의 이름에 접근할 수 있습니다.
- 2. 라벨 이름이 'reviewed'인지 확인
any(label.name == "reviewed" for label in pr.labels)
는 PR의 라벨 중 하나라도reviewed
라는 이름을 가진 라벨이 있는지 확인하는 조건문입니다.any
함수는 주어진 조건을 만족하는 요소가 하나라도 있으면True
를 반환합니다.- 리스트 컴프리헨션
for label in pr.labels
를 통해 PR의 모든 라벨을 순회하면서label.name == "reviewed"
조건을 확인합니다.
- 3. 조건을 만족하면 PR을 건너뜁니다:
continue
키워드는 현재 반복(iteration)을 중단하고 다음 반복으로 넘어가게 합니다.- 즉, PR의 라벨 중 'reviewed' 라벨이 있다면, 해당 PR은 이미 리뷰된 것으로 간주하고, 다음 PR로 넘어갑니다.
왜 필요한가?
- 리뷰 중복 방지: 이미 리뷰된 PR을 다시 리뷰하는 것을 방지합니다. 이렇게 하면 중복 작업을 줄이고, 불필요한 리뷰를 피할 수 있습니다.
- 라벨로 상태 관리: PR의 상태를 라벨로 관리할 수 있습니다. 예를 들어, 'reviewed' 라벨을 붙여서 해당 PR이 이미 리뷰되었음을 표시할 수 있습니다.