diff --git a/.github/workflows/preview-promotion.yml b/.github/workflows/preview-promotion.yml new file mode 100644 index 0000000..9422264 --- /dev/null +++ b/.github/workflows/preview-promotion.yml @@ -0,0 +1,73 @@ +name: Auto Main PR + +on: + push: + branches: + - preview + +# PR 생성과 수정은 GitHub App 토큰으로 하므로 기본 토큰은 체크아웃용 읽기 권한만 둔다. +permissions: + contents: read + +# 연달아 머지되면 PR 생성이 겹칠 수 있으므로, 목록을 매번 새로 계산하는 최신 실행만 남긴다. +concurrency: + group: preview-promotion + cancel-in-progress: true + +jobs: + create-or-update-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create GitHub App token + id: app-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Create or Update Pull Request + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_REPO: ${{ github.repository }} + shell: bash + run: | + # if 조건 안에서는 rev-list가 실패해도 멈추지 않으므로 변수에 먼저 담는다. + count=$(git rev-list --count origin/main..origin/preview) + if [ "$count" -eq 0 ]; then + echo "main에 반영할 변경 사항이 없습니다." + exit 0 + fi + + # preview에 머지된 PR만 모으기 위해 preview의 first-parent 머지 커밋에서 PR 번호를 뽑는다. + pr_numbers=$(git log origin/main..origin/preview --first-parent --merges --format='%s' \ + | sed -n 's/^Merge pull request #\([0-9]*\) .*/\1/p') + + { + echo "## 작업 요약" + echo "Preview 브랜치의 최신 변경 사항을 Main 브랜치로 반영합니다." + echo + echo "## 포함된 PR" + if [ -z "$pr_numbers" ]; then + echo "- 없음" + fi + for number in $pr_numbers; do + gh pr view "$number" --json number,title,author \ + --jq '"- #\(.number) \(.title) (@\(.author.login))"' + done + } > pr-body.md + + existing=$(gh pr list --base main --head preview --state open --json number --jq '.[0].number // empty') + + if [ -n "$existing" ]; then + gh pr edit "$existing" --body-file pr-body.md + else + gh pr create --base main --head preview \ + --title "[배포 대기] main 최신화" \ + --body-file pr-body.md \ + --label "🌿 main" + fi