From 65d59548457fec9e7c8b276e55b289ed427ee756 Mon Sep 17 00:00:00 2001 From: manNomi Date: Wed, 27 May 2026 23:03:27 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20main=20=EC=A7=81=EC=A0=91=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=A9=EC=A7=80=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .githooks/pre-push | 26 ++++++++++ .github/pull_request_template.md | 11 +++++ .github/workflows/pr-check.yml | 27 +++++++++++ README.md | 1 + docs/README.md | 1 + docs/codex/CODEX_PROMPTS.md | 2 +- docs/codex/NON_DEVELOPER_CODEX_GUIDE.md | 4 +- docs/codex/PR_ONLY_WORKFLOW.md | 63 +++++++++++++++++++++++++ package.json | 4 +- scripts/install-git-hooks.sh | 21 +++++++++ 10 files changed, 157 insertions(+), 3 deletions(-) create mode 100755 .githooks/pre-push create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/pr-check.yml create mode 100644 docs/codex/PR_ONLY_WORKFLOW.md create mode 100755 scripts/install-git-hooks.sh diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 0000000..316a3bf --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,26 @@ +#!/bin/sh + +protected_branch="main" + +while read -r local_ref local_sha remote_ref remote_sha; do + remote_branch=${remote_ref#refs/heads/} + + if [ "$remote_branch" = "$protected_branch" ]; then + cat >&2 <<'EOF' + +Blocked: direct push to main is not allowed. + +Use the PR flow instead: + git switch main + git pull --ff-only + git switch -c codex/your-change-name + git push -u origin codex/your-change-name + +Then open a pull request into main. + +EOF + exit 1 + fi +done + +exit 0 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..686616e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## 작업 내용 + +- + +## 검증 + +- + +## 참고 + +- diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..00fdb78 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,27 @@ +name: PR Check + +on: + pull_request: + branches: + - main + +jobs: + typecheck: + name: TypeScript typecheck + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Run typecheck + run: npm run typecheck diff --git a/README.md b/README.md index 41938f1..bd0117a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ EXPO_PUBLIC_MOCK_API_FAIL_ENDPOINTS=playlist.detail npm run web - [비개발자용 Codex 개발 가이드](docs/codex/NON_DEVELOPER_CODEX_GUIDE.md) - [Codex 요청 프롬프트 모음](docs/codex/CODEX_PROMPTS.md) - [UI 피드백 루프 운영 문서](docs/codex/UI_FEEDBACK_LOOP.md) +- [PR 전용 개발 흐름](docs/codex/PR_ONLY_WORKFLOW.md) - [Mock Server 안내](src/mock-server/README.md) ## Codex로 개발할 때 diff --git a/docs/README.md b/docs/README.md index d90c7ef..6088f0a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,6 +18,7 @@ Soundlog 문서는 목적별로 관리합니다. 공모전 기획, RN 프론트 - [비개발자용 Codex 개발 가이드](codex/NON_DEVELOPER_CODEX_GUIDE.md): Codex에게 개발을 맡기는 방식 - [Codex 요청 프롬프트 모음](codex/CODEX_PROMPTS.md): 바로 복사해서 쓸 수 있는 요청문 - [UI 피드백 루프 운영 문서](codex/UI_FEEDBACK_LOOP.md): 자연어 UI 수정 요청을 계획-리뷰-구현-리뷰 루프로 처리하는 방식 +- [PR 전용 개발 흐름](codex/PR_ONLY_WORKFLOW.md): `main` 직접 push를 막고 PR로만 병합하는 방식 ## Mock API diff --git a/docs/codex/CODEX_PROMPTS.md b/docs/codex/CODEX_PROMPTS.md index c9bd44d..eeea614 100644 --- a/docs/codex/CODEX_PROMPTS.md +++ b/docs/codex/CODEX_PROMPTS.md @@ -58,6 +58,6 @@ React Query 훅 또는 API facade까지 연결해줘. ## 커밋과 푸시 ```text -변경사항을 점검하고 불필요한 파일이 없는지 확인한 뒤 커밋하고 푸시해줘. +변경사항을 점검하고 불필요한 파일이 없는지 확인한 뒤 작업 브랜치에 커밋하고 PR 만들어줘. 커밋 메시지는 한국어로 간결하게 작성해줘. ``` diff --git a/docs/codex/NON_DEVELOPER_CODEX_GUIDE.md b/docs/codex/NON_DEVELOPER_CODEX_GUIDE.md index f1da540..2a636de 100644 --- a/docs/codex/NON_DEVELOPER_CODEX_GUIDE.md +++ b/docs/codex/NON_DEVELOPER_CODEX_GUIDE.md @@ -86,10 +86,12 @@ npm run typecheck를 실행하고, 구현이 끝난 뒤에는 아래처럼 요청하면 됩니다. ```text -변경사항 요약해주고, 불필요한 파일이 없는지 확인한 뒤 커밋하고 푸시해줘. +변경사항 요약해주고, 불필요한 파일이 없는지 확인한 뒤 작업 브랜치에 커밋하고 PR 만들어줘. 커밋 메시지는 한국어로 작성해줘. ``` +Soundlog는 `main`에 직접 push하지 않습니다. 모든 변경은 작업 브랜치에서 PR로 올립니다. 자세한 흐름은 `docs/codex/PR_ONLY_WORKFLOW.md`를 확인하세요. + ## 주의해야 할 요청 아래 내용은 사용자 경험이나 개인정보에 영향이 크므로 Codex가 질문하고 진행해야 합니다. diff --git a/docs/codex/PR_ONLY_WORKFLOW.md b/docs/codex/PR_ONLY_WORKFLOW.md new file mode 100644 index 0000000..472b8b7 --- /dev/null +++ b/docs/codex/PR_ONLY_WORKFLOW.md @@ -0,0 +1,63 @@ +# PR 전용 개발 흐름 + +Soundlog는 `main` 브랜치에 직접 push하지 않고, 모든 변경을 PR로 합치는 방식으로 관리합니다. + +## 팀원이 처음 해야 할 일 + +```bash +npm install +``` + +또는 이미 설치가 끝난 상태라면 아래 명령어로 Git hook을 활성화합니다. + +```bash +npm run setup:githooks +``` + +이 설정은 로컬 Git의 `core.hooksPath`를 `.githooks`로 지정하고, `main` 브랜치로 직접 push하는 행동을 차단합니다. + +## 개발 시작 + +```bash +git switch main +git pull --ff-only +git switch -c codex/my-change +``` + +작업 후에는 feature 브랜치만 push합니다. + +```bash +git push -u origin codex/my-change +``` + +그 다음 GitHub에서 `main`으로 Pull Request를 생성합니다. + +## 금지되는 흐름 + +```bash +git push origin main +git push origin HEAD:main +``` + +위 명령은 로컬 pre-push hook에서 차단됩니다. GitHub 저장소에서도 branch protection rule로 한 번 더 차단해야 합니다. + +## GitHub 저장소 보호 규칙 + +GitHub에서 `main` 브랜치에 아래 규칙을 적용합니다. + +- Require a pull request before merging +- Require approvals +- Require status checks to pass before merging +- Require branches to be up to date before merging +- Do not allow bypassing the above settings +- Include administrators + +## PR 검증 + +PR이 열리면 `.github/workflows/pr-check.yml`이 실행되어 TypeScript 타입 검사를 수행합니다. + +로컬에서도 PR을 만들기 전에 아래 명령을 실행합니다. + +```bash +npm run typecheck +``` diff --git a/package.json b/package.json index d46d90a..152bbdb 100644 --- a/package.json +++ b/package.json @@ -47,13 +47,15 @@ "ios": "expo start --ios", "web": "expo start --web", "web:clear": "expo start --web --clear", + "setup:githooks": "sh scripts/install-git-hooks.sh", "build:dev:android": "eas build --profile development --platform android", "build:dev:ios": "eas build --profile development --platform ios", "build:preview": "eas build --profile preview --platform all", "build:production": "eas build --profile production --platform all", "typecheck": "tsc --noEmit", "doctor": "npx expo-doctor", - "check": "npm run typecheck && npm run doctor" + "check": "npm run typecheck && npm run doctor", + "prepare": "sh scripts/install-git-hooks.sh" }, "private": true } diff --git a/scripts/install-git-hooks.sh b/scripts/install-git-hooks.sh new file mode 100755 index 0000000..44ef85a --- /dev/null +++ b/scripts/install-git-hooks.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -eu + +repo_root=$(git rev-parse --show-toplevel 2>/dev/null || true) + +if [ -z "$repo_root" ]; then + echo "Git repository not found. Skipping git hook setup." + exit 0 +fi + +cd "$repo_root" + +if [ ! -f ".githooks/pre-push" ]; then + echo ".githooks/pre-push not found. Skipping git hook setup." + exit 0 +fi + +chmod +x .githooks/pre-push +git config core.hooksPath .githooks + +echo "Git hooks enabled: core.hooksPath=.githooks"