feat: 학교 이메일 인증으로 HomeUniversity 자동 매핑 #9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: FF-Only Merge to Master | |
| on: | |
| pull_request: | |
| types: [labeled] | |
| check_suite: | |
| types: [completed] | |
| jobs: | |
| ff-merge: | |
| if: | | |
| (github.event_name == 'pull_request' && github.event.label.name == 'ready-to-merge') || | |
| (github.event_name == 'check_suite' && github.event.check_suite.conclusion == 'success') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: PR 조회 및 조건 검증 | |
| id: validate | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| let prNumber, headSha; | |
| if (context.eventName === 'pull_request') { | |
| const pr = context.payload.pull_request; | |
| if (pr.base.ref !== 'master' || pr.head.ref !== 'develop' || pr.state !== 'open') { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| // 레이블을 부착한 주체의 저장소 권한 확인 | |
| const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| username: context.payload.sender.login, | |
| }); | |
| if (!['admin', 'write'].includes(perm.permission)) { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| prNumber = pr.number; | |
| headSha = pr.head.sha; | |
| } else { | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| base: 'master', | |
| head: `${context.repo.owner}:develop`, | |
| }); | |
| if (prs.length === 0) { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| prNumber = prs[0].number; | |
| headSha = prs[0].head.sha; | |
| if (context.payload.check_suite.head_sha !== headSha) { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| } | |
| // ready-to-merge 레이블 확인 | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber, | |
| }); | |
| const hasLabel = pr.labels.some(l => l.name === 'ready-to-merge'); | |
| if (!hasLabel) { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| // CI 상태 확인 | |
| const { data: { check_runs } } = await github.rest.checks.listForRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: headSha, | |
| per_page: 100, | |
| }); | |
| const ciRuns = check_runs.filter(r => r.name !== context.job); | |
| const allPassed = ciRuns.length > 0 && ciRuns.every(r => | |
| r.status === 'completed' && | |
| ['success', 'skipped', 'neutral'].includes(r.conclusion) | |
| ); | |
| if (!allPassed) { | |
| core.setOutput('ready', 'false'); | |
| return; | |
| } | |
| core.setOutput('ready', 'true'); | |
| core.setOutput('head_sha', headSha); | |
| - name: Checkout | |
| if: steps.validate.outputs.ready == 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.PAT }} | |
| fetch-depth: 0 | |
| - name: Git 설정 | |
| if: steps.validate.outputs.ready == 'true' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: develop 변경 여부 검증 | |
| if: steps.validate.outputs.ready == 'true' | |
| run: | | |
| APPROVED_SHA="${{ steps.validate.outputs.head_sha }}" | |
| CURRENT_SHA=$(git rev-parse origin/develop) | |
| if [ "$APPROVED_SHA" != "$CURRENT_SHA" ]; then | |
| echo "레이블 부착 이후 develop이 변경되었습니다." | |
| echo " 레이블 시점 SHA: $APPROVED_SHA" | |
| echo " 현재 SHA: $CURRENT_SHA" | |
| exit 1 | |
| fi | |
| - name: FF-Only merge develop → master | |
| if: steps.validate.outputs.ready == 'true' | |
| run: | | |
| git checkout master | |
| git merge --ff-only ${{ steps.validate.outputs.head_sha }} | |
| git push origin master |