cli v0.11.0: 로컬 dev/migrate 제거, 개발/운영 클러스터 승격 모델. environments.{dev,prod} 매니페스트; project deploy=개발 클러스터, project promote=재빌드 없이 운영 클러스터+운영 도메인. CI=dev 환경. dev/prod dry-run 검증
This commit is contained in:
97
bin/yakcloud
97
bin/yakcloud
@ -1,24 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# yakcloud — YakCloud 프로젝트 CLI. 빈 폴더 초기화(스타터+스킬), 배포, 배포환경 상세 설정.
|
||||
# yakcloud — YakCloud 프로젝트 CLI. 개발·운영 모두 yakcloud 클러스터에서(로컬 dev 없음).
|
||||
#
|
||||
# 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 project init [name] 빈 폴더에 스타터 스캐폴딩(앱+CI+매니페스트+Claude 스킬)
|
||||
# yakcloud project deploy [vX.Y.Z] 커밋 + 태그 push → CI 빌드 → 개발 클러스터 배포
|
||||
# yakcloud project promote [vX.Y.Z] 그 이미지를 재빌드 없이 운영 클러스터로 승격 + 운영 도메인
|
||||
# yakcloud project info 프로젝트 개괄(매니페스트 + dev/prod 라이브 상태)
|
||||
# yakcloud project check [--prod] dry-run(직접 API 계획만)
|
||||
#
|
||||
# yakcloud domain <fqdn> [wl] 도메인 등록 + 워크로드에 할당(관리형=즉시, 배포중이면 라이브)
|
||||
# yakcloud scale <wl> <n> replicas 변경
|
||||
# yakcloud set <wl> --image/--port/--health/--cpu/--mem/--path/--rewrite
|
||||
# yakcloud env <wl> KEY=VAL … [--secret KEY] [--unset KEY]
|
||||
# yakcloud source add <name> <type> [plan] | source rm <name>
|
||||
# yakcloud bind <wl> <source> <alias> | unbind <wl> <alias>
|
||||
# yakcloud domain <fqdn> [wl] · scale · set · env · datasource ls · source · bind/unbind
|
||||
#
|
||||
# env: YAKCLOUD_URL, YAKCLOUD_TOKEN(배포토큰 yakd_…), (선택) YAKCLOUD_CLUSTER
|
||||
# 매니페스트: environments.{dev,prod}.cluster (+ prod.domains). env: YAKCLOUD_URL, YAKCLOUD_TOKEN(yakd_…)
|
||||
set -uo pipefail # -e 미사용: 'test && action' 관용구가 값 없을 때 CLI 를 중단시키는 함정 회피. 중요 경로는 명시적 || die.
|
||||
|
||||
REPO="${YAKCLOUD_STARTER_REPO:-https://gitea.yakenator.io/yakenator/yakcloud-starter}"
|
||||
BRANCH="${YAKCLOUD_STARTER_BRANCH:-main}"
|
||||
VERSION="0.10.0"
|
||||
VERSION="0.11.0"
|
||||
CONFIG_DIR="${YAKCLOUD_CONFIG_DIR:-$HOME/.config/yakcloud}"
|
||||
CONFIG_FILE="$CONFIG_DIR/config"
|
||||
|
||||
@ -39,18 +35,6 @@ ctl() {
|
||||
python3 scripts/yakcloud_ctl.py "$@"
|
||||
}
|
||||
|
||||
dev() {
|
||||
[ -f scripts/yakcloud_dev.py ] || die "프로젝트 폴더가 아닙니다 — 'yakcloud project init' 로 초기화하세요."
|
||||
ensure_pyyaml
|
||||
python3 scripts/yakcloud_dev.py "$@"
|
||||
}
|
||||
|
||||
migrate() {
|
||||
[ -f scripts/yakcloud_migrate.py ] || die "프로젝트 폴더가 아닙니다 — 'yakcloud project init' 로 초기화하세요."
|
||||
ensure_pyyaml
|
||||
python3 scripts/yakcloud_migrate.py "$@"
|
||||
}
|
||||
|
||||
# ── 자격 저장 ── 비밀(배포토큰·Gitea토큰)=OS 키체인(암호화), 그 외(URL·사용자)=config 파일(600) ──
|
||||
_KC="none"
|
||||
if command -v security >/dev/null 2>&1; then _KC="macos"
|
||||
@ -174,10 +158,12 @@ cmd_project_init() {
|
||||
|
||||
# 매니페스트 채우기 마법사 — ctl 은 API 미접속(YAKCLOUD_TOKEN 비움)으로 매니페스트만 편집.
|
||||
_init_wizard() {
|
||||
local dflt_app="$1" app cluster port health cpu mem reps kv
|
||||
local dflt_app="$1" app devc prodc pdom port health cpu mem reps path kv
|
||||
echo "── 프로젝트 설정 (엔터=기본값) ──"
|
||||
printf "앱 이름 [%s]: " "$dflt_app"; read -r app; app="${app:-$dflt_app}"
|
||||
printf "대상 클러스터(이름 또는 콘솔 id): "; read -r cluster
|
||||
printf "개발 클러스터(이름 또는 콘솔 id): "; read -r devc
|
||||
printf "운영 클러스터 [%s]: " "${devc:-개발과 동일}"; read -r prodc; prodc="${prodc:-$devc}"
|
||||
printf "운영 도메인(선택, 예 app.example.com): "; read -r pdom
|
||||
printf "컨테이너 포트 [8080]: "; read -r port; port="${port:-8080}"
|
||||
printf "헬스체크 경로 [/healthz]: "; read -r health; health="${health:-/healthz}"
|
||||
printf "CPU 요청 [25m]: "; read -r cpu; cpu="${cpu:-25m}"
|
||||
@ -187,7 +173,9 @@ _init_wizard() {
|
||||
sed -i.bak "s/^project: .*/project: $app/" yakcloud.yaml && rm -f yakcloud.yaml.bak
|
||||
sed -i.bak "s/yakcloud-starter-web/${app}-web/" yakcloud.yaml 2>/dev/null; rm -f yakcloud.yaml.bak
|
||||
[ -n "${GITEA_USER:-}" ] && { sed -i.bak "s#/yakenator/#/${GITEA_USER}/#" yakcloud.yaml 2>/dev/null; rm -f yakcloud.yaml.bak; }
|
||||
[ -n "$cluster" ] && { sed -i.bak "s#^cluster: .*#cluster: $cluster#" yakcloud.yaml && rm -f yakcloud.yaml.bak; }
|
||||
[ -n "$devc" ] && { sed -i.bak "s#my-dev-cluster#$devc#" yakcloud.yaml && rm -f yakcloud.yaml.bak; }
|
||||
[ -n "$prodc" ] && { sed -i.bak "s#my-prod-cluster#$prodc#" yakcloud.yaml && rm -f yakcloud.yaml.bak; }
|
||||
[ -n "$pdom" ] && { sed -i.bak "s#domains: \[\]#domains: [$pdom]#" yakcloud.yaml && rm -f yakcloud.yaml.bak; }
|
||||
ensure_pyyaml
|
||||
YAKCLOUD_TOKEN= python3 scripts/yakcloud_ctl.py set web --port "$port" --health "$health" --cpu "$cpu" --mem "$mem" --path "$path" >/dev/null 2>&1 || true
|
||||
YAKCLOUD_TOKEN= python3 scripts/yakcloud_ctl.py scale web "$reps" >/dev/null 2>&1 || true
|
||||
@ -196,7 +184,7 @@ _init_wizard() {
|
||||
printf " env> "; read -r kv || break; [ -z "$kv" ] && break
|
||||
YAKCLOUD_TOKEN= python3 scripts/yakcloud_ctl.py env web "$kv" >/dev/null 2>&1 || echo " (형식: KEY=VALUE)"
|
||||
done
|
||||
echo "✓ 매니페스트 반영: app=$app cluster=${cluster:-<미지정>} port=$port path=$path cpu=$cpu mem=$mem replicas=$reps"
|
||||
echo "✓ 매니페스트 반영: app=$app dev=${devc:-<미지정>} prod=${prodc:-<미지정>} port=$port path=$path cpu=$cpu mem=$mem replicas=$reps"
|
||||
}
|
||||
|
||||
_maybe_login_prompt() {
|
||||
@ -283,7 +271,25 @@ 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
|
||||
local env=""; for a in "$@"; do case "$a" in --env=*) env="${a#--env=}" ;; --prod) env=prod ;; esac; done
|
||||
YAKCLOUD_ENV="${env:-dev}" python3 scripts/yakcloud_deploy.py yakcloud.yaml --dry-run
|
||||
}
|
||||
|
||||
# 운영 승격 — 개발에서 검증한 그 태그의 이미지를 **재빌드 없이** 운영 클러스터로 리컨실 + 운영 도메인 부착.
|
||||
cmd_project_promote() {
|
||||
[ -f scripts/yakcloud_deploy.py ] || die "'yakcloud project init' 먼저"
|
||||
: "${YAKCLOUD_URL:?YAKCLOUD_URL 필요 — 'yakcloud login'}"; : "${YAKCLOUD_TOKEN:?YAKCLOUD_TOKEN 필요 — 'yakcloud login'}"
|
||||
ensure_pyyaml
|
||||
local tag=""; for a in "$@"; do case "$a" in -*) : ;; *) [ -z "$tag" ] && tag="$a" ;; esac; done
|
||||
if [ -z "$tag" ]; then
|
||||
git fetch -q --tags origin 2>/dev/null || true
|
||||
tag="$(git tag -l 'v*' --sort=-v:refname 2>/dev/null | head -1)"
|
||||
fi
|
||||
[ -n "$tag" ] || die "승격할 태그가 없습니다 — 'yakcloud project promote vX.Y.Z' (개발 배포된 태그)"
|
||||
case "$tag" in v*) : ;; *) tag="v$tag" ;; esac
|
||||
info "운영 승격: $tag → prod 환경(재빌드 없이 개발에서 빌드된 그 이미지를 운영 클러스터로 리컨실)"
|
||||
YAKCLOUD_ENV=prod TAG="$tag" python3 scripts/yakcloud_deploy.py yakcloud.yaml
|
||||
echo "✓ 승격 완료: $tag → 운영 클러스터 + 운영 도메인(기본 도메인은 자동)"
|
||||
}
|
||||
|
||||
# 전역 CLI 자기 갱신 — 버전이 같아도 항상 최신 파일을 강제로 다시 받아 덮어쓴다(캐시 우회).
|
||||
@ -332,8 +338,7 @@ cmd_project_update() {
|
||||
mkdir -p scripts .gitea/workflows .claude/skills
|
||||
cp "$tmp/s/scripts/yakcloud_deploy.py" scripts/ 2>/dev/null || true
|
||||
cp "$tmp/s/scripts/yakcloud_ctl.py" scripts/ 2>/dev/null || true
|
||||
cp "$tmp/s/scripts/yakcloud_dev.py" scripts/ 2>/dev/null || true
|
||||
cp "$tmp/s/scripts/yakcloud_migrate.py" scripts/ 2>/dev/null || true
|
||||
rm -f scripts/yakcloud_dev.py scripts/yakcloud_migrate.py # 옛 로컬 dev/migrate 잔재 제거
|
||||
cp "$tmp/s/.gitea/workflows/deploy.yml" .gitea/workflows/ 2>/dev/null || true
|
||||
cp "$tmp/s/DATA-SOURCES.md" DATA-SOURCES.md 2>/dev/null || true
|
||||
rm -rf .claude/skills/yakcloud-deploy
|
||||
@ -345,12 +350,13 @@ cmd_project_update() {
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
yakcloud $VERSION — YakCloud 프로젝트 CLI
|
||||
yakcloud $VERSION — YakCloud 프로젝트 CLI (개발·운영 모두 yakcloud 클러스터)
|
||||
project init [name] 빈 폴더에 스타터 스캐폴딩(대화형 마법사) + 자격 프롬프트
|
||||
project deploy [vX.Y.Z] 커밋 + 태그 push → Gitea Actions(버전 생략=자동 버전업). 도메인도 리컨실.
|
||||
project deploy --local 러너 없이 로컬 build/push/리컨실(CI 대안)
|
||||
project info 프로젝트 개괄(매니페스트 + 라이브 상태)
|
||||
project check dry-run(직접 API 계획만)
|
||||
project deploy [vX.Y.Z] 커밋 + 태그 push → CI 빌드 → **개발 클러스터** 배포(버전 생략=자동 버전업)
|
||||
project deploy --local 러너 없이 로컬 build/push/리컨실(CI 대안, 개발 클러스터)
|
||||
project promote [vX.Y.Z] 개발에서 검증한 그 이미지를 재빌드 없이 **운영 클러스터**로 승격 + 운영 도메인
|
||||
project info 프로젝트 개괄(매니페스트 + dev/prod 라이브 상태)
|
||||
project check [--prod] dry-run(직접 API 계획만)
|
||||
project update 이 프로젝트의 엔진·CI·스킬만 최신화(앱·매니페스트 보존)
|
||||
upgrade 전역 yakcloud CLI 자기 갱신(최신 버전으로)
|
||||
── 자격(한 곳에 안전 보관; 비밀=OS 키체인 암호화) ──
|
||||
@ -365,13 +371,7 @@ yakcloud $VERSION — YakCloud 프로젝트 CLI
|
||||
datasource ls 클러스터에서 이용 가능한 소스 목록(이름·타입·내부/외부·상태)
|
||||
source add <name> <type> [plan] | source rm <name>
|
||||
bind <wl> <source> <alias> | unbind <wl> <alias>
|
||||
── 로컬 개발(docker 데이터소스 + prod 동일 env) ──
|
||||
dev up [source…] requires[] 를 로컬 docker 로 기동 + .env.dev 생성
|
||||
dev run -- <명령> up 보장 후 .env.dev 로 앱 실행(배포와 동일 <ALIAS>_* 주입)
|
||||
dev down [--volumes] | status | logs [src] | env | reset [src] | doctor
|
||||
datasource migrate capture [src…] [--dry-run] 소스 전체−블랙리스트(.migrateignore) 스냅샷(읽기전용)
|
||||
datasource migrate apply [src…] 스냅샷을 빈 타깃에 적용(데이터 있으면 스킵) | migrate status
|
||||
env: YAKCLOUD_URL, YAKCLOUD_TOKEN(배포토큰 yakd_…), (선택) YAKCLOUD_CLUSTER
|
||||
매니페스트: environments.{dev,prod}.cluster(+prod.domains). env: YAKCLOUD_URL, YAKCLOUD_TOKEN(배포토큰 yakd_…)
|
||||
EOF
|
||||
}
|
||||
|
||||
@ -383,19 +383,16 @@ case "${1:-help}" in
|
||||
case "${1:-}" in
|
||||
init) shift; cmd_project_init "$@" ;;
|
||||
deploy) shift; cmd_project_deploy "$@" ;;
|
||||
promote) shift; cmd_project_promote "$@" ;;
|
||||
info) shift; ctl info "$@" ;;
|
||||
check|dry-run) shift; cmd_project_check "$@" ;;
|
||||
update) shift; cmd_project_update "$@" ;;
|
||||
*) echo "yakcloud project <init|deploy|info|check|update>"; exit 1 ;;
|
||||
*) echo "yakcloud project <init|deploy|promote|info|check|update>"; exit 1 ;;
|
||||
esac ;;
|
||||
login) cmd_login ;;
|
||||
config) cmd_config ;;
|
||||
logout) cmd_logout ;;
|
||||
dev) shift; dev "$@" ;;
|
||||
migrate) shift; migrate "$@" ;;
|
||||
datasource|ds)
|
||||
shift
|
||||
if [ "${1:-}" = migrate ]; then shift; migrate "$@"; else ctl source "$@"; fi ;;
|
||||
datasource|ds) shift; ctl source "$@" ;;
|
||||
domain|scale|set|env|source|bind|unbind) ctl "$@" ;;
|
||||
upgrade|self-update) cmd_upgrade ;;
|
||||
version|-v|--version) echo "yakcloud $VERSION" ;;
|
||||
|
||||
Reference in New Issue
Block a user