기능: bootstrap 명령을 positional token 방식의 한 줄 UX로 변경한다
사용자가 artifact URL, Edge 주소, token을 환경변수로 직접 설정하던 IOP_* named parameter 방식을 제거하고, curl | bash -s <token> 형태의 단일 positional token UX로 변경한다. - bootstrap script에서 NODE_TOKEN을 첫 번째 인자로 받도록 변경 - token 누락 시 명확한 에러 메시지 출력 - artifact HTTP를 127.0.0.1 바인딩으로 변경 - docs, rules, roadmap에 one-line bootstrap UX 기준 기록
This commit is contained in:
parent
3b9f37076a
commit
0d83ef378e
7 changed files with 160 additions and 52 deletions
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
domain: testing
|
||||
last_rule_review_commit: 01bef3dc933e225b09d0f348aab6b0097275a4d8
|
||||
last_rule_updated_at: 2026-05-21
|
||||
last_rule_review_commit: 3b9f37076a396370f1c7043d7fa92e6f0a006031
|
||||
last_rule_updated_at: 2026-05-27
|
||||
---
|
||||
|
||||
# testing
|
||||
|
||||
## 목적 / 책임
|
||||
|
||||
작업 완료 후 어떤 테스트와 bin shell 사용자 흐름 검증을 거쳐야 하는지 정리한다. 테스트 파일을 바꿨는지가 아니라, 변경 작업이 어떤 사용자 실행 파이프라인에 닿았는지를 기준으로 검증 범위를 정한다.
|
||||
작업 완료 후 어떤 테스트와 bin shell 사용자 흐름 검증을 거쳐야 하는지 정리한다. 테스트 파일을 바꿨는지가 아니라, 변경 작업이 어떤 사용자 실행 파이프라인에 닿았는지를 기준으로 검증 범위를 정한다. 대상 host에서 사용자가 복사해 실행하는 bootstrap/install command의 기본 UX 기준도 이 도메인에서 다룬다.
|
||||
|
||||
## 포함 경로
|
||||
|
||||
|
|
@ -37,6 +37,7 @@ last_rule_updated_at: 2026-05-21
|
|||
- Web Portal verify — `apps/web` 변경 시 `npm run verify --prefix apps/web` 기준으로 TypeScript check와 production build를 확인한다.
|
||||
- full-cycle 실제 구동 — 비효율적이어도 관련 사용자 명령과 실행 cycle을 한 번씩 실제 entrypoint로 통과시키는 검증이다.
|
||||
- 실제 외부 CLI 검증 — `claude`, `antigravity`, `codex`, `opencode`처럼 외부 CLI 설치와 계정/환경이 필요한 기준 profile을 실제 호출하는 검증이다.
|
||||
- one-line bootstrap/install UX — Node, OTO, specialized agent, Control Plane enrollment처럼 사용자가 대상 host에서 복사해 실행하는 연결/설치 명령의 사용자 경험 기준이다.
|
||||
|
||||
## 유지할 패턴
|
||||
|
||||
|
|
@ -50,6 +51,9 @@ last_rule_updated_at: 2026-05-21
|
|||
- 보조 E2E smoke는 mock adapter와 임시 설정/포트를 사용해 외부 CLI 의존성 없이 수행한다.
|
||||
- 보조 E2E smoke에서는 최소한 node 등록, `/nodes` 확인, console 메시지 전송, delta/message 출력, complete event를 확인한다.
|
||||
- full-cycle 실제 구동에서는 startup/register, foreground run, session 변경, background run, terminate-session, status, 관련 routing/cancel/timeout/persistent session cycle을 실제 entrypoint로 한 번씩 통과시킨다.
|
||||
- one-line bootstrap/install command는 Jenkins agent 연결처럼 간결해야 한다. 사용자에게 전달하는 명령은 artifact/bootstrap URL이 완성된 한 줄이어야 하며, 사용자가 직접 바꾸는 값은 token 같은 단일 positional 값만 둔다.
|
||||
- one-line bootstrap/install command의 Edge 주소, artifact 주소, target, platform, config path 같은 값은 작업자/Edge/Control Plane이 미리 굽거나 완성해서 제공한다. 사용자 기본 경로에서 `IOP_*=` 같은 named environment parameter나 여러 주소 조합을 직접 입력하게 하지 않는다.
|
||||
- field Node bootstrap의 사용자 명령은 `curl -fsSL <완성된-bootstrap-url> | bash -s <token>` 형태를 기준으로 한다. 다른 bootstrap/enrollment 작업에서도 같은 수준의 단일 token UX를 우선 적용하고, 예외가 필요하면 사용자에게 먼저 확인한다.
|
||||
- 상세 수행 절차와 기능별 체크리스트는 `agent-ops/skills/project/e2e-smoke/SKILL.md`를 따른다.
|
||||
- `make test-e2e`, `scripts/e2e-smoke.sh`, `scripts/e2e-openai-ollama.sh`는 보조 smoke 명령이다. 실행할 수 있으면 보조 확인으로 기록하되, bin shell 사용자 흐름을 대체하지 않는다.
|
||||
- `bin/build/field-binaries.sh` 변경 시 최소 현재 host target build를 실행하고 산출물 위치와 checksum 생성을 확인한다.
|
||||
|
|
@ -116,4 +120,5 @@ terminated session default node=test-node
|
|||
- 관련 작업 후 full-cycle 실제 구동을 비용이 크다는 이유만으로 생략하지 않는다.
|
||||
- 보조 E2E smoke를 외부 CLI 설치, 로그인, 네트워크 계정 상태에 의존하게 만들지 않는다.
|
||||
- 검증을 위해 기본 `configs/*.yaml`을 임시값으로 오염시키지 않는다. 임시 설정 파일이나 환경 변수 override를 사용한다.
|
||||
- 사용자 기본 bootstrap/install 안내에 `IOP_ARTIFACT_BASE_URL=...`, `IOP_EDGE_ADDR=...`, `IOP_NODE_TOKEN=...` 같은 named environment parameter를 요구하지 않는다. 이런 값은 작업자용 디버그/override 경로로만 분리한다.
|
||||
- 필수 검증을 실행하지 못했는데 조용히 생략하지 않는다.
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
- 테스트는 변경 범위에 맞춰 `go test ./...` 또는 대상 패키지 테스트를 실행한다.
|
||||
- 사용자 실행 파이프라인에 닿는 작업을 한 경우, 작업 완료 후 `agent-ops/rules/project/domain/testing/rules.md`의 검증 기준을 따른다.
|
||||
- field 테스트 환경 또는 one-line bootstrap 작업은 `docs/deploy-dev.md`의 Field 테스트 환경 라우팅과 활성 Milestone `Field Bootstrap UX와 테스트 포트 정비`를 먼저 확인한다.
|
||||
- Node, OTO, specialized agent, Control Plane enrollment 등 사용자가 대상 host에서 실행하는 bootstrap/install command 작업은 `agent-ops/rules/project/domain/testing/rules.md`의 one-line bootstrap UX 기준을 따른다.
|
||||
- code-server 기반 field 테스트 포트는 원격 `ssh toki@toki-labs.com`의 `~/docker/services/code-server/compose/docker-compose.yml`에서 관리한다. 기준 host port는 web/dev `13000-13099`, artifact/bootstrap HTTP `18080`, OpenAI-compatible HTTP `18081`, Edge-Node transport `19090`, Edge metrics `19092`, OTO/specialized agent transport `19190`이다.
|
||||
- 상세 DB schema, event schema, permission/policy/audit model, federation, mTLS 구현 세부, Portal UI 세부 기획은 각 작업에서 별도로 결정한다.
|
||||
|
||||
|
|
@ -86,4 +87,5 @@
|
|||
|
||||
- 사용자 실행 파이프라인 검증, bin shell 사용자 흐름, 메시지 2회 왕복, edge command 응답, 보조 E2E smoke, full-cycle 실제 구동, `bin/edge.sh`/`bin/node.sh` 통합 테스트: `agent-ops/skills/project/e2e-smoke/SKILL.md`
|
||||
- field 테스트 포트, artifact/bootstrap HTTP, one-line Node bootstrap, code-server compose 기반 외부 테스트 환경: `docs/deploy-dev.md`와 활성 Milestone `agent-roadmap/phase/serving-routing-optimization/milestones/field-bootstrap-test-port-readiness.md`
|
||||
- bootstrap/install UX, Agent Bootstrap, OTO 등록, Control Plane enrollment처럼 사용자가 대상 host에서 복사해 실행하는 명령을 설계하거나 바꿀 때: `agent-ops/rules/project/domain/testing/rules.md`의 one-line bootstrap UX 기준과 `docs/deploy-dev.md`의 field bootstrap 기준을 확인한다.
|
||||
- 반복 작업이 확인되면 `agent-ops/skills/project/<skill-name>/SKILL.md`를 생성하고 이 표에 등록한다.
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ code-server 컨테이너는 외부 테스트용 web/bootstrap, Node transport, O
|
|||
- IOP field 테스트용 포트를 web/bootstrap HTTP, Node Edge transport, OTO/specialized agent transport 용도로 분리해 재부팅 후 바로 사용할 수 있게 한다.
|
||||
- Edge 쪽 build artifact 위치와 URL 규칙을 정하고, Apple Silicon Node를 우선 대상으로 한 one-line bootstrap UX를 만든다.
|
||||
- bootstrap 명령은 바이너리 다운로드, checksum 또는 버전 확인, 임시 config 생성, `iop-node serve` 실행까지 한 줄 수준으로 이어지는 것을 목표로 한다.
|
||||
- 사용자에게 보이는 bootstrap 명령은 artifact/bootstrap URL이 완성된 상태로 제공되어야 하며, 사용자가 직접 바꾸는 값은 token 값 하나뿐이다. `IOP_*=` 같은 named parameter는 사용자 기본 경로에 두지 않는다.
|
||||
- 이번 Milestone은 테스트 환경과 bootstrap UX를 다루며, Control Plane 기반 장기 enrollment/credential 관리와 OTO agent 본격 구현은 후속 Phase/Milestone에서 다룬다.
|
||||
|
||||
## 기능
|
||||
|
|
@ -39,7 +40,7 @@ field 테스트를 매번 수동 터널과 임시 명령 조합으로 만들지
|
|||
|
||||
- [x] [compose-ports] code-server compose가 field 테스트용 web/bootstrap, Node transport, OTO/specialized agent 포트를 외부에 노출한다. 검증: `docker compose config`에서 `18080`, `18081`, `19090`, `19190` 계열 포트 매핑이 확인된다.
|
||||
- [x] [artifact-layout] Node field build 산출물의 고정 위치와 URL 규칙이 정리되어 있다. 검증: Apple Silicon용 `iop-node`를 정해진 URL에서 다운로드할 수 있다.
|
||||
- [x] [one-line-node] 사용자가 한 줄 명령으로 Apple Silicon Node를 다운로드하고 Edge에 접속할 수 있다. 검증: Mac 테스트 환경에서 command 한 줄 실행 후 Edge에서 node registration을 확인한다.
|
||||
- [x] [one-line-node] 사용자가 token 값 하나만 넣은 한 줄 명령으로 Apple Silicon Node를 다운로드하고 Edge에 접속할 수 있다. 검증: Mac 테스트 환경에서 `curl -fsSL <완성된-bootstrap-url> | bash -s <token>` 형태의 command 한 줄 실행 후 Edge에서 node registration을 확인한다.
|
||||
- [x] [serve-lifecycle] `edge serve`가 field bootstrap에 사용할 node/openai listener를 안정적으로 유지한다. 검증: `edge serve --config <field-config>` 실행 후 Node registration과 `/v1/models` 호출이 통과한다.
|
||||
- [x] [runbook] field bootstrap runbook에 직접 포트 방식과 터널 fallback 방식이 구분되어 있다.
|
||||
- [x] [llm-test-runbook] LLM/작업자가 사용자 직접 테스트를 준비하고 실패 지점을 분리할 수 있는 상세 runbook이 문서화되어 있다. 검증: `docs/deploy-dev.md`에 포트 확인, Edge config, artifact 생성, HTTP 노출, Mac one-line bootstrap, OpenAI-compatible 확인, 실패 시 확인 순서가 있다.
|
||||
|
|
@ -64,10 +65,11 @@ field 테스트를 매번 수동 터널과 임시 명령 조합으로 만들지
|
|||
|
||||
## 작업 컨텍스트
|
||||
|
||||
- 관련 경로: `docs/deploy-dev.md`, `bin/build/field-binaries.sh`, `bin/edge.sh`, `apps/edge/cmd/edge`, `apps/edge/internal/bootstrap`, `apps/edge/internal/input`, `apps/edge/internal/transport`, 원격 `~/docker/services/code-server/compose/docker-compose.yml`
|
||||
- 관련 경로: `docs/deploy-dev.md`, `docs/field-bootstrap-work-guide.md`, `bin/build/field-binaries.sh`, `bin/edge.sh`, `apps/edge/cmd/edge`, `apps/edge/internal/bootstrap`, `apps/edge/internal/input`, `apps/edge/internal/transport`, 원격 `~/docker/services/code-server/compose/docker-compose.yml`
|
||||
- 표준선(선택): Edge-Node transport는 TCP proto-socket을 유지하고, HTTP는 artifact/bootstrap과 OpenAI-compatible 입력 표면에만 사용한다.
|
||||
- 표준선(선택): 외부 테스트 포트는 기존 code-server compose의 안전 remap 관례를 따라 host 충돌 포트를 피하고, 재부팅 타이밍은 사용자가 결정한다.
|
||||
- 표준선(선택): bootstrap UX는 Jenkins agent처럼 Edge가 command를 제시하고 대상 host가 실행하는 흐름을 목표로 하되, 초기 field 단계에서는 static artifact URL과 one-time-ish token/config로 시작한다.
|
||||
- 표준선(선택): 사용자용 bootstrap command는 `curl -fsSL <완성된-bootstrap-url> | bash -s <token>` 형태를 기준으로 한다. artifact URL은 작업자/Edge가 완성해 제공하고, 사용자가 치환하는 값은 token 하나만 둔다.
|
||||
- 선행 작업: Ollama 실테스트와 후속 안정화
|
||||
- 진행 기록: 원격 `~/docker/services/code-server/compose/docker-compose.yml`에 `18080:18080`, `18081:8080`, `19190:9190`을 추가하고 기존 `19090:9090`, `19092:9092`를 역할 주석으로 정리했다. `/usr/local/bin/docker compose config --quiet` 검증은 통과했으며, 실제 포트 적용은 사용자가 정한 code-server compose 재기동 시점 이후 확인한다.
|
||||
- 진행 기록: `agent-ops/rules/project/rules.md`에서 field 테스트 환경 작업을 `docs/deploy-dev.md`와 이 Milestone으로 라우팅하도록 보강했고, `docs/deploy-dev.md`에 code-server compose 원본, 기준 포트, 직접 포트/터널 fallback, Apple Silicon `darwin/arm64` 기준을 기록했다.
|
||||
|
|
@ -78,3 +80,14 @@ field 테스트를 매번 수동 터널과 임시 명령 조합으로 만들지
|
|||
- 후속 작업: Agent Bootstrap과 OTO 등록, Control Plane 기반 enrollment
|
||||
- 진행 기록: Mac에서 bootstrap artifact 다운로드와 Node 재접속을 반복 확인했고, Edge 로그에서 `node-silicon-ollama` registration, `/v1/models`, OpenAI-compatible streaming delta, Cline XML tool protocol 통과를 확인했다.
|
||||
- 확인 필요: archive 이동 승인
|
||||
|
||||
## 다음 세션 재개 메모
|
||||
|
||||
- 사용자 정정 사항: Edge-Node 실사용 연결에 외부 공개가 필요한 포트는 `19090` 하나다. `18080`은 bootstrap shell script, `iop-node` binary, checksum을 내려받는 artifact HTTP 포트일 뿐이며 Edge-Node 런타임 포트가 아니다.
|
||||
- 최종 방향: 외부 공개는 `toki-labs.com:19090`만 유지한다. bootstrap/artifact 전달은 내부망, front/control-plane, CI artifact, 또는 임시 로컬 HTTP처럼 별도 채널로 처리하고, 생성되는 `node.yaml`의 `transport.edge_addr`만 `toki-labs.com:19090`이 되게 한다.
|
||||
- 다음 테스트에서는 `curl http://toki-labs.com:18080/... | bash` 형태를 기본 안내로 쓰지 않는다. 외부 18080을 열지 않을 계획이면 bootstrap script는 내부 접근 가능한 주소에서 받고, script 기본값으로 `toki-labs.com:19090`을 굽는다.
|
||||
- 사용자용 명령은 반드시 artifact URL이 완성된 `curl -fsSL <완성된-bootstrap-url> | bash -s <token>` 형태로 제공한다. 사용자가 직접 넣는 값은 token 하나뿐이며 `IOP_ARTIFACT_BASE_URL=...`, `IOP_EDGE_ADDR=...`, `IOP_NODE_TOKEN=...` 같은 named parameter를 요구하지 않는다.
|
||||
- 현재 임시 live artifact version은 `field-live-20260527-19ddd9bd38b7`, token은 `iop-field-20260527-7fd4c675`, node id는 `node-silicon-ollama`, model은 `gemma4:26b`였다. 이전 테스트 중 bootstrap script 기본값을 한 번 `ARTIFACT_BASE_URL=http://toki-labs.com:18080`, `EDGE_ADDR=toki-labs.com:19090`로 재생성했으나, 이는 외부 18080까지 쓰는 형태라 최종 방향과 다르다.
|
||||
- 재개 시 먼저 stale process를 확인한다: `ps -ef | rg 'python3 -m http.server 18080|go run ./apps/edge/cmd/edge|/tmp/go-build.*/edge serve|iop-edge serve'`. 필요하면 임시 edge/artifact server를 정리하고 새 설정으로 다시 띄운다.
|
||||
- 권장 재테스트 형태: artifact server는 내부에서만 접근 가능한 주소로 열고 `ARTIFACT_BASE_URL=<internal-artifact-url>`, `BOOTSTRAP_EDGE_ADDR=toki-labs.com:19090`으로 Apple Silicon bootstrap을 생성한다. 사용자에게 주는 실행 명령은 artifact 접근 채널에 맞춰 완성된 URL로 제공하되, token은 명령 마지막 positional value 하나로만 받는다.
|
||||
- 작업 가이드 문서: `docs/field-bootstrap-work-guide.md`
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ Environment:
|
|||
VERSION=<value> release version label
|
||||
COMMIT=<value> commit label
|
||||
BUILD_DATE=<value> build date label
|
||||
ARTIFACT_BASE_URL=<url> default bootstrap artifact base URL
|
||||
BOOTSTRAP_EDGE_ADDR=<host:port> default Edge address written to node.yaml
|
||||
BOOTSTRAP_NODE_TOKEN=<token> default Node registration token
|
||||
ARTIFACT_BASE_URL=<url> default bootstrap artifact base URL
|
||||
BOOTSTRAP_EDGE_ADDR=<host:port> default Edge address written to node.yaml
|
||||
BOOTSTRAP_NODE_TOKEN=<token> optional fallback token baked into bootstrap script
|
||||
CGO_ENABLED=0 Go CGO setting
|
||||
GOFLAGS="-trimpath" extra go build flags
|
||||
LDFLAGS="-s -w" linker flags
|
||||
|
|
@ -88,7 +88,7 @@ write_node_bootstrap() {
|
|||
local script="$bootstrap_dir/node-$target_dir.sh"
|
||||
local default_base_url="${ARTIFACT_BASE_URL:-"http://toki-labs.com:18080"}"
|
||||
local default_edge_addr="${BOOTSTRAP_EDGE_ADDR:-"toki-labs.com:19090"}"
|
||||
local default_node_token="${BOOTSTRAP_NODE_TOKEN:-"CHANGE_ME_FIELD_TOKEN"}"
|
||||
local default_node_token="${BOOTSTRAP_NODE_TOKEN:-}"
|
||||
|
||||
mkdir -p "$bootstrap_dir"
|
||||
cat > "$script" <<EOF
|
||||
|
|
@ -97,9 +97,13 @@ set -euo pipefail
|
|||
|
||||
VERSION="$VERSION"
|
||||
TARGET="$target_dir"
|
||||
ARTIFACT_BASE_URL="\${IOP_ARTIFACT_BASE_URL:-$default_base_url}"
|
||||
EDGE_ADDR="\${IOP_EDGE_ADDR:-$default_edge_addr}"
|
||||
NODE_TOKEN="\${IOP_NODE_TOKEN:-$default_node_token}"
|
||||
DEFAULT_ARTIFACT_BASE_URL="$default_base_url"
|
||||
DEFAULT_EDGE_ADDR="$default_edge_addr"
|
||||
DEFAULT_NODE_TOKEN="$default_node_token"
|
||||
POSITIONAL_NODE_TOKEN="\${1:-}"
|
||||
ARTIFACT_BASE_URL="\$DEFAULT_ARTIFACT_BASE_URL"
|
||||
EDGE_ADDR="\$DEFAULT_EDGE_ADDR"
|
||||
NODE_TOKEN="\${POSITIONAL_NODE_TOKEN:-\$DEFAULT_NODE_TOKEN}"
|
||||
INSTALL_DIR="\${IOP_HOME:-\$HOME/iop-field}"
|
||||
CONFIG_FILE="\${IOP_NODE_CONFIG:-\$INSTALL_DIR/node.yaml}"
|
||||
BIN_FILE="\$INSTALL_DIR/iop-node"
|
||||
|
|
@ -112,6 +116,12 @@ trap cleanup EXIT
|
|||
|
||||
ARTIFACT_BASE_URL="\${ARTIFACT_BASE_URL%/}"
|
||||
|
||||
if [[ -z "\$NODE_TOKEN" ]]; then
|
||||
echo "[iop-bootstrap] missing node token" >&2
|
||||
echo "[iop-bootstrap] usage: curl -fsSL <artifact-base-url>/bootstrap/node-\$TARGET.sh | bash -s TOKEN" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "[iop-bootstrap] version=\$VERSION target=\$TARGET"
|
||||
echo "[iop-bootstrap] install_dir=\$INSTALL_DIR"
|
||||
mkdir -p "\$INSTALL_DIR"
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ field 테스트의 1차 기준 환경은 `ssh toki@toki-labs.com`의 code-server
|
|||
| Host port | Container port | Purpose |
|
||||
|---:|---:|---|
|
||||
| `13000-13099` | `3000-3099` | web/dev app preview range |
|
||||
| `18080` | `18080` | IOP field artifact/bootstrap HTTP |
|
||||
| `18080` | `18080` | IOP field artifact/bootstrap HTTP 후보. Edge-Node runtime 포트가 아니며, 외부 공개는 테스트 채널로 선택된 경우에만 사용한다. |
|
||||
| `18081` | `8080` | Edge OpenAI-compatible HTTP |
|
||||
| `19080` | `19080` | Portal/Control Plane wire test endpoint |
|
||||
| `19090` | `9090` | Edge-Node TCP transport |
|
||||
|
|
@ -141,50 +141,51 @@ field bootstrap UX는 Jenkins agent 연결처럼 Edge가 command를 제시하고
|
|||
- 사용자가 실행하는 명령은 한 줄 수준으로 유지하고, 내부에서 다운로드, 실행 권한 부여, config 생성, `iop-node serve`까지 이어진다.
|
||||
- 직접 포트가 아직 적용되지 않았거나 외부망에서 막히면 SSH tunnel 또는 reverse tunnel은 fallback으로만 사용한다.
|
||||
|
||||
Apple Silicon Node용 field artifact는 다음처럼 만든다. `BOOTSTRAP_NODE_TOKEN`은 Edge config의 `nodes[].token`과 같아야 한다.
|
||||
Apple Silicon Node용 field artifact는 다음처럼 만든다. Node token은 artifact에 굽지 않고 사용자 명령의 첫 번째 인자로 전달한다.
|
||||
|
||||
```bash
|
||||
VERSION=<field-version> \
|
||||
APPS=node \
|
||||
TARGETS="darwin/arm64" \
|
||||
ARTIFACT_BASE_URL="http://toki-labs.com:18080" \
|
||||
ARTIFACT_BASE_URL="<artifact-base-url>" \
|
||||
BOOTSTRAP_EDGE_ADDR="toki-labs.com:19090" \
|
||||
BOOTSTRAP_NODE_TOKEN="CHANGE_ME_FIELD_TOKEN" \
|
||||
DIST_DIR=dist/field \
|
||||
./bin/build/field-binaries.sh
|
||||
```
|
||||
|
||||
산출물 layout과 외부 URL 규칙은 다음을 기준으로 한다.
|
||||
산출물 layout과 artifact URL 규칙은 다음을 기준으로 한다.
|
||||
|
||||
```text
|
||||
dist/field/<field-version>/darwin-arm64/iop-node
|
||||
dist/field/<field-version>/darwin-arm64/SHA256SUMS
|
||||
dist/field/<field-version>/bootstrap/node-darwin-arm64.sh
|
||||
|
||||
http://toki-labs.com:18080/darwin-arm64/iop-node
|
||||
http://toki-labs.com:18080/darwin-arm64/SHA256SUMS
|
||||
http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh
|
||||
<artifact-base-url>/darwin-arm64/iop-node
|
||||
<artifact-base-url>/darwin-arm64/SHA256SUMS
|
||||
<artifact-base-url>/bootstrap/node-darwin-arm64.sh
|
||||
```
|
||||
|
||||
정적 artifact/bootstrap HTTP는 version 디렉터리를 document root로 열어 둔다.
|
||||
|
||||
```bash
|
||||
python3 -m http.server 18080 --bind 0.0.0.0 -d dist/field/<field-version>
|
||||
python3 -m http.server 18080 --bind 127.0.0.1 -d dist/field/<field-version>
|
||||
```
|
||||
|
||||
사용자는 Apple Silicon Mac에서 다음 한 줄을 실행한다.
|
||||
작업자는 artifact URL을 완성한 뒤 사용자가 token 값 하나만 바꾸는 한 줄 명령을 전달한다.
|
||||
사용자에게 전달하는 명령에는 `<artifact-base-url>` placeholder를 남기지 않는다.
|
||||
|
||||
```bash
|
||||
curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash
|
||||
curl -fsSL <완성된-bootstrap-url> | bash -s CHANGE_ME_FIELD_TOKEN
|
||||
```
|
||||
|
||||
bootstrap 스크립트는 `~/iop-field`를 만들고, `darwin-arm64/iop-node`와 `SHA256SUMS`를 받아 checksum을 확인한 뒤 `node.yaml`을 생성하고 `iop-node serve --config ./node.yaml`을 실행한다.
|
||||
실행 시점에 값을 바꾸려면 `IOP_ARTIFACT_BASE_URL`, `IOP_EDGE_ADDR`, `IOP_NODE_TOKEN`, `IOP_HOME`, `IOP_NODE_CONFIG`, `IOP_NODE_METRICS_PORT` 환경변수를 사용할 수 있다.
|
||||
첫 번째 인자 `CHANGE_ME_FIELD_TOKEN`은 Edge config의 `nodes[].token`과 같은 값이어야 한다.
|
||||
|
||||
## Field Bootstrap 작업자 테스트 Runbook
|
||||
|
||||
이 절차는 LLM/작업자가 사용자 직접 테스트를 준비하고 실패 지점을 분리할 때 기준으로 삼는다.
|
||||
사용자에게 전달할 짧은 가이드는 `docs/field-bootstrap-user-test.md`를 사용한다.
|
||||
다음 작업 재개와 포트 의미 정리는 `docs/field-bootstrap-work-guide.md`를 먼저 확인한다.
|
||||
토큰과 version 값은 테스트 시점에 맞춰 바꾸고, 기본 `configs/*.yaml`은 수정하지 않는다.
|
||||
|
||||
### 1. code-server 포트 확인
|
||||
|
|
@ -264,9 +265,8 @@ repo root에서 Apple Silicon Node artifact와 bootstrap script를 만든다.
|
|||
VERSION=field-bootstrap-manual \
|
||||
APPS=node \
|
||||
TARGETS="darwin/arm64" \
|
||||
ARTIFACT_BASE_URL="http://toki-labs.com:18080" \
|
||||
ARTIFACT_BASE_URL="<artifact-base-url>" \
|
||||
BOOTSTRAP_EDGE_ADDR="toki-labs.com:19090" \
|
||||
BOOTSTRAP_NODE_TOKEN="CHANGE_ME_FIELD_TOKEN" \
|
||||
DIST_DIR=dist/field \
|
||||
./bin/build/field-binaries.sh
|
||||
```
|
||||
|
|
@ -284,7 +284,7 @@ test -x dist/field/field-bootstrap-manual/bootstrap/node-darwin-arm64.sh
|
|||
version 디렉터리를 document root로 열어 둔다.
|
||||
|
||||
```bash
|
||||
python3 -m http.server 18080 --bind 0.0.0.0 -d dist/field/field-bootstrap-manual
|
||||
python3 -m http.server 18080 --bind 127.0.0.1 -d dist/field/field-bootstrap-manual
|
||||
```
|
||||
|
||||
다른 터미널에서 URL이 보이는지 확인한다.
|
||||
|
|
@ -294,10 +294,11 @@ curl -fsS http://127.0.0.1:18080/darwin-arm64/SHA256SUMS
|
|||
curl -fsS http://127.0.0.1:18080/bootstrap/node-darwin-arm64.sh | sed -n '1,40p'
|
||||
```
|
||||
|
||||
외부에서 직접 포트를 사용할 경우 Apple Silicon Mac에서도 같은 URL이 보여야 한다.
|
||||
artifact HTTP를 외부에서 직접 쓰기로 선택한 경우에만 Apple Silicon Mac에서도 같은 URL이 보여야 한다.
|
||||
외부 공개 포트를 `19090` 하나로 제한하는 테스트에서는 이 확인을 생략하고, 내부망, front/control-plane, CI artifact, 임시 로컬 HTTP 같은 별도 artifact 채널을 사용한다.
|
||||
|
||||
```bash
|
||||
curl -fsS http://toki-labs.com:18080/darwin-arm64/SHA256SUMS
|
||||
curl -fsS <artifact-base-url>/darwin-arm64/SHA256SUMS
|
||||
```
|
||||
|
||||
### 5. Edge serve 시작
|
||||
|
|
@ -326,20 +327,10 @@ ollama list | grep 'gemma4:26b'
|
|||
```
|
||||
|
||||
그 다음 one-line bootstrap을 실행한다.
|
||||
사용자에게 전달할 때는 `<완성된-bootstrap-url>`을 실제 URL로 바꿔 둔다.
|
||||
|
||||
```bash
|
||||
curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash
|
||||
```
|
||||
|
||||
테스트 중 값을 바꿔야 하면 pipe 오른쪽의 `bash`에 환경변수를 붙인다.
|
||||
|
||||
```bash
|
||||
curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | \
|
||||
IOP_ARTIFACT_BASE_URL="http://toki-labs.com:18080" \
|
||||
IOP_EDGE_ADDR="toki-labs.com:19090" \
|
||||
IOP_NODE_TOKEN="CHANGE_ME_FIELD_TOKEN" \
|
||||
IOP_HOME="$HOME/iop-field" \
|
||||
bash
|
||||
curl -fsSL <완성된-bootstrap-url> | bash -s CHANGE_ME_FIELD_TOKEN
|
||||
```
|
||||
|
||||
성공하면 Mac에 다음 파일이 생기고, Node process가 foreground로 실행된다.
|
||||
|
|
@ -388,8 +379,8 @@ curl -fsS -N http://127.0.0.1:8080/v1/chat/completions \
|
|||
다운로드 실패:
|
||||
|
||||
```bash
|
||||
curl -v http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh
|
||||
curl -v http://toki-labs.com:18080/darwin-arm64/iop-node
|
||||
curl -v <artifact-base-url>/bootstrap/node-darwin-arm64.sh
|
||||
curl -v <artifact-base-url>/darwin-arm64/iop-node
|
||||
```
|
||||
|
||||
Node가 Edge에 연결하지 못함:
|
||||
|
|
@ -401,7 +392,7 @@ cat ~/iop-field/node.yaml
|
|||
|
||||
token 불일치:
|
||||
|
||||
- Edge config의 `nodes[].token` 값과 bootstrap의 `BOOTSTRAP_NODE_TOKEN` 또는 `IOP_NODE_TOKEN` 값을 맞춘다.
|
||||
- Edge config의 `nodes[].token` 값과 bootstrap 명령 마지막의 token 인자 값을 맞춘다.
|
||||
|
||||
Ollama 호출 실패:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
# Field Bootstrap 직접 테스트
|
||||
|
||||
Apple Silicon Mac에서 아래만 실행한다.
|
||||
`<token>`은 그대로 쓰지 말고, 전달받은 실제 테스트 토큰으로 바꾼다.
|
||||
Edge 설정의 `nodes[].token`과 같은 값이어야 한다.
|
||||
작업자는 bootstrap URL이 완성된 명령을 전달해야 한다.
|
||||
사용자는 마지막 token 값 하나만 전달받은 실제 테스트 token으로 바꾼다.
|
||||
이 token은 Edge 설정의 `nodes[].token`과 같은 값이어야 한다.
|
||||
|
||||
## 1. Ollama 준비
|
||||
|
||||
|
|
@ -14,14 +15,11 @@ ollama list | grep 'gemma4:26b'
|
|||
## 2. Node 연결
|
||||
|
||||
```bash
|
||||
curl -fsSL http://192.168.0.97:18080/bootstrap/node-darwin-arm64.sh | \
|
||||
IOP_EDGE_ADDR="192.168.0.97:19090" \
|
||||
IOP_NODE_TOKEN="<token>" \
|
||||
bash
|
||||
curl -fsSL <완성된-bootstrap-url> | bash -s <token>
|
||||
```
|
||||
|
||||
예를 들어 전달받은 토큰이 `abc123`이면 `IOP_NODE_TOKEN="abc123"`로 바꾼다.
|
||||
전달받은 토큰이 없으면 실행하지 말고 토큰을 먼저 요청한다.
|
||||
예를 들어 전달받은 토큰이 `abc123`이면 마지막 `<token>` 자리만 `abc123`으로 바꾼다.
|
||||
전달받은 명령에 `<완성된-bootstrap-url>` 같은 placeholder가 남아 있거나 token이 없으면 실행하지 말고 먼저 요청한다.
|
||||
|
||||
성공하면 터미널에 `starting node against toki-labs.com:19090`가 보이고, 프로세스가 계속 실행된다.
|
||||
종료는 `Ctrl-C`.
|
||||
|
|
|
|||
89
docs/field-bootstrap-work-guide.md
Normal file
89
docs/field-bootstrap-work-guide.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Field Bootstrap 작업 가이드
|
||||
|
||||
이 문서는 작업자/LLM이 field bootstrap 테스트를 이어갈 때 읽는 재개 가이드다.
|
||||
사용자에게 그대로 전달하는 문서는 `docs/field-bootstrap-user-test.md`를 사용하고, 상세 runbook은 `docs/deploy-dev.md`를 확인한다.
|
||||
|
||||
## 핵심 규칙
|
||||
|
||||
- Edge-Node 런타임 연결에 외부 공개가 필요한 포트는 `19090` 하나다.
|
||||
- `18080`은 bootstrap shell script, `iop-node` binary, checksum을 내려받는 artifact HTTP 포트다. Edge-Node 런타임 포트가 아니다.
|
||||
- 외부 공개를 `19090` 하나로 제한할 때는 `toki-labs.com:18080`을 사용자 기본 명령으로 안내하지 않는다.
|
||||
- bootstrap/artifact는 내부망, front/control-plane, CI artifact, 또는 임시 로컬 HTTP 등 별도 채널로 전달한다.
|
||||
- 생성되는 `node.yaml`의 `transport.edge_addr`만 외부 접속 주소인 `toki-labs.com:19090`으로 맞춘다.
|
||||
|
||||
## 현재 테스트 값
|
||||
|
||||
- live version: `field-live-20260527-19ddd9bd38b7`
|
||||
- node token: `iop-field-20260527-7fd4c675`
|
||||
- node id: `node-silicon-ollama`
|
||||
- model: `gemma4:26b`
|
||||
- edge config 후보: `/tmp/iop-edge-field-bootstrap.yaml`
|
||||
|
||||
위 값은 임시 field 테스트 값이다. 장기 규약으로 고정하지 않는다.
|
||||
|
||||
## 재개 전 확인
|
||||
|
||||
stale process가 남아 있는지 먼저 본다.
|
||||
|
||||
```bash
|
||||
ps -ef | rg 'python3 -m http.server 18080|go run ./apps/edge/cmd/edge|/tmp/go-build.*/edge serve|iop-edge serve'
|
||||
netstat -ltnp 2>/dev/null | rg ':(18080|8080|9090)\b|Proto' || true
|
||||
```
|
||||
|
||||
이전 테스트 프로세스가 남아 있으면 정리한 뒤 새 설정으로 띄운다.
|
||||
|
||||
## 권장 테스트 흐름
|
||||
|
||||
Apple Silicon bootstrap artifact를 만들 때 artifact URL과 edge runtime 주소를 분리한다.
|
||||
|
||||
```bash
|
||||
VERSION=field-live-20260527-19ddd9bd38b7 \
|
||||
APPS=node \
|
||||
TARGETS="darwin/arm64" \
|
||||
ARTIFACT_BASE_URL="<internal-artifact-url>" \
|
||||
BOOTSTRAP_EDGE_ADDR="toki-labs.com:19090" \
|
||||
DIST_DIR=dist/field \
|
||||
./bin/build/field-binaries.sh
|
||||
```
|
||||
|
||||
artifact HTTP가 필요하면 내부에서 접근 가능한 경로로만 연다.
|
||||
|
||||
```bash
|
||||
python3 -m http.server 18080 --bind 127.0.0.1 -d dist/field/field-live-20260527-19ddd9bd38b7
|
||||
```
|
||||
|
||||
Edge는 field config로 실행한다.
|
||||
|
||||
```bash
|
||||
go run ./apps/edge/cmd/edge serve --config /tmp/iop-edge-field-bootstrap.yaml
|
||||
```
|
||||
|
||||
기본 확인:
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:8080/healthz
|
||||
curl -fsS http://127.0.0.1:8080/v1/models
|
||||
nc -vz toki-labs.com 19090
|
||||
```
|
||||
|
||||
사용자에게 전달하는 bootstrap 명령의 URL은 artifact 전달 채널에 맞춰 작업자가 완성한다.
|
||||
사용자 명령은 token 값 하나만 인자로 받는다. 사용자에게 `<artifact-base-url>` 같은 placeholder를 채우게 하지 않는다.
|
||||
외부 18080을 열지 않는 흐름에서는 bootstrap script 안의 기본 Edge runtime 주소만 `19090`으로 들어가야 한다.
|
||||
|
||||
```bash
|
||||
curl -fsSL <완성된-bootstrap-url> | bash -s iop-field-20260527-7fd4c675
|
||||
```
|
||||
|
||||
## 성공 기준
|
||||
|
||||
- Node host에서 `toki-labs.com:19090`에 연결할 수 있다.
|
||||
- Edge 로그에 `node registered`가 나온다.
|
||||
- `/v1/models`가 `gemma4:26b`를 반환한다.
|
||||
- OpenAI-compatible 호출에서 비어 있지 않은 응답 또는 SSE delta가 나온다.
|
||||
|
||||
## 주의
|
||||
|
||||
- `curl http://toki-labs.com:18080/... | bash`는 외부 18080 공개를 전제로 하므로 기본 안내로 쓰지 않는다.
|
||||
- Cline 전용 감지나 provider별 분기는 만들지 않는다. OpenAI-compatible protocol 차원에서 안정화한다.
|
||||
- 기본 `configs/*.yaml`에 field token이나 임시 host 값을 넣지 않는다.
|
||||
- 테스트 후에는 임시 edge와 artifact server를 내려둔다.
|
||||
Loading…
Reference in a new issue