Tilt Dev Loop
Tilt 개발 루프 (Tilt Dev Loop)
Section titled “Tilt 개발 루프 (Tilt Dev Loop)”FractalOps는 실제 개발 경로를 위한 Tilt 워크플로를 가집니다.
로컬 워크스테이션 -> 로컬 이미지 빌더 -> Helm dev 릴리스 -> dev 네임스페이스 -> 브라우저 스모크Tilt는 이 저장소 자신의 FractalOps API/worker/portal 이미지를 위한 로컬 컨트롤-플레인 이미지 빌드 / dev-릴리스 루프입니다. 프로젝트 dev 프리뷰와는 무관합니다(그건 Daytona 샌드박스에서 bare 프로세스로 돕니다 — Dev Preview Plane 참고).
Tilt를 돌리는 호스트는 라이브 k3s API를 직접 mutate하지 않습니다. 그래서 올바른 모양은 직접 k8s_resource(...)나 원격 데몬 엔드포인트가 아닙니다. Tilt는 다음을 하는 로컬 셸 리소스를 구동합니다.
- 컨테이너 빌드 툴체인으로 런타임 이미지를 로컬 빌드
- Nexus 빌드 캐시 평면으로 dev 이미지/캐시 push
- dev 네임스페이스의 dev-only Helm 릴리스 upgrade
- 실제 공개 라우트 스모크
모드 분리 (Mode split)
Section titled “모드 분리 (Mode split)”flowchart LR
subgraph dev["development mode (Tilt)"]
d1["로컬 이미지 빌드"] --> d2["GHCR dev tag"]
d2 --> d3["helm upgrade --install\n-> fractalops-dev"]
end
subgraph staging["staging mode"]
s1["staging-tagged 이미지\n+ cache scope"] -.->|기본: live mutate 안 함| s2["(옵션) 라이브 적용"]
end
subgraph release["deployment mode"]
r1["Git/CI -> immutable tag"] --> r2["Helm values 핀"]
r2 --> r3["Argo sync\n(canonical live)"]
end
- development mode: Tilt가 이미지를 빌드하고 dev-only Helm 릴리스를 upgrade.
- staging mode: staging-tagged 이미지와 캐시 스코프를 빌드하되, 기본적으로 라이브 워크로드를 mutate하지 않음.
- deployment mode: Argo가 Helm-선언된 Git 상태를 화해.
절대로 Tilt로 릴리스를 승격하지 마세요. 라이브-클러스터 빠른 반복에만 쓰세요.
요구 사항 (Requirements)
Section titled “요구 사항 (Requirements)”tilt로컬 설치 — 공식 설치 문서: https://docs.tilt.dev/install.html- 로컬 컨테이너 이미지 빌드 툴체인
helm- repo 루트
/home/devuser/work/fractalops
dev 배포 mutation에는 로컬 kubectl이 필요 없습니다.
시작 (Start)
Section titled “시작 (Start)”make tilt-up이것이 하는 일:
- 로컬 Tilt 이미지 빌더로 런타임 이미지 빌드
- tag 대상 기본값
ghcr.io/yamonco/... - Tilt가 dev push에 GitOps 머신 GHCR 자격증명을 자동 사용
- 원격 캐시 import/export 기본 off — 이 호스트는 원격 빌드 캐시를 효율적으로 쓸 수 없어 라이브 dev 루프에 복잡도만 더함
- tag 대상 기본값
- dev 네임스페이스에서 런타임 Helm 릴리스 upgrade
- 같은 방식으로 portal dev 릴리스 빌드 + 롤아웃
기본 리소스: api, portal.
선택 리소스:
make tilt-up TILT_ARGS="-- --worker --e2e"개발 모드 떠나기 (Leave development mode)
Section titled “개발 모드 떠나기 (Leave development mode)”로컬 Tilt 세션만 정지:
make tilt-down이것은 로컬 dev 루프를 멈출 뿐, release/staging/prod 앱을 mutate하지 않습니다.
배포 모드로 완전히 돌아가 Argo 소유권을 재확립:
make deploy-modemake deploy-mode가 하는 세 가지:
- Tilt가 설치돼 있으면 로컬 Tilt 세션 정지
- Argo CD에 canonical FractalOps 앱 sync 요청
- canonical 앱이
Synced/Healthy로 돌아올 때까지 대기
리소스 (Resources)
Section titled “리소스 (Resources)”Tilt가 정의하는 것:
runtimeportal- 선택
portal-e2e-smoke - 수동
deploy-mode
Dev와 Release 경계 (Dev and Release Boundary)
Section titled “Dev와 Release 경계 (Dev and Release Boundary)”FractalOps 런타임 API/worker/portal 앱은 하나의 배포 표면: Helm 차트를 씁니다. Tilt는 disposable dev 네임스페이스에 같은 차트를, Argo는 같은 차트 경로를 runtime 환경에 sync합니다.
Dev: Tilt -> 로컬 이미지 빌드 -> GHCR dev tag -> helm upgrade --install -> fractalops-dev
Release: Git/CI -> 이미지 빌드 -> GHCR immutable tag -> Helm values 이미지 핀 -> Argo sync빌드 평면과 캐시 (Build plane and cache)
Section titled “빌드 평면과 캐시 (Build plane and cache)”모든 이미지 빌더는 Kubernetes BuildKit 평면을 사용합니다.
pnpm verify의도된 레지스트리 분리:
- GHCR: 최종 이미지 레지스트리만
- Nexus docker-group
:8083: docker.io + ghcr.io pull-through 미러 - GHCR HTTPS registry cache: CI OCI 빌드 캐시 import/export
- Nexus buildcache (in-cluster docker-internal
:8082): 내부 TLS/Gateway writer가 준비되기 전까지 topology evidence/reserved endpoint
Nexus buildcache_ref가 문서/토폴로지에 남아 있어도 plain-HTTP endpoint는 BuildKit registry cache writer로 자동 승격되지 않습니다. Gateway API/HTTPRoute 등으로 내부 HTTPS 경로를 만든 뒤 FRACTALOPS_BUILDCACHE_REGISTRY를 명시해야 Nexus writer가 됩니다. 기본 캐시 스코프는 stage + target 스코프:
nexus.nexus.svc.cluster.local:8082/fractalops/buildcache/dev/runtimenexus.nexus.svc.cluster.local:8082/fractalops/buildcache/dev/portalnexus.nexus.svc.cluster.local:8082/fractalops/buildcache/dev/daytona-workspacenexus.nexus.svc.cluster.local:8082/fractalops/buildcache/staging/runtimenexus.nexus.svc.cluster.local:8082/fractalops/buildcache/staging/portal이렇게 하면 GHCR가 캐시 버킷이 되는 것을 막고, runtime/portal/workspace 빌드가 invalidation-무거운 하나의 캐시 태그를 공유하지 않게 합니다.
빌드 텔레메트리 (Build telemetry)
Section titled “빌드 텔레메트리 (Build telemetry)”빌드/캐시/utilization 텔레메트리는 워크플로 테스트 스위트가 아니라 Build Plane에 속합니다. 새 이벤트 이름/싱크를 추가하기 전에 Build Plane Observability의 ubiquitous 용어를 보세요.
Tilt/CI build runner -> Telemetry Marker -> OTLP HTTP logs -> OpenTelemetry Collector -> ClickHouse웨어하우스 자격증명이 있는 제어된 runner는 직접 ClickHouse emission이 옵션:
FRACTALOPS_BUILD_EVENTS_ENABLED=trueFRACTALOPS_BUILD_EVENTS_TABLE=build_eventsFRACTALOPS_CLICKHOUSE_HOST_PORT=clickhouse.clickhouse.svc.cluster.local:8123FRACTALOPS_CLICKHOUSE_DATABASE=warehouseTilt/GitHub build 래퍼는 Build Plane Event 레코드를 best-effort로 emit합니다. 싱크는 기본 non-blocking이며, 텔레메트리 경로 자체를 검증할 때만 FRACTALOPS_BUILD_EVENTS_STRICT=true를 설정하세요.
오토스케일링 경계 (Autoscaling boundary)
Section titled “오토스케일링 경계 (Autoscaling boundary)”라이브 FractalOps 컨트롤-플레인 워크로드는 Kubernetes HPA를 씁니다.
fractalops-api: min 2, max 6fractalops-portal: min 1, max 4fractalops-worker: min 1, max 4
Daytona 프로젝트 샌드박스는 HPA-관리 Deployment가 아닙니다. 런타임-소유 워크스페이스 컨테이너이며, 라이프사이클은 Daytona 컨트롤 플레인과 프로젝트 리스 정책을 따릅니다. 정지된 샌드박스는 0으로 스케일되거나 샌드박스 TTL이 회수합니다.
플랫폼 CI 이미지 빌드는 Nexus 레지스트리/빌드 캐시를 쓰는 관리 build worker를 씁니다. 병렬 빌드 수요는 새 privileged 데몬 Deployment가 아니라 공유 build worker와 레지스트리 캐시를 거쳐야 합니다.
staging 이미지 채널 (Staging image channel)
Section titled “staging 이미지 채널 (Staging image channel)”라이브 클러스터를 건드리지 않고 staging-tagged 런타임/portal 이미지를 발행하려면 staging 모드를 쓰세요.
make staging-mode한 타깃만 빌드:
make staging-mode TILT_ARGS="runtime --build-only"make staging-mode TILT_ARGS="portal --build-only"명시적으로 라이브-클러스터 점검을 원할 때만 staging-tagged 이미지를 canonical 라이브 Deployment에 적용:
make staging-mode TILT_ARGS="runtime"make staging-mode TILT_ARGS="portal"브라우저 스모크 (Browser smoke)
Section titled “브라우저 스모크 (Browser smoke)”Tilt는 수동 리소스 portal-e2e-smoke를 노출합니다. 포트-포워드된 portal에 실제 Playwright 스모크를 돌리고 output/playwright/tilt-portal-smoke.png를 씁니다. Tilt UI에서 트리거하거나:
make tilt-ci TILT_ARGS="-- --e2e"스모크는 공개 라우트 https://portal.yamon.io/projects에 대해 돕니다.
왜 이런 모양인가 (Why this shape)
Section titled “왜 이런 모양인가 (Why this shape)”이 워크플로는 Tilt의 local-resource 가이드를 실제 FractalOps 경계에 맞춘 것입니다.
- 호스트가 라이브 kube API에 직접 말할 수 없다
- 호스트는 로컬 빌드를 하고 Nexus 캐시 평면에 도달할 수 있다
- Helm이 dev 릴리스 mutation을 소유한다
- Argo가 canonical 릴리스 mutation을 소유한다
- 그래서 개발 모드는 “Argo-소유 deployment 패치”가 아니라 “로컬 빌드 + Helm dev 릴리스”여야 한다
Tilt는 빌드/롤아웃/스모크/복원 스텝을 local_resource 파이프라인으로 모델링합니다.
공식 참조:
- 원격 서비스/빌드: https://docs.tilt.dev/local_vs_remote.html
- 로컬 리소스: https://docs.tilt.dev/local_resource.html
- 커스텀 빌드: https://docs.tilt.dev/custom_build.html
노트 (Notes)
Section titled “노트 (Notes)”- 이 루프는 빠른 개발자 반복용이지 GitOps 승격용이 아닙니다.
- Argo는
main의 canonical 라이브 워크로드 배포 오너로 남습니다. make deploy-mode가 Argo에 소유권을 넘기는 필수 방법입니다.
프로젝트 프리뷰는 Tilt가 아닙니다 (Project Previews Are Not Tilt)
Section titled “프로젝트 프리뷰는 Tilt가 아닙니다 (Project Previews Are Not Tilt)”이 Tilt 루프는 이 저장소 자신의 컨트롤-플레인 이미지를 빌드합니다. 프로젝트 프리뷰 경로가 아닙니다. 관리되는 프로젝트는 Tilt나 샌드박스 안에서 빌드/ship하지 않습니다.
프로젝트 dev 프리뷰는 Daytona 샌드박스에서 bare 프로세스(vite / next / uvicorn, 0.0.0.0 바인드)로 돌고, dev-preview MCP로 daytona-proxy 서명 프리뷰 URL을 통해 노출됩니다. 프로젝트당 하나의 공개 호스트(<slug>.monstore.io)가 실행 중이면 라이브 dev 프리뷰를, 아니면 프로젝트의 Dokploy 딜리버리를 서빙합니다. Dev Preview Plane 참고.
Project dev preview: Daytona 샌드박스 (docker 없음) -> bare 개발 서버 프로세스 -> daytona-proxy 서명 프리뷰 URL -> <slug>.monstore.io (라이브 프리뷰, 아니면 Dokploy 딜리버리)규칙:
- repo/branch/agent/preview 채널마다 Daytona 워크스페이스를 만들지 마세요.
- 관리되는 프로젝트 프리뷰를 Tilt에서 ad-hoc k3s 네임스페이스로 배포하지 마세요.
- Dokploy는 영구 backing 서비스 전용입니다(DB, 정적 사이트 / vercel-sim 호스팅, big-facility compose) — dev 서버가 아닙니다.
- PlaywrightGrid는 로컬 Tilt 라우트가 아니라 프로젝트의 공개 프리뷰 호스트를 테스트합니다.
이로써 역할이 선명해집니다.
- Daytona: source-attached 프로젝트 워크스페이스와 bare dev 프리뷰 프로세스
- daytona-proxy: 서명 프리뷰 URL 표면
- Dokploy: 영구 backing 서비스와 정적 딜리버리
- PlaywrightGrid: 프로젝트 공개 프리뷰 호스트에 대한 브라우저 증명
- FractalOps Studio: 컨트롤 플레인, 계보, 에이전트 UX