Files
yakcloud-starter/.claude/skills/yakcloud-deploy/SKILL.md

6.7 KiB

name, description
name description
yakcloud-deploy Scaffold and wire up YakCloud declarative CI/CD for a project — Gitea Actions (tag push) → build/push images → reconcile data sources → deploy workloads → bind → tenant cluster. Use when the user wants to deploy this project to YakCloud, set up the Gitea Actions workflow, create the yakcloud.yaml manifest, bind data sources, add a custom domain, or start a brand-new project from a minimal starter.

YakCloud 배포 스킬 (선언적 CI/CD)

VS Code로 개발 → 커밋 → v* 태그 push 하면, Gitea Actions가 이미지를 빌드/푸시하고 YakCloud 콘솔 API로 데이터소스 리컨실 + 워크로드 배포 + 바인딩을 자동 처리한다.

이 스킬은 아무 프로젝트에나 이 파이프라인을 심는다. 번들된 자산(assets/)을 프로젝트에 복사하고 매니페스트를 채운 뒤, 1회 시크릿만 설정하면 끝. 빈 프로젝트면 프레임워크 중립 스타터로 바로 시작.

언제 쓰나

  • "이 프로젝트를 YakCloud에 배포/자동화" / "Gitea CI/CD 붙여줘" / "yakcloud.yaml 만들어줘"
  • "새 프로젝트 시작해서 배포까지" (→ assets/starter/ 로 스캐폴딩)
  • "데이터소스(Postgres/Mongo/…) 연결/바인딩" / "커스텀 도메인으로 노출"

에이전트 실행 절차

0) 상황 파악

  • git 레포인지, 앱 코드가 이미 있는지 확인. 빈/신규면 §1-A(스타터), 기존 앱이면 §1-B.
  • Gitea 원격이 있는지(git remote -v) 확인. 없으면 사용자에게 Gitea 레포 URL을 물어 추가하도록 안내.

1-A) 신규 — 스타터로 스캐폴딩

  1. assets/starter/(app.py·Dockerfile·README) 를 프로젝트 루트에 복사. (프레임워크 무의존 최소 HTTP 서버: PORT 리슨, /healthz 200, / 는 바인딩된 소스의 <PREFIX>_URL 키만 표시)
  2. 아래 §2 공통 파일 복사 + §3 매니페스트 작성.

1-B) 기존 앱에 부착

  1. 앱이 PORT env로 리슨 + /healthz(또는 health 경로) 제공하는지 확인. 없으면 추가 제안.
  2. 앱이 데이터소스 접속정보를 하드코딩하지 말고 주입 env(<ALIAS>_URL 등)로 읽도록 수정 제안. 키 규약: reference/DATA-SOURCES.md.
  3. 각 배포 단위마다 Dockerfile 필요(없으면 언어에 맞게 생성). 베이스 이미지는 Gitea 미러(gitea.yakenator.io/yakenator/{node,python,...}) 권장.

2) 공통 파일 복사 (모든 경우)

프로젝트 루트에 그대로 복사:

  • assets/yakcloud.yaml./yakcloud.yaml (매니페스트 — §3에서 채움)
  • assets/workflows/deploy.yml./.gitea/workflows/deploy.yml (매니페스트 구동형 CI — 수정 불필요)
  • assets/scripts/yakcloud_deploy.py./scripts/yakcloud_deploy.py (리컨실 배포 CLI — 그대로)
  • assets/reference/DATA-SOURCES.md./DATA-SOURCES.md (선택 — 소스별 주입 env 표)

3) 매니페스트(yakcloud.yaml) 채우기 (핵심)

사용자와 함께 값을 정한다:

  • project: 프로젝트 이름(이미지 경로에 사용).
  • cluster: 배포 대상 클러스터 이름 또는 콘솔 id (콘솔 대시보드에서 확인). 여러 개면 여기서 특정.
  • requires: 필요한 데이터 소스 목록 { name, type, plan }. 없으면 [].
    • typepostgresql·mysql·mariadb·mongodb·redis·minio·rabbitmq·solr·oracle, plansmall·medium·large.
    • 이 이름의 소스가 클러스터에 이미 READY면 스킵, 없으면 자동 프로비저닝.
  • workloads[]:
    • build: 도커 빌드 컨텍스트 경로(예 ./ 또는 ./api). CI가 이 컨텍스트를 빌드해 image로 push.
    • image: gitea.yakenator.io/<GITEA_USER>/<project>-<name>:${TAG} (${TAG}=릴리스 태그로 치환).
    • port·health·replicas(≥2 권장 → 무중단 롤링)·resources{cpu,mem}.
    • expose: { path, rewrite, host? }host 지정 시 등록 도메인으로 노출(미지정=클러스터 기본 도메인). 여러 도메인은 hosts: [a, b].
    • binds[]: { alias, source }source는 위 requires 이름, alias는 env 프리픽스(대문자화). 예 alias: dbDB_URL/DB_HOST/… 주입.

4) 1회 준비 (사용자에게 안내 — 에이전트가 대신 못 함)

아래를 사용자가 설정하도록 명확히 출력:

  1. 배포 토큰(PAT): 콘솔 → 설정 → 배포 토큰 → 발급(yakd_…, 한 번만 표시). 계정 스코프(어느 클러스터든).
  2. Gitea 토큰: 스코프 read:repository + write:package + read:package. (레포 read 없으면 CI git clone 403)
  3. 레포 시크릿(Gitea: Settings → Actions → Secrets):
    이름
    YAKCLOUD_URL https://console.yakenator.io
    YAKCLOUD_TOKEN 1의 배포 토큰(yakd_…)
    YAKCLOUD_CLUSTER 대상 클러스터 이름/ id (생략 시 매니페스트 cluster:)
    REGISTRY_TOKEN 2의 Gitea 토큰
  4. 러너: 전용 러너(라벨 ci-polyglot)가 이미 공유로 떠 있으면 레포 Actions만 켜면 됨. 없으면 GUIDE의 러너 등록 참고.

5) 배포

git add -A && git commit -m "yakcloud: CI/CD 스캐폴딩"
git push origin main
git tag v0.1.0 && git push origin v0.1.0     # v* 태그만 배포 트리거(일반 커밋은 배포 안 함)

→ Gitea Actions 탭에서 실행 확인. 성공 시 콘솔 앱 탭 / 데이터 소스 / 도메인에 반영. 로컬 사전 점검: YAKCLOUD_URL=… YAKCLOUD_TOKEN=… python3 scripts/yakcloud_deploy.py yakcloud.yaml --dry-run

6) 커스텀 도메인(선택)

콘솔 설정 → 도메인 → 도메인 추가로 등록(관리형 도메인은 즉시 Active). 매니페스트 expose.host에 지정하거나 콘솔 앱 편집 폼에서 선택. 여러 도메인은 expose.hosts: [a.example.com, b.example.com].

동작/규약 요점

  • 트리거: v* 태그 push만. 일반 커밋은 배포 안 함.
  • 멱등/무중단: 기존 배포는 이미지 PATCH(→ kubectl apply 롤링). replicas≥2 + health면 무중단.
  • 자격: 데이터소스 비밀번호/키는 인클러스터 Secret으로 주입되고 브라우저/포털에 노출되지 않음. 앱은 <ALIAS>_URL 등으로 접속.

트러블슈팅(실제 겪은 것)

증상 원인 → 해결
CI git clone … 403 REGISTRY_TOKEN에 레포 read 없음 → read:repository 추가
docker create 실패(잡 시작 안 됨) 러너 config에서 docker.sock 중복 마운트 → act 기본 마운트만(수동 제거)
배포 중 429 RATE_LIMITED CLI가 retryAfterSec 백오프로 재시도(내장)
다른 러너가 잡 가져감 라벨 충돌 → 전용 라벨(runs-on) 사용