남은 PR 디스코드 비동기 알림 CI 만들기 (CI로 코드리뷰 문화 활성화-1)
상황
개발은 잘 진행되고 있는 것 같은데, PR(pull request)는 계속 쌓이고, 점차 레거시 코드를 갖고 있기 때문에 이를 새로운 것으로 다시 병합하고 수정하는 시간들이 길어져 프로젝트에 들이는 시간대비 효율성이 나오는 것 같지 않다는 생각이 들었다.
추가로 개인적으로 코드 리뷰를 하는 것, 받는 것 자체가 재밌고, 개발의 원동력을 준다고 생각하는데, 이런 부분이 PR을 올린 시점으로부터 늦어지면 팀원 모두의 참여도에 영향을 미칠 것 같았다.
원인 분석
PR이 쌓이는 주된 원인이 무엇일까? develop 브랜치에 머지하기 전에 코드리뷰 및 승인을 받아야 하는데, 이 부분에서 너무 지체된다고 생각했다.
해결방안 모색
따라서 아직 머지 안된 PR들의 목록과 함께 매일 특정 시간에 알려주는 시스템이 있으면 남은 PR이 있다는 것을 팀원 모두가 인지하는데 도움을 줄 수 있다고 생각했고, 코드승인까지 지체되는 시간을 줄여 개발 생산성을 조금이라도 높일 수 있을 것 같다고 생각했다. 이를 적용할 수 있는 깃 액션 워크플로우를 만들었다.
리뷰 알람
깃허브 레포의 setting에서 webhook 설정이 가능해 PR이 올라왔을때나 다른 이벤트가 발생했을 때의 트리거를 통해 외부로 정보를 보낼 수 있다.
github marketplace 에서는 slack 에 대한 알림만 가능해서 우리 팀은 디스코드를 활성화 할 것이기 때문에 디스코드로 알림이 가도록 구현해보았다.
pr-remaining.yml
깃 액션을 시작할 수 있게끔 아래와 같이 yml 파일을 작성하였다.
name: Remaining PR
on:
schedule:
- cron: '0 7 * * *' # 매일 16:00 KTC (한국 시간 = UTC+9)
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: run remainingPR.py
run: |
python remainingPR.py
Cron 스케줄링을 사용할 수 있는 옵션이 있어 사용해봤다. 그런데, 실제로는 해당 16:00시각에 알림이 가는게 아니라, 16:08, 16:10 등 10분 정도 늦춰져 알림이 가는 현상이 발생했다.
이에 대해 알아보니, 엄청난 유저 수의 cron을 처리하다보니 큐에 쌓여 딜레이가 생겨서 이런 현상이 일어난다고 한다.
10분 정도는 작은 차이일 수 있지만, 이런 깃액션 cron 오차에 대해 알아보니, 어떤 케이스에서는 2시간 뒤에 작업이 실행된다는 글을 봐서 충분히 문제가 될 수 있겠다 생각하였다. 이부분에 대해서는 아래에 내용을 썼다.
remainingPR.py
pr-remaining.yml 에 사용된 remainingPR.py 은 다음과 같은 플로우로 진행된다.
# 디스코드 채널로 메세지 전송
def discord_send_message(text):
value = set_pull_requests_tags()
print(value)
now = datetime.datetime.now()
now_kst = now + datetime.timedelta(hours=9) # KST 변환
message = {
"content": "", # 메인 메시지는 비워두고
"embeds": [{
"title": "Merge 안된 PR 목록",
"description": str(text),
"color": 5814783, # 푸른색 계열
"footer": {
"text": f"알림 시각: {now_kst.strftime('%Y-%m-%d %H:%M:%S')} (KST)"
},
"fields": [
{
"name": "",
"value": value,
"inline": True
}
]
}]
}
response = requests.post(
DISCORD_URL,
json=message # data 대신 json을 사용하면 자동으로 JSON 직렬화됨
)
디스코드 채널로 메시지를 전송하는 부분의 로직은 위와 같다. 코드를 짜고 보니, 추후에 남은 PR이 없을 때, D-라벨이 없는 경우 예외처리를 해야될 것 같다.
Cron 제시간 실행되지 않는 문제
사실 이부분에 대해서 깊게 고민해야 될 필요성을 느낀 이유가 3가지가 있다.
1) 추후 2시간 정도의 지연 가능성을 방지하기 위해서
2) 확장 기능으로 특정 시간 간격으로 comment 알림, 서버 헬스 체크 등 다른 부분들을 추가해서 구현하려 했는데, 특정 시간이 늦춰지면 치명적인 알림 기능인 경우 지연되면 안됨
3) cron이 딜레이 되는 최대 시간대를 알 수 없음 ( 운이 나쁘면 2시간 딜레이 가능성 있음 )
따라서 반드시 정확한 시간에 실행이 되도록 해야된다. git action에서 제공하는 cron을 제 시각에 실행시킬 방법은 없는 것 같아 third party 를 도입하려 한다.
지금 생각한 것은 aws 에 서버리스 lambda를 사용하는 것.
일단 기존에 위 비동기 알림 기능을 위해 만들어두었던 테스트를 사용해서 구현 시도를 해보려 한다.
왜 cron을 큐로 처리 할까?
먼저 cron을 설정한 사람들은 당연히 먼저 실행되어야 할 것이고, 유저수가 엄청나서 2시간 가량 딜레이 되는 상황이다. 큐가 가장 적합하다고 해서 깃허브에서 큐를 사용했으나, third party를 사용하지 않고 깃허브의 큐 로직을 바꾼다면 다른 방법은 없을까?
참고