Skip to content

chore(week2): photo/admin form retrofit + CI + Deploy + retro#31

Merged
peterabcd merged 4 commits into
devfrom
chore/week2-wrapup
Jun 5, 2026
Merged

chore(week2): photo/admin form retrofit + CI + Deploy + retro#31
peterabcd merged 4 commits into
devfrom
chore/week2-wrapup

Conversation

@peterabcd

@peterabcd peterabcd commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

2주차 마무리 한 PR. 작은 작업 4개를 commit 단위로 분리, 머지는 한 번.

Closes #5, #22. 사진 폼/admin 폼 retrofit + Week 2 회고는 별도 issue 없음 — 본문 기재.

Commits (review 단위)

1. fix(forms): SKILL 4.5 retrofit — photo & admin members inline alert + dedupe

PR #30 에 새로 박은 SKILL §4.5 폼 표준 체크리스트를 이미 있는 폼에 소급 적용.

  • 사진 업로드/교체/삭제 폼: useActionState + ErrorAlert + SubmitButton. 15MB 초과 / MIME 거부 / 빈 파일 → inline alert.
  • admin 승인/거절 폼: 같은 패턴. "본인은 본인을 승인할 수 없습니다." 같은 메시지를 throw 대신 alert.
  • 변경 모듈: photo-actions.ts, PhotoSection.tsx (server→client), PhotoReplaceButton.tsx (props 통해 부모 action 공유), app/admin/members/actions.ts, _components/PendingMemberActions.tsx (new).

2. chore(ci): typecheck + lint + build on PR/push (#5)

.github/workflows/ci.yml. PR to dev/main + dev/main push 트리거.

  • Node 22 + pnpm 11.5.1 + pnpm store 캐시 + .next/cache 캐시
  • pnpm install --frozen-lockfiledb:generatetypechecklintbuild
  • Build env 에 dummy AUTH_*/DATABASE_URL 주입 (build 단계에 필요)
  • Concurrency: 같은 ref 새 push 시 이전 run 취소
  • Timeout 10분
  • 호스트(나) 가 Settings → Branches 에서 'check' 통과를 dev/main 보호 룰로 등록 (코드 변경 X)

3. chore(deploy): GH Actions SSH deploy pipeline (#22)

.github/workflows/deploy.yml + deploy/README.md 의 secret 등록 절차.

  • trigger: push to dev (→ staging), main (→ prod), workflow_dispatch
  • build job: Docker Buildx + ghcr.io push. 태그 <target>-<sha7> + <target> (latest 역할). GHA cache 사용.
  • deploy job: appleboy/ssh-action 으로 N100 접속, docker compose pull && up -d (project name 으로 staging/prod 격리)
  • Environments: staging (자동) / prod (수동 승인 가능)
  • Sanity check: secret 누락 시 즉시 명시적 에러
  • 필요 secrets (사용자 등록): N100_HOST, N100_USER, N100_SSH_KEY

4. docs(retro): Week 2 회고 + Home toc

docs/wiki/Retrospective-Week2.md 신설. Home 색인 갱신.

  • 두 사고 (silent noop, double submit) 의 근본 원인 분석 — "OOS 미루기 핑계", "fidelity 통과 ≠ UX 통과"
  • 3주차에 들고 가는 5가지 습관 변화

Fidelity check (06)

  • 1. spec (.gjc/specs/week2-wrapup.md) acceptance 1:1 매칭
  • 2. spec 밖 추가 없음. 의도적 묶음 (4 commit 1 PR) 은 spec 본문에 명시
  • 3. TODO/stub 없음
  • 4. 합의된 접근법 그대로 (Server Action + useActionState/useFormStatus, GHCR + SSH deploy, Docker compose project name 분리)
  • 5. pnpm typecheck/lint/build 4 commit 모두 통과 (마지막 회고는 docs 라 skip)
  • 6. diff: 4 commit 별로 응집 (코드/CI/Deploy/Docs 분리)
  • 7. E2E — 머지 후 사용자 직접 (negative case 머릿속 시뮬레이션 명시):
    • 사진 폼: 빈 파일 / 16MB / .pdf 업로드 → 각각 alert. [올리기] 더블 클릭 → 1번만 동작.
    • admin 폼: 본인 [승인] → "본인은 본인을 승인할 수 없습니다." alert (페이지 그대로). [승인] 더블 클릭 → 1번만.
    • CI: 이 PR open 자체가 첫 검증 — Actions 탭에서 ci.yml 동작 확인. 통과 시 그 자체가 acceptance.
    • Deploy: secret 등록 + dev 머지 → Actions 탭에서 deploy.yml 두 job 동작. N100 에서 docker ps 로 컨테이너 갱신 확인.

호스트(너) 작업

머지 후:

  1. GitHub Actions 탭에서 ci.yml 통과 여부 확인 (이 PR 자체가 첫 trigger)
  2. Settings → Branches 에서 dev/main 에 'check' 통과 필수로 추가 (옵션)
  3. Deploy 사용하려면 secret 등록:
    ssh-keygen -t ed25519 -C "gh-actions-murun-deploy" -f ~/.ssh/n100_gh_deploy
    cat ~/.ssh/n100_gh_deploy.pub >> ~/.ssh/authorized_keys  # N100 에서
    gh secret set N100_SSH_KEY < ~/.ssh/n100_gh_deploy
    gh secret set N100_HOST --body "<N100 ip 또는 ddns>"
    gh secret set N100_USER --body "<N100 ssh user>"
  4. (옵션) prod environment 보호 추가 — Settings → Environments → "prod" → Required reviewers 본인
  5. N100 에서 1회 init (deploy/README.md §0 참고)
  6. 2주차 결과 슬랙 랜덤 채널 공유 + Week 2 회고 read-through

다음 PR 후보 (Week 3 진입 시)

추천: (a) → (b) 순. dogfooding 1회 후 실제로 어색한 부분이 다음 PR 우선순위를 결정.

peterabcd added 4 commits June 4, 2026 21:30
… dedupe

PR #30 에 박은 폼 표준 체크리스트(SKILL.md §4.5)를 이미 있는 폼에 소급 적용.

Photo upload (app/sessions/[id]/photo-actions.ts + PhotoSection.tsx):
- uploadSessionPhoto / removeSessionPhoto 시그니처를 useActionState 패턴
  ((prev, formData) => Promise<{ ok, error? }>) 으로 변경.
- 검증 실패 (15MB 초과 / MIME 거부 / 빈 파일 / 세션 id 불량) 시 throw 대신
  명시적 PhotoResult.error 반환.
- PhotoSection 을 server → client component 로 (useActionState).
- 업로드/교체/삭제 모두 SubmitButton (useFormStatus) — pending 중 disabled
  + 라벨 교체.
- 사진 우측 [교체] 버튼은 부모의 useActionState formAction 을 props 로 받음
  → alert/pending 상태가 한 곳에서 관리됨.

Admin members (app/admin/members/actions.ts + page.tsx + _components):
- approveUser / rejectUser 시그니처 동일 패턴.
- 'cannot approve/reject self' 를 throw 대신 inline alert 메시지로.
- 페이지 (server component) 가 PendingMemberActions (client) 를 행마다 렌더.
- 두 버튼 ([승인]/[거절]) 이 같은 row 의 alert 영역 공유.

검증된 회귀 항목:
- 사진 업로드 [올리기] 빠른 더블 클릭 → 첫 클릭 후 button disabled.
- 본인 [승인] 시도 → '본인은 본인을 승인할 수 없습니다.' alert, 페이지 그대로.
- 빌드 9 → 10 routes, /sessions/[id] +1.2kB (client form 추가분).

Spec: .gjc/specs/week2-wrapup.md §1
.github/workflows/ci.yml — PR to dev/main 과 dev/main push 에서 동작.

Jobs:
- Setup Node 22 + pnpm 11.5.1 (lockfile 의 packageManager 와 일치)
- pnpm store 캐시 (lockfile hash 기반)
- .next/cache 캐시 (ts/tsx hash 기반)
- pnpm install --frozen-lockfile (lockfile drift 차단)
- pnpm db:generate (postinstall 보강)
- typecheck → lint → build 직렬
- build env: dummy 값 주입 (auth/db url 필요)

Concurrency: 같은 ref 의 새 push 가 들어오면 이전 run 취소.
Timeout: 10분.

브랜치 보호 (Settings → Branches) 설정으로 'check' 통과 강제는 호스트(나)
가 main, dev 두 곳에 별도 등록 — 코드 변경 X.
.github/workflows/deploy.yml + deploy/README.md secret 등록 절차.

Workflow:
- trigger: push to dev (→ staging), main (→ prod), 또는 workflow_dispatch
- build job: Docker Buildx + GHCR (ghcr.io) push, GHA cache 사용
  태그: '<target>-<sha7>' + '<target>' (latest 역할)
- deploy job: appleboy/ssh-action 으로 N100 접속,
  docker compose pull && up -d (project name 으로 staging/prod 분리)
- concurrency: 같은 ref 의 동시 배포 금지
- environment: GitHub Environments 의 'staging' / 'prod' 사용 (prod 는
  수동 승인 가능)
- Sanity check 단계: secret 누락 시 명시적 에러로 즉시 실패

필요 secrets (사용자 직접 등록):
- N100_HOST / N100_USER / N100_SSH_KEY
- GITHUB_TOKEN 은 자동 (GHCR push 권한 위해 permissions.packages: write)

deploy/README.md:
- '0. CI/CD 사용 시' 섹션 신설 — secret 등록 절차, SSH key 생성, prod
  environment 보호.
- 기존 '1. 첫 배포 (수동)' 은 'CI/CD 우회/디버깅' 으로 강등 (호스트 init
  1회는 여전히 필요)
@peterabcd peterabcd merged commit 55a56de into dev Jun 5, 2026
1 check passed
@peterabcd peterabcd deleted the chore/week2-wrapup branch June 5, 2026 02:58
peterabcd added a commit that referenced this pull request Jun 7, 2026
* fix(forms): SKILL 4.5 retrofit — photo & admin members inline alert + dedupe

PR #30 에 박은 폼 표준 체크리스트(SKILL.md §4.5)를 이미 있는 폼에 소급 적용.

Photo upload (app/sessions/[id]/photo-actions.ts + PhotoSection.tsx):
- uploadSessionPhoto / removeSessionPhoto 시그니처를 useActionState 패턴
  ((prev, formData) => Promise<{ ok, error? }>) 으로 변경.
- 검증 실패 (15MB 초과 / MIME 거부 / 빈 파일 / 세션 id 불량) 시 throw 대신
  명시적 PhotoResult.error 반환.
- PhotoSection 을 server → client component 로 (useActionState).
- 업로드/교체/삭제 모두 SubmitButton (useFormStatus) — pending 중 disabled
  + 라벨 교체.
- 사진 우측 [교체] 버튼은 부모의 useActionState formAction 을 props 로 받음
  → alert/pending 상태가 한 곳에서 관리됨.

Admin members (app/admin/members/actions.ts + page.tsx + _components):
- approveUser / rejectUser 시그니처 동일 패턴.
- 'cannot approve/reject self' 를 throw 대신 inline alert 메시지로.
- 페이지 (server component) 가 PendingMemberActions (client) 를 행마다 렌더.
- 두 버튼 ([승인]/[거절]) 이 같은 row 의 alert 영역 공유.

검증된 회귀 항목:
- 사진 업로드 [올리기] 빠른 더블 클릭 → 첫 클릭 후 button disabled.
- 본인 [승인] 시도 → '본인은 본인을 승인할 수 없습니다.' alert, 페이지 그대로.
- 빌드 9 → 10 routes, /sessions/[id] +1.2kB (client form 추가분).

Spec: .gjc/specs/week2-wrapup.md §1

* chore(ci): typecheck + lint + build on PR/push (#5)

.github/workflows/ci.yml — PR to dev/main 과 dev/main push 에서 동작.

Jobs:
- Setup Node 22 + pnpm 11.5.1 (lockfile 의 packageManager 와 일치)
- pnpm store 캐시 (lockfile hash 기반)
- .next/cache 캐시 (ts/tsx hash 기반)
- pnpm install --frozen-lockfile (lockfile drift 차단)
- pnpm db:generate (postinstall 보강)
- typecheck → lint → build 직렬
- build env: dummy 값 주입 (auth/db url 필요)

Concurrency: 같은 ref 의 새 push 가 들어오면 이전 run 취소.
Timeout: 10분.

브랜치 보호 (Settings → Branches) 설정으로 'check' 통과 강제는 호스트(나)
가 main, dev 두 곳에 별도 등록 — 코드 변경 X.

* chore(deploy): GH Actions SSH deploy pipeline (#22)

.github/workflows/deploy.yml + deploy/README.md secret 등록 절차.

Workflow:
- trigger: push to dev (→ staging), main (→ prod), 또는 workflow_dispatch
- build job: Docker Buildx + GHCR (ghcr.io) push, GHA cache 사용
  태그: '<target>-<sha7>' + '<target>' (latest 역할)
- deploy job: appleboy/ssh-action 으로 N100 접속,
  docker compose pull && up -d (project name 으로 staging/prod 분리)
- concurrency: 같은 ref 의 동시 배포 금지
- environment: GitHub Environments 의 'staging' / 'prod' 사용 (prod 는
  수동 승인 가능)
- Sanity check 단계: secret 누락 시 명시적 에러로 즉시 실패

필요 secrets (사용자 직접 등록):
- N100_HOST / N100_USER / N100_SSH_KEY
- GITHUB_TOKEN 은 자동 (GHCR push 권한 위해 permissions.packages: write)

deploy/README.md:
- '0. CI/CD 사용 시' 섹션 신설 — secret 등록 절차, SSH key 생성, prod
  environment 보호.
- 기존 '1. 첫 배포 (수동)' 은 'CI/CD 우회/디버깅' 으로 강등 (호스트 init
  1회는 여전히 필요)

* docs(retro): Week 2 회고 + Home toc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant