MSG-413 feat: 대표 뱃지 설정 실연동 — 도감 뱃지 탭 편집모드(최대 2개 토글·랭크 링·프로필 미리보기) + PUT badges/featured #163
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: CI | |
| on: | |
| pull_request: | |
| branches: [develop, main] | |
| push: | |
| branches: [develop] | |
| # 같은 PR/브랜치에 연속 push 시 이전 실행 취소 | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| ci: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| # pnpm 버전은 루트 package.json의 packageManager 필드가 단일 출처 — version 입력 생략 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Setup Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version-file: .nvmrc | |
| cache: pnpm | |
| # CI 환경에서는 pnpm이 자동으로 frozen-lockfile 모드로 동작하지만 명시성을 위해 지정 | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| # 커밋된 스냅샷(openapi/api-docs.json)으로 재생성해 생성물 드리프트를 검사한다 (MSG-323). | |
| # 생성물 수기 수정·재생성 누락 시 실패. diff는 추적 파일만 잡으므로 신규 untracked | |
| # 파일은 git status --porcelain으로 병행 검출한다. 라이브 명세 curl은 CI에서 하지 | |
| # 않는다(스냅샷 갱신은 사람이 의도적으로). Lint 이전 배치 — 이후 게이트가 재생성본 기준. | |
| - name: OpenAPI codegen drift check | |
| run: | | |
| pnpm openapi-ts | |
| git diff --exit-code -- apps/web/src/shared/api/generated | |
| test -z "$(git status --porcelain apps/web/src/shared/api/generated)" | |
| # oxlint 단일 실행(MSG-386) — 범용 룰 + 커스텀 룰(토큰: tools/oxlint JS 플러그인, RN 경계: | |
| # 네이티브 no-restricted-imports/globals)을 루트 .oxlintrc.json 하나로 검사한다. eslint 제거됨. | |
| - name: Lint | |
| run: pnpm lint | |
| # oxfmt(Rust 기반 Prettier 호환 포매터) — 2026-08-03 전체 도입, printWidth 80(.oxfmtrc.json)으로 | |
| # 기존 코드 스타일과 정렬. --check만 실행(자동 수정 없음), 포맷 안 맞으면 실패. | |
| - name: Format check (oxfmt) | |
| run: pnpm format:check | |
| - name: Typecheck | |
| run: pnpm typecheck | |
| - name: Test | |
| run: pnpm test | |
| - name: Build | |
| run: pnpm build | |
| - name: Build Storybook | |
| run: pnpm build-storybook | |
| # optional 게이트 — 도입 초기(2026-08-03, MSG-307 후속)라 continue-on-error로 PR 머지를 막지 않는다. | |
| # 팀 검토 후 안정화되면 continue-on-error 줄을 제거해 필수 게이트로 승격한다. | |
| # nose.baseline.json은 도입 시점의 기존 중복(71 families)을 그대로 승인한 것 — 신규/변경분만 실패 대상. | |
| # 로컬 재실행: pnpm check:duplication (nose CLI 설치 필요 — https://github.com/corca-ai/nose) | |
| duplication: | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Setup Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version-file: .nvmrc | |
| cache: pnpm | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| # 버전은 로컬 개발 환경(brew install corca-ai/tap/nose)과 동일하게 고정 — 임의 업데이트로 | |
| # 인한 예기치 않은 신규 탐지 방식 변경을 방지. nose CLI 업그레이드 시 이 버전도 함께 올릴 것. | |
| - name: Install nose | |
| run: | | |
| curl --proto '=https' --tlsv1.2 -LsSf \ | |
| https://github.com/corca-ai/nose/releases/download/v0.20.0/nose-cli-installer.sh | sh | |
| echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" | |
| - name: Check code duplication (baseline — 신규 중복만 실패) | |
| run: pnpm check:duplication | |
| e2e: | |
| runs-on: ubuntu-latest | |
| continue-on-error: true | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Setup Node | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version-file: .nvmrc | |
| cache: pnpm | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| - name: Cache Playwright browsers | |
| id: playwright-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }} | |
| - name: Install Playwright browsers | |
| if: steps.playwright-cache.outputs.cache-hit != 'true' | |
| run: pnpm --filter web exec playwright install --with-deps chromium | |
| # cache hit 시: 브라우저 바이너리만 캐시되고 apt 의존성은 캐시 경로 밖이라 매번 재설치 필요 | |
| - name: Install Playwright OS dependencies | |
| if: steps.playwright-cache.outputs.cache-hit == 'true' | |
| run: pnpm --filter web exec playwright install-deps chromium | |
| # NOTE: pull_request 이벤트는 포크에서 열린 PR에 리포지토리 Secret을 노출하지 않는 게 | |
| # GitHub Actions 기본 동작이다 (보안 목적). 그 경우 VITE_NAVER_MAP_NCP_KEY_ID가 빈 값이 되어 | |
| # 네이버 지도 SDK 로딩이 실패하고 이 job은 항상 실패한다. 지금은 continue-on-error라 머지를 | |
| # 막지 않지만, 이 job을 필수 게이트로 승격하기 전에는 반드시 재확인할 것 — 사내 기여자만 | |
| # PR을 연다면 문제없으나(이 레포는 Private), 외부 포크 PR이 생기는 시점에 재발 가능. | |
| - name: E2E Test | |
| working-directory: apps/web | |
| run: pnpm test:e2e | |
| env: | |
| VITE_NAVER_MAP_NCP_KEY_ID: ${{ secrets.VITE_NAVER_MAP_NCP_KEY_ID }} | |
| - name: Upload Playwright report | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report | |
| path: apps/web/playwright-report/ | |
| retention-days: 7 |