generated from ttipo/project-base
Initial commit
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
## 무엇을 · 왜
|
||||
|
||||
<!-- 무엇을 바꿨고 왜 필요한지 적습니다. "무엇을"은 diff 가 말해주므로 "왜"에 비중을 둡니다. -->
|
||||
|
||||
## 확인 방법
|
||||
|
||||
<!-- 리뷰어가 동작을 확인할 수 있는 절차나 명령을 적습니다. -->
|
||||
|
||||
## 영향 범위
|
||||
|
||||
- [ ] backend
|
||||
- [ ] frontend
|
||||
- [ ] flutter
|
||||
- [ ] docker / 인프라
|
||||
- [ ] 규칙 문서(.claude/)
|
||||
|
||||
> **공유 계약(에러 코드 · 응답 포맷 · 페이지네이션 · API 규약)을 바꿨다면**
|
||||
> 세 스택에 미치는 영향을 아래에 구체적으로 적어 주세요.
|
||||
|
||||
## 체크리스트
|
||||
|
||||
<!-- 자세한 항목은 .claude/rules/checklist.md 참조 -->
|
||||
|
||||
- [ ] 린트/분석 통과 (Warning 0) · 변경 영역 테스트 통과
|
||||
- [ ] 주석 한국어, 매직 넘버·하드코딩 문자열 없음
|
||||
- [ ] 사용자 노출 실패는 모두 에러 코드와 함께 처리 (`BusinessException` / `error.code` 분기)
|
||||
- [ ] 에러 코드를 바꿨다면 `npm run sync:error-codes` 실행 후 생성 파일까지 커밋
|
||||
- [ ] 민감정보 미커밋 (`*.example` 값은 placeholder)
|
||||
- [ ] 로그에 비밀번호·토큰·요청 본문 전체가 남지 않음
|
||||
@@ -0,0 +1,57 @@
|
||||
name: CI (Flutter)
|
||||
|
||||
# Flutter 는 기본 CI 에서 분리되어 있다.
|
||||
#
|
||||
# 이유: SDK 다운로드로 매 실행마다 수 분이 걸리는데,
|
||||
# backend/frontend 만 고친 커밋에서는 검사할 것이 없다.
|
||||
#
|
||||
# 언제 도는가:
|
||||
# - flutter/ 아래 파일이 바뀐 푸시·PR (= 실제로 Flutter 를 쓸 때 자동으로)
|
||||
# - Actions 탭의 "Run workflow" 버튼으로 수동 실행
|
||||
#
|
||||
# 모바일 앱을 아예 쓰지 않는 프로젝트라면 이 파일을 지우면 된다.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'flutter/**'
|
||||
- '.github/workflows/ci-flutter.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'flutter/**'
|
||||
- '.github/workflows/ci-flutter.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
flutter:
|
||||
name: Flutter (analyze · test)
|
||||
runs-on: ubuntu-latest
|
||||
# 멈춘 잡이 러너를 무한 점유하지 않도록 상한을 둔다
|
||||
timeout-minutes: 25
|
||||
defaults:
|
||||
run:
|
||||
working-directory: flutter
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
cache: true
|
||||
|
||||
# .env 는 pubspec 의 asset 이라 없으면 analyze 가 경고를 낸다
|
||||
- name: Prepare .env
|
||||
run: cp .env.example .env
|
||||
|
||||
- run: flutter pub get
|
||||
|
||||
- name: Analyze
|
||||
run: flutter analyze
|
||||
|
||||
- name: Test
|
||||
run: flutter test
|
||||
@@ -0,0 +1,135 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
# 같은 브랜치에서 새 푸시가 오면 이전 실행을 취소한다
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
backend:
|
||||
name: Backend (lint · test · e2e · build)
|
||||
runs-on: ubuntu-latest
|
||||
# 멈춘 잡이 러너를 무한 점유하지 않도록 상한을 둔다
|
||||
timeout-minutes: 20
|
||||
defaults:
|
||||
run:
|
||||
working-directory: backend
|
||||
# e2e 는 응답 계약을 실제 HTTP 로 검증하므로 DB 가 필요하다.
|
||||
#
|
||||
# ⚠️ 호스트 포트 매핑(ports)을 두지 않는다.
|
||||
# Gitea Actions 러너는 잡을 **컨테이너로** 실행하고 서비스와 같은 네트워크에 붙여준다.
|
||||
# 따라서 서비스 이름(postgres)으로 바로 접근할 수 있고, 호스트 포트는 필요 없다.
|
||||
# 오히려 개발 DB 가 이미 5432 를 쓰고 있으면 충돌해 잡 전체가 시작조차 못 한다.
|
||||
# (GitHub Actions 는 잡이 VM 위에서 직접 돌아 localhost + ports 를 쓰는 점이 다르다)
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
env:
|
||||
POSTGRES_USER: ci_user
|
||||
POSTGRES_PASSWORD: ci_password
|
||||
POSTGRES_DB: ci_db
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U ci_user -d ci_db"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: npm
|
||||
cache-dependency-path: backend/package-lock.json
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# Warning 0 (.claude/rules/checklist.md)
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Test
|
||||
run: npm run test
|
||||
|
||||
# 표준 응답 래퍼·에러 코드·traceId 계약 검증 (.claude/rules/response-format.md)
|
||||
- name: E2E test
|
||||
run: npm run test:e2e
|
||||
env:
|
||||
NODE_ENV: test
|
||||
# 서비스 컨테이너의 네트워크 별칭 (localhost 는 잡 컨테이너 자신을 가리킨다)
|
||||
DB_HOST: postgres
|
||||
DB_PORT: 5432
|
||||
DB_USER: ci_user
|
||||
DB_PASSWORD: ci_password
|
||||
DB_NAME: ci_db
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
frontend:
|
||||
name: Frontend (lint · type-check · test)
|
||||
runs-on: ubuntu-latest
|
||||
# 멈춘 잡이 러너를 무한 점유하지 않도록 상한을 둔다
|
||||
timeout-minutes: 15
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Test
|
||||
run: npm run test:unit -- --run
|
||||
|
||||
error-codes-sync:
|
||||
name: 에러 코드 SSOT 동기화 검사
|
||||
runs-on: ubuntu-latest
|
||||
# 멈춘 잡이 러너를 무한 점유하지 않도록 상한을 둔다
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: npm
|
||||
cache-dependency-path: backend/package-lock.json
|
||||
|
||||
- name: Install backend deps
|
||||
working-directory: backend
|
||||
run: npm ci
|
||||
|
||||
# 레지스트리만 고치고 sync 를 안 돌린 경우를 잡아낸다.
|
||||
# 생성 파일이 최신이면 diff 가 비어 있어야 한다.
|
||||
- name: Regenerate client error lexicons
|
||||
working-directory: backend
|
||||
run: npm run sync:error-codes
|
||||
|
||||
- name: Fail if generated files are stale
|
||||
run: |
|
||||
if ! git diff --exit-code -- \
|
||||
frontend/src/shared/constants/error-codes.generated.ts \
|
||||
flutter/lib/core/api/error_lexicon.g.dart; then
|
||||
echo ""
|
||||
echo "::error::에러 코드 생성 파일이 레지스트리와 어긋났습니다."
|
||||
echo "backend 에서 'npm run sync:error-codes' 를 실행하고 생성 파일을 함께 커밋하세요."
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user