PR 충돌? GitHub Actions이 먼저 알려드립니다

김유경·6일 전

들어가며

프로젝트를 진행하다 보면 동시에 작업하면서 PR이 쌓이게 됩니다. 이때 main/develop 브랜치에 새로운 커밋이 푸시되면, 기존에 열려 있던 PR이 충돌을 일으키는 일이 자주 발생합니다.

문제는 이런 충돌을 매번 직접 확인해야 한다는 점입니다. PR이 여러 개 쌓이면 어떤 PR에서 충돌이 발생했는지 파악하는 것만으로도 시간이 소요됩니다.

그래서 이번 글에서는 GitHub Actions를 활용해 PR 충돌을 자동으로 감지하고, 충돌이 발생한 PR을 Discord로 알림을 보내는 워크플로우를 어떻게 구현했는지 정리해보았습니다.


아키텍처 설계

워크플로우 트리거

on:
  pull_request:
    types: [opened, synchronize, reopened]
  push:
    branches: [main, develop]

두 가지 이벤트를 중심으로 충돌을 확인합니다.

  • pull_request: PR이 생성되거나 업데이트될 때
  • push: main/develop 브랜치에 커밋이 푸시될 때

핵심 구현

1. 환경 설정

- uses: actions/checkout@v4
  with:
    fetch-depth: 0
    token: ${{ secrets.PAT_KEY }}

- name: Setup
  run: |
    if ! command -v jq &> /dev/null; then
      sudo apt-get update && sudo apt-get install -y jq
    fi

fetch-depth: 0 옵션을 사용해 전체 Git 히스토리를 가져오고, private 레포지토리에 접근하기 위해 PAT을 설정합니다. 이후 JSON 처리를 위해 jq가 없으면 자동으로 설치되도록 구성했습니다.

2. PR 충돌 감지 로직

MERGE_BASE=$(git merge-base HEAD "origin/${PR_BASE}")
CONFLICTS=$(git merge-tree "$MERGE_BASE" HEAD "origin/${PR_BASE}" | grep -c "<<<<<<< ")

git merge-base로 두 브랜치가 분기되기 전의 공통 기반 커밋을 구한 뒤, git merge-tree로 실제 병합 없이 충돌 여부만 시뮬레이션하고, <<<<<<< 패턴 등장 여부를 검사해 충돌을 판단합니다.

3. Discord 알림

PAYLOAD=$(jq -n \
  --arg title "⚠️ PR 충돌 발생!" \
  --arg pr_info "[#${PR_NUMBER}](${PR_URL}) ${PR_TITLE}" \
  '{
    embeds: [{
      title: $title,
      color: 15158332,
      fields: [
        { name: "PR 정보", value: $pr_info, inline: false }
      ]
    }]
  }')

curl -X POST "${WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" \
  --fail --silent --show-error

충돌이 감지되면 jq로 JSON payload를 생성해 Discord Webhook으로 전송합니다.

4. 병렬 처리로 성능 개선

check_pr() {
  local PR_NUMBER=$1
  # ... 충돌 체크 로직 ...
}

export -f check_pr
echo "$OPEN_PRS" | xargs -I {} -P 5 bash -c 'check_pr "$@"' _ {}

xargs -P 5로 최대 5개의 PR을 동시에 체크합니다.


실제 사용 예시

시나리오 1: PR 생성/업데이트 시 충돌 감지

PR이 새로 생성되거나 업데이트되면, 워크플로우가 해당 PR과 base 브랜치를 비교해 충돌 여부를 판단합니다.

⚠️ PR 충돌 발생!
PR에서 충돌이 감지되었습니다.

PR 정보: #42 feat: 사용자 인증 구현
브랜치 정보: john | feature/auth → main

시나리오 2: main/develop에 Push된 변경으로 인한 충돌 감지

base 브랜치에 새로운 커밋을 push하면, 기존에 열려 있던 모든 PR을 다시 검사합니다. 이 과정에서 특정 PR이 충돌할 경우 알림을 전송합니다.

환경 설정

GitHub Secrets에 아래 값을 저장합니다.

secrets.PAT_KEY              # Personal Access Token
secrets.DISCORD_WEBHOOK_URL  # Discord 웹훅 URL

절대 코드에 직접 넣지 말고 반드시 Secrets 사용!


전체 코드

🔗 https://github.com/Kim-Yukyung/pr-conflict/blob/main/.github/workflows/conflict.yaml

0개의 댓글