#!/usr/bin/env bash # yakcloud — YakCloud 프로젝트 CLI. 빈 폴더 초기화(스타터+스킬), 배포, 배포환경 상세 설정. # # yakcloud project init [name] 빈 폴더에 스타터 스캐폴딩(앱+CI+매니페스트+Claude 스킬) # yakcloud project deploy [vX.Y.Z] 커밋 + 태그 push → Gitea Actions 자동 배포 # yakcloud project info 프로젝트 개괄(매니페스트 + 라이브 상태) # yakcloud project check dry-run(직접 API 계획만) # # yakcloud domain [wl] 도메인 등록 + 워크로드에 할당(관리형=즉시, 배포중이면 라이브) # yakcloud scale replicas 변경 # yakcloud set --image/--port/--health/--cpu/--mem/--path/--rewrite # yakcloud env KEY=VAL … [--secret KEY] [--unset KEY] # yakcloud source add [plan] | source rm # yakcloud bind | unbind # # env: YAKCLOUD_URL, YAKCLOUD_TOKEN(배포토큰 yakd_…), (선택) YAKCLOUD_CLUSTER set -euo pipefail REPO="${YAKCLOUD_STARTER_REPO:-https://gitea.yakenator.io/yakenator/yakcloud-starter}" BRANCH="${YAKCLOUD_STARTER_BRANCH:-main}" VERSION="0.2.0" die() { echo "✗ $*" >&2; exit 1; } info() { echo "▸ $*"; } ensure_pyyaml() { python3 -c "import yaml" 2>/dev/null && return 0 pip3 install --quiet pyyaml 2>/dev/null \ || python3 -m pip install --quiet --break-system-packages pyyaml 2>/dev/null \ || die "pyyaml 설치 실패 — 'pip install pyyaml'" } # 설정/조회 커맨드는 프로젝트의 ctl 엔진에 위임(현재 폴더 = 프로젝트). ctl() { [ -f scripts/yakcloud_ctl.py ] || die "프로젝트 폴더가 아닙니다 — 'yakcloud project init' 로 초기화하세요." ensure_pyyaml python3 scripts/yakcloud_ctl.py "$@" } cmd_project_init() { local name="${1:-}" [ -n "$name" ] && { mkdir -p "$name"; cd "$name"; } if [ -n "$(ls -A . 2>/dev/null | grep -v '^\.git$' || true)" ]; then die "폴더가 비어있지 않습니다. 빈 폴더에서 실행하거나 'yakcloud project init '." fi info "yakcloud-starter 내려받는 중… ($REPO @ $BRANCH)" command -v git >/dev/null 2>&1 || die "git 이 필요합니다." local tmp; tmp="$(mktemp -d)" git clone -q --depth 1 -b "$BRANCH" "$REPO.git" "$tmp/s" \ || { rm -rf "$tmp"; die "스타터 클론 실패 — 네트워크/레포 공개 여부 확인 ($REPO)"; } rm -rf "$tmp/s/.git" cp -R "$tmp/s/." . rm -rf "$tmp" [ -n "$name" ] && [ -f yakcloud.yaml ] && { sed -i.bak "s/^project: .*/project: $name/" yakcloud.yaml && rm -f yakcloud.yaml.bak; } git rev-parse --git-dir >/dev/null 2>&1 || git init -q echo "✓ 초기화 완료 ($(pwd))" echo " 다음: yakcloud project info · yakcloud domain … · yakcloud project deploy v0.1.0" } cmd_project_deploy() { [ -f yakcloud.yaml ] || die "yakcloud.yaml 없음 — 'yakcloud project init' 먼저" git rev-parse --git-dir >/dev/null 2>&1 || git init -q git remote get-url origin >/dev/null 2>&1 \ || die "git 원격(origin) 없음 — Gitea 레포 만들어 'git remote add origin ' + Secrets 설정 후 다시" git fetch -q --tags origin 2>/dev/null || true # 버전: 인자 있으면 그것, 없으면 최신 v* 태그에서 패치 +1(없으면 v0.1.0) — 배포마다 자동 버전업. local ver="${1:-}" if [ -z "$ver" ]; then local last; last="$(git tag -l 'v*' --sort=-v:refname 2>/dev/null | head -1)" if [ -n "$last" ]; then ver="$(printf '%s' "$last" | awk -F. 'BEGIN{OFS="."} {$NF=$NF+1; print}')" else ver="v0.1.0" fi fi case "$ver" in v*) : ;; *) ver="v$ver" ;; esac info "배포 버전: $ver (커밋 + 태그 push)" git add -A; git commit -q -m "deploy $ver" 2>/dev/null || true git push -q origin HEAD 2>/dev/null || true git tag "$ver" 2>/dev/null || die "태그 $ver 이미 존재 — 'yakcloud project deploy <다음버전>'" git push -q origin "$ver" echo "✓ $ver push — Gitea Actions 에서 빌드·배포. 콘솔 앱 탭/도메인 확인." } cmd_project_check() { [ -f scripts/yakcloud_deploy.py ] || die "'yakcloud project init' 먼저" : "${YAKCLOUD_URL:?YAKCLOUD_URL 필요}"; : "${YAKCLOUD_TOKEN:?YAKCLOUD_TOKEN 필요}" ensure_pyyaml python3 scripts/yakcloud_deploy.py yakcloud.yaml --dry-run } usage() { cat < [wl] 도메인 등록 + 워크로드 할당(관리형=즉시/배포중이면 라이브) scale replicas 변경 set --image/--port/--health/--cpu/--mem/--path/--rewrite env KEY=VAL … [--secret KEY] [--unset KEY] source add [plan] | source rm bind | unbind env: YAKCLOUD_URL, YAKCLOUD_TOKEN(배포토큰 yakd_…), (선택) YAKCLOUD_CLUSTER EOF } case "${1:-help}" in project) shift case "${1:-}" in init) shift; cmd_project_init "$@" ;; deploy) shift; cmd_project_deploy "$@" ;; info) shift; ctl info "$@" ;; check|dry-run) shift; cmd_project_check "$@" ;; *) echo "yakcloud project "; exit 1 ;; esac ;; domain|scale|set|env|source|bind|unbind) ctl "$@" ;; version|-v|--version) echo "yakcloud $VERSION" ;; help|-h|--help|"") usage ;; *) echo "알 수 없는 명령: $1"; echo; usage; exit 1 ;; esac