feat: 저장소 생성 시 설명 필수화 + 템플릿 복제 생성
- 프로젝트 설명을 생성 필수 항목으로 변경(CreateRepoDto.description required + 프론트 검증)
- 템플릿 복제: useTemplate=true 면 Gitea generate API 로 GITEA_TEMPLATE_OWNER/REPO
(기본 TtiPo/project-base) 저장소를 복제 생성(브랜치는 템플릿을 따름)
- GET /repos/owner → /repos/meta 로 확장({ owner, template }) — 생성폼 메타 일괄 제공
- 프론트 생성폼: 가짜 템플릿 목록 제거 → 실제 템플릿 옵션, 설명 필수 UI
- env.example/ api-contract/ 진행현황 문서 갱신
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -80,12 +80,17 @@ status 매핑보다 우선해 그대로 표준 응답으로 내려보내고, 프
|
||||
| 메서드 | 경로 | 요청 | 응답 |
|
||||
|---|---|---|---|
|
||||
| GET | `/repos` | `?page&size` | `Repo[]`(요약) — 내가 멤버인 저장소 |
|
||||
| GET | `/repos/meta` | — | `{ owner, template }` — 생성 폼 메타(`:repoId` 보다 먼저 매칭) |
|
||||
| POST | `/repos` | `CreateRepoDto` | `Repo` |
|
||||
| GET | `/repos/:repoId` | — | `Repo`(상세) |
|
||||
| PATCH | `/repos/:repoId` | `UpdateRepoDto` | `Repo` |
|
||||
| DELETE | `/repos/:repoId` | — | `null` |
|
||||
|
||||
`CreateRepoDto`: `{ slug, name, visibility('private'|'public'), description?, branch? }`
|
||||
`GET /repos/meta` 응답: `{ owner: string, template: { available: boolean, slug: string } }`
|
||||
— 생성 전 소유자(조직) 고정 표시 + 템플릿 옵션 노출용.
|
||||
|
||||
`CreateRepoDto`: `{ slug, name, visibility('private'|'public'), description, branch?, useTemplate? }`
|
||||
(**description 필수**, `useTemplate=true` 면 템플릿 저장소를 복제해 생성)
|
||||
`Repo` 응답(원시값 중심):
|
||||
|
||||
```jsonc
|
||||
@@ -116,10 +121,12 @@ status 매핑보다 우선해 그대로 표준 응답으로 내려보내고, 프
|
||||
|
||||
| Relay 동작 | Gitea API | 매핑 |
|
||||
|---|---|---|
|
||||
| `POST /repos` | `POST /api/v1/orgs/{org}/repos` (auto_init) | `slug`→repo name, `visibility`→private, `branch`→default_branch, `name`+`desc`→description |
|
||||
| `POST /repos` (빈 저장소) | `POST /api/v1/orgs/{org}/repos` (auto_init) | `slug`→repo name, `visibility`→private, `branch`→default_branch, `name`+`desc`→description |
|
||||
| `POST /repos` (`useTemplate`) | `POST /api/v1/repos/{tplOwner}/{tplRepo}/generate` (git_content) | `owner`→org, `slug`→name, `name`+`desc`→description, `visibility`→private. 기본 브랜치는 템플릿을 따름 |
|
||||
| `PATCH /repos/:id` | `PATCH /api/v1/repos/{org}/{slug}` | `name`/`desc` 변경→description, `visibility` 변경→private (slug 불변) |
|
||||
| `DELETE /repos/:id` | `DELETE /api/v1/repos/{org}/{slug}` | — |
|
||||
|
||||
- 템플릿 출처: `GITEA_TEMPLATE_OWNER`/`GITEA_TEMPLATE_REPO`(기본 `TtiPo`/`project-base`). 해당 저장소는 Gitea 에서 *template* 로 설정돼 있어야 한다.
|
||||
- 인증: 조직 권한 토큰 단일 사용(`Authorization: token <TOKEN>`). 사용자별 Gitea 계정 매핑은 추후.
|
||||
- 생성은 Gitea 우선 → 성공 시 Relay 저장(연동 정보 `giteaRepoId`/`cloneUrl`/`htmlUrl` 보관). Relay 저장 실패 시 Gitea repo 롤백 삭제.
|
||||
- Gitea 이름 충돌(409) → `BIZ_001` "이미 사용 중인 저장소 이름입니다.", 그 외 실패 → `BIZ_001`(502).
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
- **ID 전략**: User/Repo PK=UUID, Repo 라우팅 식별자=`slugName`, Task=저장소 내 순번(#9, 4단계).
|
||||
- **Gitea 연동 방식**: HTTP 클라이언트는 새 의존성(@nestjs/axios) 없이 Node 20 내장 `fetch` 사용(베이스 이미지 alpine 호환). 인증은 조직 토큰 1개(사용자별 Gitea 계정 매핑은 8단계 후보). `slug`↔Gitea repo name 1:1, 한글 표시제목은 Gitea description 에 합쳐 저장(Gitea 에 표시명 필드 없음).
|
||||
- **연동 비활성 폴백**: `GITEA_*` 미설정 시 `GiteaService.enabled=false` → 저장소 CRUD 가 Gitea 없이 동작. 로컬 개발/테스트에서 Gitea 없이도 기존 흐름 유지.
|
||||
- **저장소 생성 폼 보강**: ① **프로젝트 설명 필수화**(`CreateRepoDto.description` required, 프론트 검증 추가). ② **템플릿 복제** — `useTemplate=true` 면 Gitea generate API 로 `GITEA_TEMPLATE_OWNER/REPO`(기본 `TtiPo/project-base`, *template* 설정 필요) 저장소를 복제 생성(브랜치는 템플릿을 따름). 프론트는 `GET /repos/meta`(owner+template) 로 owner 고정표시·템플릿 옵션을 받아 하드코딩 제거.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user