Github Actions 로 리뷰어 자동 할당하기

Kim Dong Kyun·2024년 7월 23일
6
post-thumbnail

개요

프로젝트를 진행하면서, 추후 구현에 PR 및 리뷰가 좀 더 적극적으로 이루어졌으면 하는 바램이 생겼다. 그에 따라

1. 리뷰어를 내가 고르지 않아도 돼서 부담이 덜하고
2. 리뷰어에게 깃허브에서 자동으로 보내주는 메일 뿐만 아니라, 소통 채널(ex : 디스코드) 에서의 멘션(알림을 끌 수도 있으니)

이 자동으로 이루어지는 환경이 필요했다. 이 과정에서 협업하고 있는 백엔드, 프론트엔드 모두 사용할 수 있는 통합된 환경을 원했으므로 Github Actions 외 다른 설정이 필요 없는 방식으로 리뷰어 자동 할당 을 구현했다.

예제에서는 현재 팀이 다루고 있는 Discord 를 사용하지만, Slack 등의 다른 알림툴을 사용해도 무방 할 것으로 보인다.


구현

1. 깃허브 토큰 발급

우리가 참여해서 개발하고 있는 특정 Github Repository 에서 풀 리퀘스트가 있을 시

  1. 같은 Repository 에서 작업중인 작업자의 목록들을 가져오는 API
  • 이 API 로 리뷰어를 랜덤으로 한 명 추출한다.
  1. 추출한 리뷰어에게 리뷰 요청을 보내는 API
  • 이 API 로 리뷰어에게 PR 리뷰를 할당한다.

를 사용해야 하기 때문에, 깃헙에 위 API 요청을 보낼 시 인증 수단으로 사용할 관리자의 개인 토큰이 필요하다.

  1. 깃허브 접속 -> 프로필 -> 세팅으로 진입한다.

  1. 맨 아래있는 Developer settings 클릭
  1. 익숙한 클래식 방식으로 토큰을 생성한다.

  2. 토큰을 생성한다.

  3. 같은 Repository 에서 작업중인 작업자의 목록들을 가져오는 API

  4. 추출한 리뷰어에게 리뷰 요청을 보내는 API

를 호출해야 하므로, admin:repo_hook + workflow(repo 도 자동으로 권한 체크된다) 를 선택해준다

  1. 생성된 토큰을 잘 저장해둔다 (어딘가에)

2. Discord Webhook 설정

WebHook?
웹후크를 설정하기 위해 클라이언트는 서버 API에 고유한 URL을 부여하고 알고자 하는 이벤트를 지정합니다. 웹후크가 설정되면 클라이언트는 더 이상 서버를 폴링할 필요가 없습니다. 지정된 이벤트가 발생하면 서버는 클라이언트의 웹후크 URL에 관련 페이로드를 자동으로 전송합니다. - Redhat '웹후크란?'

예제에서는 디스코드를 사용 할 것이기 때문에, 디스코드 웹훅을 발급받아보자.

  1. 서버(참여하고 있는) 설정에 들어간다.

  2. 좌측 연동 버튼을 클릭한다.

  3. 웹후크를 새로 만든다

  4. 적절히 웹후크 설정을 마치고 (채널, 프사...) 링크를 클릭하여 발급받는다.


3. Repository secret 설정

깃헙 토큰, 디스코드 웹훅 URL 을 퍼블릭하게 노출시키는 것은 싫기 때문에, Github Actions 사용 시에 유용하게 사용 가능한 Github secret 을 사용한다.

  1. 작업 중인 repository 의 Settings -> Scretes and variables -> Actions 에서 New repository secret(녹색 버튼) 을 클릭해서 디스코드 웹훅 URL, 리뷰용 깃허브 인증 토큰을 등록한다.

(GITHUB ... 으로 시작되는 키는 발급이 제한되므로, REVIEW_TOKEN 이라는 이름으로 만들었다)

이제 준비 거~의 끝.


4. Github-actions 스크립트(.yml) 작성

별표친대로
(repo이름)/.github/workflows/만들파일이름.yml

위치에 새 워크플로를 작성한다.

나의 경우는 이미 gradle.yml 이라는 파일이 존재하는데, 이 파일은 CI-CD용으로 main 브랜치에 push 이벤트에 대한 워크플로 파일이고, 우리가 원하는 것은 main 브랜치에 향하는 pull_request 이벤트에 대한 것이므로 둘을 분리했다. (관리나, 책임의 분리 관점에서도 이게 맞다고 생각했다)

4 - 1 간단한 버전

name: Assign Random Reviewer

on:
  pull_request:
    branches:
      - "develop"

jobs:
  assign-reviewer:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up jq
      run: sudo apt-get install -y jq

    - name: Select Random Reviewer
      id: select-reviewer
      run: |
        reviewers=$(curl -s -H "Authorization: token ${{ secrets.REVIEW_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/contributors | jq -r '.[].login')
        reviewer_array=($reviewers)
        random_index=$(($RANDOM % ${#reviewer_array[@]}))
        selected_reviewer=${reviewer_array[$random_index]}
        echo "Selected reviewer: $selected_reviewer"
        echo "::set-output name=reviewer::$selected_reviewer"

    - name: Add reviewer to PR
      run: |
        pr_number=${{ github.event.pull_request.number }}
        reviewer=${{ steps.select-reviewer.outputs.reviewer }}
        curl -s -X POST -H "Authorization: token ${{ secrets.REVIEW_TOKEN }}" -d '{"reviewers":["'"$reviewer"'"]}' "https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number/requested_reviewers"

    - name: Send Discord Notification
      run: |
        webhook_url=${{ secrets.DISCORD_WEBHOOK_URL }}
        reviewer=${{ steps.select-reviewer.outputs.reviewer }}
        pr_number=${{ github.event.pull_request.number }}
        pr_title=${{ github.event.pull_request.title }}
        pr_url=${{ github.event.pull_request.html_url }}

        payload=$(cat <<EOF
        {
          "content": "새로운 PR이 생성되었습니다. [#$pr_number] $pr_title\n@$reviewer 님, 아래 URL에서 PR을 리뷰 해 주세요!\n$pr_url"
        }
        EOF
        )

        curl -X POST -H "Content-Type: application/json" -d "$payload" $webhook_url

위에서 볼 수 있듯

  1. 환경을 세팅하고
  2. 깃헙 API 를 사용해서 리뷰어 목록을 가져오고, 그 중 랜덤한 인덱스에 해당하는 (즉 랜덤한) 유저를 고른다.
  3. 고른 유저를 PR reviewer 로 추가한다.
  4. 디스코드에 알림을 보낸다.

의 순서로 진행된다.


5. 테스트 해보기

이미 알고 계시겠지만, 워크플로우가 실패하면 아주 민망하다.

쌓여가는 커밋과...

무수한 실패들...

이를 방지하기 위해서, 로컬에서 Github Actions 워크플로우를 테스트 할 수 있는 ACT 라는 좋은 오픈소스가 존재한다.

Mac 기준으로

brew install act

로 설치 할 수 있고, docker 기반으로 이벤트를 발행시킬 수 있다 (push, pull_request...)

우리는 풀리퀘스트 시 알림을 보낼 목적이므로,

act pull_request

로 테스트해보자.

위와 같이 잘 뜬다. (pr 이 특정되진 않아서 pr 번호나, url 은 나타나지 않는다)

실제 PR시의 모습.


놀라운 사실

사실 위 워크플로우를 사용하면, 깃허브 아이디 기준으로 알림이 간다.

이것을 디스코드 멘션으로 바꾸는 것은 조금 짜치는 부분이기도 하고, 마스킹 할 자신이 없으므로...남기지 않는다

하지만 조금만 찾아보면 금방 찾을 수 있을 것!

더해서, 조그만 조직에서 적은 멤버들과 함께 관리되는 레포라면 위 같이 간단한 방식이 유용 할 수 있지만, 조금 더 크고 체계적으로 관리하기에는 아무래도 부족함이 느껴지는 것이 사실이다.

나의 경우는 SpringBoot 서버를 워크플로우 도중에 띄우기엔 너무 부담스러워서 (오래걸릴까봐) 시도하지 않았지만, 머찐 예제 에서는 다른 환경을 사용해서 적절한 PR 자동분배를 구현했다. 이 아티클도 참고가 되면 너무 좋을 것 같다.

0개의 댓글