From 1211d577d4bf1dffab86dc9411400f0aab125d5c Mon Sep 17 00:00:00 2001 From: chaeyn Date: Thu, 1 Oct 2026 20:55:02 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20PR=20=EB=A6=AC=EB=B7=B0=20=ED=95=84?= =?UTF-8?q?=EC=88=98=20=EC=A1=B0=EA=B1=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agent/skills/pull-request/SKILL.md | 8 +++++--- .claude/skills/pull-request/SKILL.md | 8 +++++--- .codex/skills/pull-request/SKILL.md | 8 +++++--- .github/pull_request_template.md | 1 - .github/scripts/collaboration-policy.mjs | 9 +++++---- .github/scripts/collaboration-policy.test.mjs | 15 +++++++++++++-- docs/collaboration.md | 16 ++++++++-------- sync/pr-body.ts | 3 +-- 8 files changed, 42 insertions(+), 26 deletions(-) diff --git a/.agent/skills/pull-request/SKILL.md b/.agent/skills/pull-request/SKILL.md index 11fd5f6..b36e195 100644 --- a/.agent/skills/pull-request/SKILL.md +++ b/.agent/skills/pull-request/SKILL.md @@ -15,8 +15,8 @@ description: Framework 저장소의 Draft PR 생성, 검증 결과와 체크리 - 명사형 종결의 최상위 개조식 사용. 변경 내용·검증 결과는 각각 1~3개 항목 - 핵심 동작·영향·실제 결과만 기록. 구현 과정·작업 순서·시도한 방법·중첩 목록·홍보 문구 생략 - 중요한 미검증 범위와 API 계약·배포 조건 유지. 상세 설명은 Issue 또는 문서에 기록 -- 체크리스트는 해당 변경의 필수 검증과 리뷰 확인으로 구성. 미수행 항목 체크 금지 -- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환, 리뷰 반영 후 머지 +- 체크리스트는 변경 범위 확인과 필수 검증으로 구성. 미수행 항목 체크 금지 +- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환 후 머지 - 이슈 전체 완료는 `Closes #번호`, 부분 완료·참고는 `Refs #번호` - 본문은 파일과 `--body-file`로 전달. 문자열 `\n` 사용 금지 @@ -29,7 +29,9 @@ gh pr ready ## 병합 -사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·체크리스트·리뷰 확인 후 merge commit으로 병합한다. +리뷰는 선택사항이며 승인 리뷰·리뷰 체크·미해결 대화를 공통 머지 조건으로 요구하지 않는다. + +사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·검증 체크리스트 완료 후 merge commit으로 병합한다. ```bash head_branch=$(gh pr view --json headRefName --jq .headRefName) diff --git a/.claude/skills/pull-request/SKILL.md b/.claude/skills/pull-request/SKILL.md index 11fd5f6..b36e195 100644 --- a/.claude/skills/pull-request/SKILL.md +++ b/.claude/skills/pull-request/SKILL.md @@ -15,8 +15,8 @@ description: Framework 저장소의 Draft PR 생성, 검증 결과와 체크리 - 명사형 종결의 최상위 개조식 사용. 변경 내용·검증 결과는 각각 1~3개 항목 - 핵심 동작·영향·실제 결과만 기록. 구현 과정·작업 순서·시도한 방법·중첩 목록·홍보 문구 생략 - 중요한 미검증 범위와 API 계약·배포 조건 유지. 상세 설명은 Issue 또는 문서에 기록 -- 체크리스트는 해당 변경의 필수 검증과 리뷰 확인으로 구성. 미수행 항목 체크 금지 -- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환, 리뷰 반영 후 머지 +- 체크리스트는 변경 범위 확인과 필수 검증으로 구성. 미수행 항목 체크 금지 +- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환 후 머지 - 이슈 전체 완료는 `Closes #번호`, 부분 완료·참고는 `Refs #번호` - 본문은 파일과 `--body-file`로 전달. 문자열 `\n` 사용 금지 @@ -29,7 +29,9 @@ gh pr ready ## 병합 -사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·체크리스트·리뷰 확인 후 merge commit으로 병합한다. +리뷰는 선택사항이며 승인 리뷰·리뷰 체크·미해결 대화를 공통 머지 조건으로 요구하지 않는다. + +사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·검증 체크리스트 완료 후 merge commit으로 병합한다. ```bash head_branch=$(gh pr view --json headRefName --jq .headRefName) diff --git a/.codex/skills/pull-request/SKILL.md b/.codex/skills/pull-request/SKILL.md index 11fd5f6..b36e195 100644 --- a/.codex/skills/pull-request/SKILL.md +++ b/.codex/skills/pull-request/SKILL.md @@ -15,8 +15,8 @@ description: Framework 저장소의 Draft PR 생성, 검증 결과와 체크리 - 명사형 종결의 최상위 개조식 사용. 변경 내용·검증 결과는 각각 1~3개 항목 - 핵심 동작·영향·실제 결과만 기록. 구현 과정·작업 순서·시도한 방법·중첩 목록·홍보 문구 생략 - 중요한 미검증 범위와 API 계약·배포 조건 유지. 상세 설명은 Issue 또는 문서에 기록 -- 체크리스트는 해당 변경의 필수 검증과 리뷰 확인으로 구성. 미수행 항목 체크 금지 -- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환, 리뷰 반영 후 머지 +- 체크리스트는 변경 범위 확인과 필수 검증으로 구성. 미수행 항목 체크 금지 +- 실제 검증 후 결과·체크 상태 갱신, Ready for review 전환 후 머지 - 이슈 전체 완료는 `Closes #번호`, 부분 완료·참고는 `Refs #번호` - 본문은 파일과 `--body-file`로 전달. 문자열 `\n` 사용 금지 @@ -29,7 +29,9 @@ gh pr ready ## 병합 -사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·체크리스트·리뷰 확인 후 merge commit으로 병합한다. +리뷰는 선택사항이며 승인 리뷰·리뷰 체크·미해결 대화를 공통 머지 조건으로 요구하지 않는다. + +사용자 요청 범위와 저장소 승인 조건을 확인한다. 공통 규칙의 필수 검사·검증 체크리스트 완료 후 merge commit으로 병합한다. ```bash head_branch=$(gh pr view --json headRefName --jq .headRefName) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b7a7989..8d6dfb0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,7 +14,6 @@ - [ ] 변경 범위 확인 - [ ] 변경 범위에 맞는 검증 완료 - [ ] 검증 결과 및 미검증 범위 기재 -- [ ] 리뷰 반영 및 미해결 의견 확인 ## 관련 이슈 diff --git a/.github/scripts/collaboration-policy.mjs b/.github/scripts/collaboration-policy.mjs index 5a8c8c6..7eaf0cb 100644 --- a/.github/scripts/collaboration-policy.mjs +++ b/.github/scripts/collaboration-policy.mjs @@ -94,11 +94,12 @@ export function validatePullRequest(pr, { legacyPullRequestMaxNumber = 0 } = {}) const kind = pullRequestKind(pr, errors); bullets(sections.get('변경 내용'), '변경 내용', errors, { max: 3 }); bullets(sections.get('검증 결과'), '검증 결과', errors, { max: 3 }); - const checklist = bullets(sections.get('머지 체크리스트'), '머지 체크리스트', errors, { checklist: true }); - for (const required of ['변경 범위 확인', '리뷰 반영 및 미해결 의견 확인']) { + const checklist = bullets(sections.get('머지 체크리스트'), '머지 체크리스트', errors, { checklist: true }) + .filter(item => item.text !== '리뷰 반영 및 미해결 의견 확인'); + for (const required of ['변경 범위 확인']) { if (!checklist.some(item => item.text === required)) error(errors, `필수 체크 항목: ${required}`); } - if (checklist.length < 3) error(errors, '머지 체크리스트: 공통 확인 2개와 변경에 맞는 검증 항목 필요'); + if (checklist.length < 2) error(errors, '머지 체크리스트: 변경 범위 확인과 변경에 맞는 검증 항목 필요'); const references = []; for (const line of sections.get('관련 이슈') ?? []) { const reference = /^(?:- )?(Closes|Fixes|Resolves|Refs) (?:(?:[\w.-]+)\/(?:[\w.-]+))?#([1-9]\d*)$/iu.exec(line); @@ -119,7 +120,7 @@ export function validateReadiness(pr, config = {}) { if (result.legacy || pr.draft) return result; const { sections } = parseBody(pr.body, PR_HEADINGS); const items = bullets(sections.get('머지 체크리스트'), '머지 체크리스트', [] , { checklist: true }); - for (const item of items) if (!item.checked) error(result.errors, `머지 전 완료 필요: ${item.text}`); + for (const item of items) if (item.text !== '리뷰 반영 및 미해결 의견 확인' && !item.checked) error(result.errors, `머지 전 완료 필요: ${item.text}`); return result; } diff --git a/.github/scripts/collaboration-policy.test.mjs b/.github/scripts/collaboration-policy.test.mjs index bb61675..fada08e 100644 --- a/.github/scripts/collaboration-policy.test.mjs +++ b/.github/scripts/collaboration-policy.test.mjs @@ -20,7 +20,6 @@ const body = `## 변경 내용 - [x] 변경 범위 확인 - [x] 회귀 테스트 완료 - [ ] 실기기 반복 진입 확인 -- [x] 리뷰 반영 및 미해결 의견 확인 ## 관련 이슈 @@ -53,9 +52,21 @@ test('체크 후 같은 PR의 머지 검사 통과', () => { assert.deepEqual(validateReadiness({ ...pr, draft: false, body: body.replace('- [ ]', '- [x]') }).errors, []); }); test('필수 공통 확인 항목 삭제로 머지 검사를 우회하지 못함', () => { - assert.ok(validatePullRequest({ ...pr, body: body.replace('- [x] 리뷰 반영 및 미해결 의견 확인\n', '') }).errors.length); + assert.ok(validatePullRequest({ ...pr, body: body.replace('- [x] 변경 범위 확인\n', '') }).errors.length); assert.ok(validatePullRequest({ ...pr, body: body.replace('- [x] 회귀 테스트 완료\n- [ ] 실기기 반복 진입 확인\n', '') }).errors.length); }); +test('리뷰 없는 Ready PR과 기존 미완료 리뷰 체크는 머지 허용', () => { + const ready = { ...pr, draft: false, body: body.replace('- [ ]', '- [x]') }; + assert.deepEqual(validateReadiness(ready).errors, []); + const legacyReview = ready.body.replace('## 관련 이슈', '- [ ] 리뷰 반영 및 미해결 의견 확인\n\n## 관련 이슈'); + assert.deepEqual(validateReadiness({ ...ready, body: legacyReview }).errors, []); +}); +test('변경 범위와 검증 한 개만으로 Ready PR 머지 허용', () => { + const minimal = body.replace('- [ ] 실기기 반복 진입 확인\n', ''); + assert.deepEqual(validateReadiness({ ...pr, draft: false, body: minimal }).errors, []); + const reviewOnly = minimal.replace('- [x] 회귀 테스트 완료', '- [ ] 리뷰 반영 및 미해결 의견 확인'); + assert.ok(validatePullRequest({ ...pr, body: reviewOnly }).errors.length); +}); test('미완료 항목이 있는 Issue는 진행 추적 허용', () => assert.deepEqual(validateIssue(issue).errors, [])); test('GitHub 웹 Issue Form의 H3 섹션도 같은 양식으로 검사', () => assert.deepEqual(validateIssue({ ...issue, body: issue.body.replaceAll('## ', '### ') }).errors, [])); test('Issue의 완료 기준 누락 거부', () => assert.ok(validateIssue({ ...issue, body: issue.body.split('## 완료 기준')[0] }).errors.length)); diff --git a/docs/collaboration.md b/docs/collaboration.md index 9464196..87b9afc 100644 --- a/docs/collaboration.md +++ b/docs/collaboration.md @@ -59,7 +59,6 @@ Issue·브랜치·PR 타입은 `feat/fix/chore/refactor` 사용. 개별 커밋 - [x] 변경 범위 확인 - [x] 관련 테스트 완료 - [ ] 실제 기기 반복 진입 확인 -- [ ] 리뷰 반영 및 미해결 의견 확인 ## 관련 이슈 @@ -67,12 +66,12 @@ Issue·브랜치·PR 타입은 `feat/fix/chore/refactor` 사용. 개별 커밋 ``` - 구현 중 Draft 생성 허용. 검증 전에는 `검증 대기`와 미완료 체크박스 기재 -- 체크리스트는 해당 변경의 머지에 필요한 항목만 작성. 검증 항목과 리뷰 확인 항목 포함 -- `변경 범위 확인`, `리뷰 반영 및 미해결 의견 확인`은 고정 필수 항목. 해당 변경의 검증 항목을 하나 이상 추가 +- 체크리스트는 해당 변경의 머지에 필요한 항목만 작성. 변경 범위 확인과 검증 항목 포함 +- `변경 범위 확인`은 고정 필수 항목. 해당 변경의 검증 항목을 하나 이상 추가 - 수행하지 않은 검증 체크 금지. 빌드·실기기 검증이 미대상이면 결과에 이유 기재 - 검증 결과는 실행 명령·대상·통과 개수·핵심 결과로 요약 -- 검증 후 결과·체크 상태 갱신, Ready for review 전환, 리뷰 반영 후 머지 -- 리뷰는 요청한 리뷰 또는 자가 검토의 실제 확인 결과로 체크. 체크만으로 승인 리뷰를 대체하지 않음 +- 검증 후 결과·체크 상태 갱신, Ready for review 전환 후 머지 +- 리뷰는 선택사항. 승인 리뷰·리뷰 체크·미해결 대화를 공통 머지 조건으로 요구하지 않음 - `Closes #번호`는 이슈 전체 완료, `Refs #번호`는 일부 완료 또는 참고에 사용 - 중요 미검증 범위를 후속 Issue로 분리한 경우 `검증 결과`에 범위와 번호 기재. 필수 항목을 삭제해 검사만 통과시키지 않음 @@ -88,10 +87,11 @@ Issue·브랜치·PR 타입은 `feat/fix/chore/refactor` 사용. 개별 커밋 ## 자동 검사와 적용 시점 - `Collaboration / PR format`: 제목·브랜치·섹션 순서·개조식·문장형 종결·항목 수·이슈 연결 및 연결 Issue 본문 검사 -- `Collaboration / merge readiness`: Draft의 미완료 체크 허용, Ready PR의 미완료 체크 차단 +- `Collaboration / merge readiness`: Draft의 미완료 검증 체크 허용, Ready PR의 미완료 검증 체크 차단 +- 기존 PR 본문의 `리뷰 반영 및 미해결 의견 확인` 체크는 형식·머지 검사에서 제외. 검증 항목으로 계산하지 않음 - `Collaboration / policy tests`: 검사기의 정상·거부·Draft·Ready 전환 회귀 검증 - `Collaboration / Issue format`: 새 Issue의 본문 검사, 오류 시 `needs-format` 표시, 수정 후 표시 제거 -- CI는 내용의 사실성·검증 충분성·과정 서술의 의미를 판정하지 않음. 작성자와 리뷰어가 확인 +- CI는 내용의 사실성·검증 충분성·과정 서술의 의미를 판정하지 않음. 작성자가 확인 - `.github/collaboration-policy.json`의 기존 번호 이하 기록은 새 양식 소급 적용 제외 - 적용 기준 파일은 저장소별 관리. 하네스 동기화 대상에서 제외하여 재동기화 시 기준 유지 @@ -109,7 +109,7 @@ gh pr merge --merge --match-head-commit "$head_sha" \ --subject "merge: $head_branch" --body "" ``` -필수 검사와 리뷰 확인 후 병합. GitHub 웹에서도 같은 제목·빈 본문 사용. 병합 후 실제 커밋의 제목·본문·두 부모 확인. 이 명령 예시는 사용자 승인·저장소 권한·요청 범위를 확장하지 않음. +필수 검사와 검증 체크 완료 후 병합. GitHub 웹에서도 같은 제목·빈 본문 사용. 병합 후 실제 커밋의 제목·본문·두 부모 확인. 이 명령 예시는 사용자 승인·저장소 권한·요청 범위를 확장하지 않음. ## 규칙 원본 diff --git a/sync/pr-body.ts b/sync/pr-body.ts index 7e8a87f..a931ef8 100644 --- a/sync/pr-body.ts +++ b/sync/pr-body.ts @@ -8,14 +8,13 @@ export const syncPullRequestBody = `## 변경 내용 ## 검증 결과 - 동기화 변경 파일 생성 완료 -- 대상 저장소 검증·리뷰 대기 +- 대상 저장소 검증 대기 ## 머지 체크리스트 - [ ] 변경 범위 확인 - [ ] 대상 저장소 검증 완료 - [ ] 검증 결과 및 미검증 범위 기재 -- [ ] 리뷰 반영 및 미해결 의견 확인 ## 관련 이슈