diff --git a/.gitignore b/.gitignore index 1c49fd8..237a43e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,19 +5,10 @@ agent-ops/rules/private/ # Local runtime/test artifacts /iop.db /*.log +/build/ /dist/ /.env /temp_verif/ -/bin/control-plane -/bin/edge -/bin/artifacts/ -/bin/iop-control-plane -/bin/iop-edge -/bin/iop-node -/bin/iop-node-* -/bin/iop-worker -/bin/node -/bin/worker # Flutter Portal artifacts apps/portal/.dart_tool/ diff --git a/Makefile b/Makefile index 07c2055..08f8c1a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,14 @@ -.PHONY: all build build-edge build-node build-node-target pack-node-target tidy test test-e2e test-openai-ollama proto proto-dart portal-test portal-build-web clean +.PHONY: all build build-edge build-node build-node-target pack-node-target pack-edge tidy test test-e2e test-openai-ollama proto proto-dart portal-test portal-build-web clean GOFLAGS ?= -trimpath -BUILD_DIR ?= bin +BUILD_DIR ?= build +BUILD_BIN_DIR ?= $(BUILD_DIR)/bin +ARTIFACT_DIR ?= $(BUILD_DIR)/artifacts +PACK_DIR ?= $(BUILD_DIR)/packages +EDGE_TARGET ?= $(shell go env GOOS)-$(shell go env GOARCH) +EDGE_PACKAGE_NAME ?= iop-edge-$(EDGE_TARGET) +EDGE_PACKAGE ?= $(PACK_DIR)/$(EDGE_PACKAGE_NAME).tar.gz +EDGE_PACKAGE_TMP ?= $(BUILD_DIR)/.edge-package NODE_TARGET ?= $(shell go env GOOS)-$(shell go env GOARCH) NODE_TARGET_PARTS = $(subst -, ,$(NODE_TARGET)) NODE_GOOS = $(word 1,$(NODE_TARGET_PARTS)) @@ -10,21 +17,35 @@ NODE_GOARCH = $(word 2,$(NODE_TARGET_PARTS)) all: build build: - go build $(GOFLAGS) -o $(BUILD_DIR)/iop-edge ./apps/edge/cmd/edge - go build $(GOFLAGS) -o $(BUILD_DIR)/iop-node ./apps/node/cmd/node + mkdir -p $(BUILD_BIN_DIR) + go build $(GOFLAGS) -o $(BUILD_BIN_DIR)/iop-edge ./apps/edge/cmd/edge + go build $(GOFLAGS) -o $(BUILD_BIN_DIR)/iop-node ./apps/node/cmd/node build-edge: - go build $(GOFLAGS) -o $(BUILD_DIR)/iop-edge ./apps/edge/cmd/edge + mkdir -p $(BUILD_BIN_DIR) + go build $(GOFLAGS) -o $(BUILD_BIN_DIR)/iop-edge ./apps/edge/cmd/edge build-node: - go build $(GOFLAGS) -o $(BUILD_DIR)/iop-node ./apps/node/cmd/node + mkdir -p $(BUILD_BIN_DIR) + go build $(GOFLAGS) -o $(BUILD_BIN_DIR)/iop-node ./apps/node/cmd/node build-node-target: @test -n "$(NODE_GOOS)" && test -n "$(NODE_GOARCH)" || (echo "NODE_TARGET must be -" >&2; exit 2) - GOOS=$(NODE_GOOS) GOARCH=$(NODE_GOARCH) go build $(GOFLAGS) -o $(BUILD_DIR)/iop-node-$(NODE_TARGET) ./apps/node/cmd/node + mkdir -p $(BUILD_BIN_DIR) + GOOS=$(NODE_GOOS) GOARCH=$(NODE_GOARCH) go build $(GOFLAGS) -o $(BUILD_BIN_DIR)/iop-node-$(NODE_TARGET) ./apps/node/cmd/node pack-node-target: build-edge build-node-target - cd $(BUILD_DIR) && ./iop-edge bootstrap pack --target $(NODE_TARGET) --node-binary ./iop-node-$(NODE_TARGET) + $(BUILD_BIN_DIR)/iop-edge bootstrap pack --target $(NODE_TARGET) --node-binary $(BUILD_BIN_DIR)/iop-node-$(NODE_TARGET) --output $(ARTIFACT_DIR) + +pack-edge: build-edge + @test -d "$(ARTIFACT_DIR)/bootstrap" || (echo "missing node bootstrap artifacts; run make pack-node-target NODE_TARGET=- first" >&2; exit 2) + rm -rf "$(EDGE_PACKAGE_TMP)" + mkdir -p "$(EDGE_PACKAGE_TMP)/$(EDGE_PACKAGE_NAME)/artifacts" "$(EDGE_PACKAGE_TMP)/$(EDGE_PACKAGE_NAME)/logs" "$(PACK_DIR)" + cp "$(BUILD_BIN_DIR)/iop-edge" "$(EDGE_PACKAGE_TMP)/$(EDGE_PACKAGE_NAME)/iop-edge" + cp -R "$(ARTIFACT_DIR)/." "$(EDGE_PACKAGE_TMP)/$(EDGE_PACKAGE_NAME)/artifacts/" + tar -C "$(EDGE_PACKAGE_TMP)" -czf "$(EDGE_PACKAGE)" "$(EDGE_PACKAGE_NAME)" + rm -rf "$(EDGE_PACKAGE_TMP)" + @echo "wrote $(EDGE_PACKAGE)" tidy: go mod tidy @@ -87,9 +108,6 @@ portal-build-web: --dart-define=IOP_CONTROL_PLANE_WIRE_URL=ws://localhost:19080/portal clean: - rm -f bin/iop-edge bin/iop-node bin/iop-control-plane bin/iop-worker - rm -f bin/iop-node-* - rm -f bin/node bin/edge bin/control-plane bin/worker - rm -rf bin/artifacts + rm -rf build rm -rf dist rm -f iop.db diff --git a/agent-ops/rules/project/domain/testing/rules.md b/agent-ops/rules/project/domain/testing/rules.md index aa32a8c..88f0903 100644 --- a/agent-ops/rules/project/domain/testing/rules.md +++ b/agent-ops/rules/project/domain/testing/rules.md @@ -13,8 +13,8 @@ last_rule_updated_at: 2026-05-28 ## 포함 경로 - `Makefile` — 공식 test target, proto generation, 보조 smoke target을 선언하는 위치이다. -- `bin/edge.sh` — repo 내부 edge console/server 개발 진단 helper이다. -- `bin/node.sh` — repo 내부 node 연결 개발 진단 helper이다. field 사용자 기본 경로로 안내하지 않는다. +- `scripts/dev/edge.sh` — repo 내부 edge console/server 개발 진단 helper이다. +- `scripts/dev/node.sh` — repo 내부 node 연결 개발 진단 helper이다. field 사용자 기본 경로로 안내하지 않는다. - `iop-edge bootstrap pack` — Node host bootstrap용 artifact 폴더를 준비하는 공식 command이다. - `scripts/e2e-smoke.sh` — mock/real profile 기반 보조 edge-node smoke 검증이다. - `scripts/e2e-openai-ollama.sh` — OpenAI-compatible Ollama 입력 표면 보조 smoke 검증이다. @@ -29,7 +29,7 @@ last_rule_updated_at: 2026-05-28 - 대상 패키지 테스트 — 변경한 패키지와 인접한 패키지의 빠른 회귀 검증이다. - `go test ./...` — 저장소 전체 Go 테스트 회귀 검증이다. -- edge-node 개발 진단 흐름 검증 — `bin/edge.sh`와 `bin/node.sh`를 각각 실행하고, edge console에서 메시지 2회와 command 명령을 직접 보내 결과가 edge 화면에 도착하는지 확인하는 저수준 검증이다. field 사용자 기본 UX는 Edge가 제시한 bootstrap 명령이다. +- edge-node 개발 진단 흐름 검증 — `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 각각 실행하고, edge console에서 메시지 2회와 command 명령을 직접 보내 결과가 edge 화면에 도착하는지 확인하는 저수준 검증이다. field 사용자 기본 UX는 Edge가 제시한 bootstrap 명령이다. - 보조 E2E smoke — 임시 설정과 mock adapter로 최소 생존을 빠르게 확인하는 보조 검증이다. 이 결과만으로 완료 처리하지 않는다. - OpenAI-compatible Ollama smoke — `scripts/e2e-openai-ollama.sh`로 OpenAI HTTP 입력 표면이 edge service와 node adapter 경로로 수렴하는지 확인하는 보조 검증이다. - full-cycle 실제 구동 — 비효율적이어도 관련 사용자 명령과 실행 cycle을 한 번씩 실제 entrypoint로 통과시키는 검증이다. @@ -39,9 +39,9 @@ last_rule_updated_at: 2026-05-28 ## 유지할 패턴 - 테스트는 테스트 파일 변경 여부가 아니라 작업 영향 범위로 결정한다. -- 사용자 실행 파이프라인에 닿는 작업을 한 경우, 작업 완료 후 일반 Go 테스트와 변경 범위에 맞는 full-cycle 실제 구동을 검증한다. repo 내부 edge-node 진단에는 `bin/edge.sh` + `bin/node.sh`를 사용할 수 있지만, field 사용자 기본 UX는 bootstrap 명령으로 확인한다. -- 사용자 실행 파이프라인에는 `bin/**`, `apps/*/cmd/**`, `apps/*/internal/bootstrap/**`, edge-node transport/service/registry/input surface, adapter 실행/stream/cancel/status 경로, `configs/**`, `packages/config/**`, `packages/hostsetup/**`, 관련 protobuf 계약 변경이 포함된다. -- edge-node 개발 진단 흐름 검증은 `bin/edge.sh`와 `bin/node.sh`를 별도 프로세스로 직접 실행하고, edge console prompt에 명령을 한 줄씩 입력한 뒤 기대 출력이 도착한 것을 확인하고 다음 입력으로 넘어간다. +- 사용자 실행 파이프라인에 닿는 작업을 한 경우, 작업 완료 후 일반 Go 테스트와 변경 범위에 맞는 full-cycle 실제 구동을 검증한다. repo 내부 edge-node 진단에는 `scripts/dev/edge.sh` + `scripts/dev/node.sh`를 사용할 수 있지만, field 사용자 기본 UX는 bootstrap 명령으로 확인한다. +- 사용자 실행 파이프라인에는 `scripts/dev/**`, `Makefile`, `apps/*/cmd/**`, `apps/*/internal/bootstrap/**`, edge-node transport/service/registry/input surface, adapter 실행/stream/cancel/status 경로, `configs/**`, `packages/config/**`, `packages/hostsetup/**`, 관련 protobuf 계약 변경이 포함된다. +- edge-node 개발 진단 흐름 검증은 `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 별도 프로세스로 직접 실행하고, edge console prompt에 명령을 한 줄씩 입력한 뒤 기대 출력이 도착한 것을 확인하고 다음 입력으로 넘어간다. - 메시지 검증 기준은 edge console에서 같은 session으로 메시지 2회를 보내고, 각 요청마다 `[edge] sent`, `[node-*-event] start`, 비어 있지 않은 `[node-*-message]`, `[node-*-event] complete`가 edge 화면에 표시되는 것이다. - 완료 이벤트만으로 정상 판정하지 않는다. node 로컬 출력에 생성된 `[node-message]` payload가 edge console의 `[node-*-message]` 출력에 모두 표시되어야 하며, complete event는 모든 message payload가 edge에 도착한 뒤의 마감 신호로 본다. - command 검증 기준은 edge console에서 `/nodes`와 변경 범위에 닿는 command를 직접 입력하고, node에서 온 결과가 edge 화면에 `[node-*-]` 또는 명확한 성공/unsupported/error 출력으로 표시되는 것이다. CLI 경로 변경 시 최소 `/capabilities`, `/transport`, `/sessions`, persistent profile이면 `/terminate-session`을 확인한다. @@ -53,7 +53,7 @@ last_rule_updated_at: 2026-05-28 - field Node bootstrap의 사용자 명령은 `curl -fsSL <완성된-bootstrap-url> | bash -s ` 형태를 기준으로 한다. 다른 bootstrap/enrollment 작업에서도 같은 수준의 단일 token UX를 우선 적용하고, 예외가 필요하면 사용자에게 먼저 확인한다. - repo 내부 edge-node 진단의 상세 수행 절차와 기능별 체크리스트는 `agent-ops/skills/project/e2e-smoke/SKILL.md`를 따른다. - `make test-e2e`, `scripts/e2e-smoke.sh`, `scripts/e2e-openai-ollama.sh`는 보조 smoke 명령이다. 실행할 수 있으면 보조 확인으로 기록하되, full-cycle 실제 구동이나 field bootstrap 검증을 대체하지 않는다. -- `iop-edge bootstrap pack` 또는 내장 artifact server 변경 시 최소 현재 host target build를 실행하고 artifact 폴더 위치, checksum 생성, node bootstrap script가 positional token UX를 유지하는지 확인한다. +- `iop-edge bootstrap pack`, `make pack-edge`, 내장 artifact server 변경 시 최소 현재 host target build를 실행하고 archive 압축 해제, artifact 폴더 위치, checksum 생성, node bootstrap script가 positional token UX를 유지하는지 확인한다. - 풀테스트에서는 실제 외부 CLI profile 검증을 필수로 수행한다. 환경, 계정, provider, 원격 endpoint 문제로 호출할 수 없거나 실패한 profile은 누락하지 말고 profile별 실패 또는 blocker로 보고한다. - 작업 최종 보고에는 실행한 테스트 명령, repo 내부 edge-node 진단 수행 여부, 보조 E2E smoke 수행 여부, full-cycle 실제 구동 수행 여부를 명시한다. 수행하지 못한 필수 검증은 이유와 남은 위험을 함께 적는다. diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index b7c2adc..cb36dfd 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -23,7 +23,10 @@ - `proto/iop/` — IOP 메시지 계약 원본이다. - `proto/gen/iop/` — protobuf 생성물이다. - `configs/` — 앱별 YAML 설정 예시이다. -- `bin/` — 개발 보조 shell entrypoint와 로컬 바이너리 산출 위치이다. Edge/Node 운영 UX와 Node bootstrap artifact 준비는 `iop-edge`/`iop-node` 바이너리 command 표면에 모은다. +- `scripts/dev/` — repo 내부 개발 진단 helper 위치이다. field 사용자 기본 경로로 안내하지 않는다. +- `build/bin/` — 로컬 바이너리 산출 위치이다. +- `build/artifacts/` — Node bootstrap artifact 산출 위치이다. +- `build/packages/` — Edge host에 전달할 압축 배포 archive 산출 위치이다. archive는 `iop-edge`와 `artifacts/`를 포함하고, Edge host에서 config 확정 후 Node bootstrap을 제공하는 흐름을 기준으로 한다. - `scripts/` — 보조 E2E smoke와 입력 표면 검증 스크립트이다. - `Makefile` — 빌드와 테스트 진입점을 정의한다. - `docs/` — 사람용 최신 가이드만 둔다. 환경별 값은 `agent-ops/rules/private/`에 두고, `rules.md`는 라우터로만 쓴다. @@ -46,7 +49,7 @@ - 새 node 어댑터는 `runtime.Adapter`를 구현하고 `apps/node/internal/bootstrap/module.go`에서 registry에 등록한다. - 내부 실행 요청과 상태 저장에서는 `adapter`, `target`, `execution` 용어를 우선한다. `model`은 외부 API 호환이나 legacy placeholder일 때만 허용한다. - Control Plane은 Node를 직접 연결/스케줄링하지 않고 Edge를 통해 시스템을 제어한다. Edge는 자신의 로컬 런타임 상태와 Node registry를 소유한다. -- 사용자 실행, 로컬/dev 배포, field 테스트, 임시 Control Plane 대체 흐름은 사용법을 `bin/`, `scripts/`, 별도 dev deploy 바이너리, 모델용 skill로 흩뜨리지 않고 `iop-edge`와 `iop-node` command 표면에 모은다. helper script가 필요해도 공식 사용자 경로가 되면 안 된다. +- 사용자 실행, 로컬/dev 배포, field 테스트, 임시 Control Plane 대체 흐름은 사용법을 `scripts/dev/`, 보조 smoke script, 별도 dev deploy 바이너리, 모델용 skill로 흩뜨리지 않고 `iop-edge`와 `iop-node` command 표면에 모은다. helper script가 필요해도 공식 사용자 경로가 되면 안 된다. - Control Plane이 없는 테스트/개발 배포 단계에서는 `edge.yaml`을 테스트용 Control Plane source of truth로 본다. Node별 id/alias/token/adapter/runtime 설정은 Edge config의 `nodes[]`에서 관리한다. - Node 사용자 UX는 bootstrap 명령 하나로 끝나야 한다. 사용자가 `node.yaml`을 만들거나 편집하거나 `iop-node serve --config ...`를 직접 실행하는 흐름을 기본 경로로 두지 않는다. bootstrap 내부에서 임시 상태나 설정 파일을 만들 수 있더라도 이는 구현 세부이며 사용자 가이드와 기본 운영 UX에 노출하지 않는다. - 바이너리 배포 UX는 repo checkout 위치에 묶이지 않아야 한다. `iop-edge`/`iop-node`는 아무 작업 디렉터리에서 실행 가능해야 하며, 로컬/dev bundle에서는 Edge 설정을 바이너리와 같은 디렉터리의 `edge.yaml` 같은 구조화된 config에 모으는 방향을 우선한다. Node 쪽은 별도 사용자 config 파일이 아니라 Edge가 제공하는 bootstrap으로 연결한다. @@ -75,7 +78,7 @@ | `packages/**` | platform-common | `agent-ops/rules/project/domain/platform-common/rules.md` | | `proto/**` | platform-common | `agent-ops/rules/project/domain/platform-common/rules.md` | | `configs/**` | platform-common | `agent-ops/rules/project/domain/platform-common/rules.md` | -| `bin/**` | testing | `agent-ops/rules/project/domain/testing/rules.md` | +| `scripts/dev/**` | testing | `agent-ops/rules/project/domain/testing/rules.md` | | `scripts/e2e-*.sh` | testing | `agent-ops/rules/project/domain/testing/rules.md` | | `Makefile` | testing | `agent-ops/rules/project/domain/testing/rules.md` | @@ -85,7 +88,7 @@ ## 스킬 라우팅 -- 사용자 실행 파이프라인 검증, repo 내부 edge-node 진단, 메시지 2회 왕복, edge command 응답, 보조 E2E smoke, full-cycle 실제 구동, `bin/edge.sh`/`bin/node.sh` 진단 테스트: `agent-ops/skills/project/e2e-smoke/SKILL.md` +- 사용자 실행 파이프라인 검증, repo 내부 edge-node 진단, 메시지 2회 왕복, edge command 응답, 보조 E2E smoke, full-cycle 실제 구동, `scripts/dev/edge.sh`/`scripts/dev/node.sh` 진단 테스트: `agent-ops/skills/project/e2e-smoke/SKILL.md` - field 테스트 포트, artifact/bootstrap HTTP, 외부 테스트 환경: private rule 라우팅을 따른다. - bootstrap/install UX, Agent Bootstrap, OTO 등록, Control Plane enrollment: `testing` domain rule과 private rule 라우팅을 따른다. - 반복 작업이 확인되면 `agent-ops/skills/project//SKILL.md`를 생성하고 이 표에 등록한다. diff --git a/agent-ops/skills/project/e2e-smoke/SKILL.md b/agent-ops/skills/project/e2e-smoke/SKILL.md index 2950345..0192601 100644 --- a/agent-ops/skills/project/e2e-smoke/SKILL.md +++ b/agent-ops/skills/project/e2e-smoke/SKILL.md @@ -1,19 +1,19 @@ --- name: e2e-smoke version: 1.1.0 -description: bin/edge.sh와 bin/node.sh 기반 repo 내부 edge-node 진단, 보조 E2E smoke, 실제 외부 CLI 통합 검증 절차 +description: scripts/dev/edge.sh와 scripts/dev/node.sh 기반 repo 내부 edge-node 진단, 보조 E2E smoke, 실제 외부 CLI 통합 검증 절차 --- # e2e-smoke ## 목적 -repo 내부 edge-node 진단이 필요할 때 `bin/edge.sh`와 `bin/node.sh`를 각각 실행하고, edge console에서 메시지 2회와 command 명령을 직접 보내 결과가 edge 화면에 표시되는지 검증한다. field 사용자 기본 UX는 Edge가 제시한 bootstrap 명령이며, `bin/*` helper를 공식 사용자 경로로 안내하지 않는다. `make test-e2e`와 `scripts/e2e-smoke.sh`는 최소 생존을 빠르게 확인하는 보조 smoke일 뿐이며, 사용자 실행 파이프라인 변경의 완료 기준이 아니다. +repo 내부 edge-node 진단이 필요할 때 `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 각각 실행하고, edge console에서 메시지 2회와 command 명령을 직접 보내 결과가 edge 화면에 표시되는지 검증한다. field 사용자 기본 UX는 Edge가 제시한 bootstrap 명령이며, `scripts/dev/*` helper를 공식 사용자 경로로 안내하지 않는다. `make test-e2e`와 `scripts/e2e-smoke.sh`는 최소 생존을 빠르게 확인하는 보조 smoke일 뿐이며, 사용자 실행 파이프라인 변경의 완료 기준이 아니다. ## 언제 호출할지 - 사용자 실행 파이프라인에 닿는 작업을 완료한 뒤 검증 단계에 들어갈 때 -- `bin/**`, `apps/*/cmd/**`, `apps/*/internal/bootstrap/**`, edge-node transport/service/registry, adapter 실행/stream/cancel/status 경로를 변경했을 때 +- `scripts/dev/**`, `Makefile`, `apps/*/cmd/**`, `apps/*/internal/bootstrap/**`, edge-node transport/service/registry, adapter 실행/stream/cancel/status 경로를 변경했을 때 - `configs/**`, `packages/config/**`, 관련 protobuf 계약 변경이 edge-node 실행 방식에 영향을 줄 때 - `make test-e2e` 또는 보조 E2E smoke 스크립트를 만들거나 갱신할 때 @@ -27,7 +27,7 @@ repo 내부 edge-node 진단이 필요할 때 `bin/edge.sh`와 `bin/node.sh`를 ## 먼저 확인할 것 - [ ] `agent-ops/rules/project/domain/testing/rules.md`를 읽고 이번 작업에 필요한 repo 내부 edge-node 진단 또는 field bootstrap 검증 범위를 확인한다. -- [ ] `bin/edge.sh`와 `bin/node.sh`는 repo 내부 진단 helper이며 field 사용자 기본 entrypoint가 아님을 확인한다. +- [ ] `scripts/dev/edge.sh`와 `scripts/dev/node.sh`는 repo 내부 진단 helper이며 field 사용자 기본 entrypoint가 아님을 확인한다. - [ ] `make test-e2e` 같은 고정 smoke 명령은 보조 확인으로만 취급한다. - [ ] 기본 `configs/*.yaml`을 오염시키지 않도록 임시 config 또는 환경 변수 override 전략을 정한다. - [ ] 실제 외부 CLI 검증이 필요한 경우 command 경로, 로그인/계정 상태, provider 설정, workspace 권한이 준비되어 있는지 확인한다. @@ -36,18 +36,18 @@ repo 내부 edge-node 진단이 필요할 때 `bin/edge.sh`와 `bin/node.sh`를 1. **검증 범위 결정** - 변경 파일이 사용자 실행 파이프라인에 닿는지 확인한다. - - 필수 검증은 `go test ./...` 또는 대상 패키지 테스트와 변경 범위에 맞는 full-cycle 실제 구동이다. repo 내부 edge-node 진단에는 `bin/edge.sh`와 `bin/node.sh`를 사용할 수 있다. + - 필수 검증은 `go test ./...` 또는 대상 패키지 테스트와 변경 범위에 맞는 full-cycle 실제 구동이다. repo 내부 edge-node 진단에는 `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 사용할 수 있다. - 보조 smoke는 실행할 수 있으면 기록하되, 통과만으로 완료 처리하지 않는다. - 풀테스트에서는 실제 외부 CLI profile 검증을 full-cycle에 포함한다. 2. **repo 내부 edge-node 진단 준비** - - edge와 node는 `bin/edge.sh`, `bin/node.sh`를 각각 별도 프로세스로 실행한다. 이 흐름은 내부 진단용이며 사용자-facing field bootstrap 안내가 아니다. + - edge와 node는 `scripts/dev/edge.sh`, `scripts/dev/node.sh`를 각각 별도 프로세스로 실행한다. 이 흐름은 내부 진단용이며 사용자-facing field bootstrap 안내가 아니다. - 임시 edge/node config 또는 환경 변수 override를 사용하고, edge listen 주소와 node edge 주소는 충돌을 피하기 위해 임시 포트를 사용한다. - 검증용 target은 변경 범위에 맞춘다. 외부 CLI 자체가 검증 대상이 아니면 deterministic CLI profile을 사용해 메시지 출력 내용을 분명하게 만든다. 3. **startup/register cycle** - - 먼저 `bin/edge.sh`를 실행해 edge console prompt가 뜨는지 확인한다. - - 다른 프로세스에서 `bin/node.sh`를 실행해 node가 edge에 연결되는지 확인한다. + - 먼저 `scripts/dev/edge.sh`를 실행해 edge console prompt가 뜨는지 확인한다. + - 다른 프로세스에서 `scripts/dev/node.sh`를 실행해 node가 edge에 연결되는지 확인한다. - edge 화면에 `[node-*-event] connected reason="registered"`가 표시되어야 한다. - edge console에서 `/nodes`를 입력하고 node ID와 alias가 표시되어야 한다. @@ -132,7 +132,7 @@ terminated session default node=test-node ## 실행 결과 검증 - [ ] 일반 Go 테스트 또는 대상 패키지 테스트 결과가 보고되었는가 -- [ ] `bin/edge.sh`와 `bin/node.sh`를 각각 실행한 repo 내부 edge-node 진단 결과가 보고되었는가 +- [ ] `scripts/dev/edge.sh`와 `scripts/dev/node.sh`를 각각 실행한 repo 내부 edge-node 진단 결과가 보고되었는가 - [ ] node register와 `/nodes` 결과가 edge 화면에 표시되었는가 - [ ] 같은 session에서 메시지 2회가 각각 sent/start/message/complete로 표시되었는가 - [ ] node 로컬 `[node-message]` payload가 edge `[node-*-message]` 출력에 모두 표시되었는가 diff --git a/apps/edge/README.md b/apps/edge/README.md index 4dc41fd..8ac8869 100644 --- a/apps/edge/README.md +++ b/apps/edge/README.md @@ -28,7 +28,7 @@ ops console은 edge-local diagnostic surface이고, HTTP/API는 central/remote m ## 원격 CLI adapter 개발 진단 흐름 -field 사용자 기본 경로는 `iop-edge`가 제시한 bootstrap 명령으로 Node를 연결하는 흐름이다. `bin/edge.sh`와 `bin/node.sh`는 repo 내부 개발 진단 helper이며 공식 사용자 UX로 안내하지 않는다. +field 사용자 기본 경로는 `iop-edge`가 제시한 bootstrap 명령으로 Node를 연결하는 흐름이다. `scripts/dev/edge.sh`와 `scripts/dev/node.sh`는 repo 내부 개발 진단 helper이며 공식 사용자 UX로 안내하지 않는다. 개발 진단의 기준은 `make test-e2e`나 smoke 통과만이 아니라, edge console에서 메시지와 command를 직접 보내 결과가 edge 화면에 표시되는지 확인하는 것이다. 구체적인 내부 진단 절차는 `agent-ops/skills/project/e2e-smoke/SKILL.md`로 모은다. `make test-e2e` 명령은 `scripts/e2e-smoke.sh`를 실행하는 보조 smoke이며, 최소 생존 확인에는 쓸 수 있지만 완료 기준을 대체하지 않는다. @@ -104,6 +104,9 @@ sudo iop-edge setup --dry-run --binary /usr/local/bin/iop-edge sudo iop-edge setup --enable --start --binary /usr/local/bin/iop-edge ``` +Edge 배포 archive는 repo root에서 `make pack-node-target NODE_TARGET=-` 후 `make pack-edge`로 만든다. +archive에는 `iop-edge`와 Node bootstrap용 `artifacts/`가 들어가며, Edge host에서 `config init`과 `node register`를 수행해 현재 host 기준 bootstrap URL을 확정한다. + `setup`의 `--config` 기본값은 `/etc/iop/edge.yaml`이다. dev 단계 명령(`serve`, `console`, `config init/print/check`, `env`, `node register`)의 root persistent `--config` 기본값은 bundle-local `edge.yaml` (없을 시 executable-adjacent `edge.yaml`, 그 다음 repo dev fallback `configs/edge.yaml`)로 확인된다. 기존 설정 파일은 그대로 두며 `--overwrite-config`를 지정해야 덮어쓴다. ## Console 명령 diff --git a/apps/edge/cmd/edge/main.go b/apps/edge/cmd/edge/main.go index ab467cf..6c856e2 100644 --- a/apps/edge/cmd/edge/main.go +++ b/apps/edge/cmd/edge/main.go @@ -609,8 +609,18 @@ func packNodeBootstrap(opts nodeBootstrapPackOptions) error { return fmt.Errorf("mkdir target dir: %w", err) } dstNode := filepath.Join(targetDir, "iop-node") - if err := copyFile(opts.NodeBinary, dstNode, 0o755); err != nil { - return fmt.Errorf("copy iop-node: %w", err) + same, err := sameFile(opts.NodeBinary, dstNode) + if err != nil { + return fmt.Errorf("stat iop-node: %w", err) + } + if same { + if err := os.Chmod(dstNode, 0o755); err != nil { + return fmt.Errorf("chmod iop-node: %w", err) + } + } else { + if err := copyFile(opts.NodeBinary, dstNode, 0o755); err != nil { + return fmt.Errorf("copy iop-node: %w", err) + } } sum, err := fileSHA256(dstNode) if err != nil { @@ -635,6 +645,21 @@ func packNodeBootstrap(opts nodeBootstrapPackOptions) error { return nil } +func sameFile(a, b string) (bool, error) { + ai, err := os.Stat(a) + if err != nil { + return false, err + } + bi, err := os.Stat(b) + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + if err != nil { + return false, err + } + return os.SameFile(ai, bi), nil +} + func copyFile(src, dst string, mode os.FileMode) error { in, err := os.Open(src) if err != nil { @@ -758,6 +783,26 @@ var tokenGenerator = func() string { return uuid.NewString() } +func refreshBootstrapForExistingArtifact(cfg *config.EdgeConfig, target, artifactURL string) error { + outputDir := resolveBootstrapArtifactDir(cfg.Bootstrap.ArtifactDir) + nodeBinary := filepath.Join(outputDir, target, "iop-node") + if _, err := os.Stat(nodeBinary); err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } + return fmt.Errorf("stat node artifact: %w", err) + } + adv := resolveAdvertiseHost(cfg.Server.AdvertiseHost) + return packNodeBootstrap(nodeBootstrapPackOptions{ + NodeBinary: nodeBinary, + OutputDir: outputDir, + Target: target, + Version: version.Version, + ArtifactBaseURL: artifactURL, + EdgeAddr: addressFor(adv.Host, cfg.Server.Listen), + }) +} + func validateEdgeConfig(cfg *config.EdgeConfig) error { // 1. Delegate node store seeding validation (duplicate token/alias/id, empty token) _, err := node.LoadFromConfig(cfg.Nodes) @@ -979,6 +1024,9 @@ directly in the default flow.`, if err := validateEdgeConfig(&cfg); err != nil { return fmt.Errorf("validate node register: %w", err) } + if err := refreshBootstrapForExistingArtifact(&cfg, target, artifactURL); err != nil { + return fmt.Errorf("refresh bootstrap artifacts: %w", err) + } // Patch raw YAML to preserve defaults and other sections outData, err := patchYAML(data, &cfg) diff --git a/apps/edge/cmd/edge/main_test.go b/apps/edge/cmd/edge/main_test.go index 222cd3d..772b93f 100644 --- a/apps/edge/cmd/edge/main_test.go +++ b/apps/edge/cmd/edge/main_test.go @@ -454,6 +454,60 @@ bootstrap: } } +func TestNodeRegisterRefreshesExistingBootstrapArtifact(t *testing.T) { + dir := t.TempDir() + artifactDir := filepath.Join(dir, "artifacts") + target := "darwin-arm64" + targetDir := filepath.Join(artifactDir, target) + if err := os.MkdirAll(targetDir, 0o755); err != nil { + t.Fatalf("mkdir target dir: %v", err) + } + if err := os.WriteFile(filepath.Join(targetDir, "iop-node"), []byte("fake-node-binary"), 0o755); err != nil { + t.Fatalf("write node artifact: %v", err) + } + + cfgPath := filepath.Join(dir, "edge.yaml") + yamlStr := `server: + listen: "127.0.0.1:39090" + advertise_host: "edge.deploy.test" +bootstrap: + listen: "127.0.0.1:38080" + artifact_dir: "` + artifactDir + `" +nodes: [] +` + if err := os.WriteFile(cfgPath, []byte(yamlStr), 0o600); err != nil { + t.Fatalf("write config: %v", err) + } + + root := rootCmd() + var out bytes.Buffer + root.SetOut(&out) + root.SetErr(&out) + root.SetArgs([]string{ + "--config", cfgPath, + "node", "register", "mac-node", + "--target", target, + "--token", "test-token", + }) + if err := root.Execute(); err != nil { + t.Fatalf("execute register: %v\n%s", err, out.String()) + } + + script, err := os.ReadFile(filepath.Join(artifactDir, "bootstrap", "node-"+target+".sh")) + if err != nil { + t.Fatalf("read refreshed script: %v", err) + } + if !strings.Contains(string(script), `DEFAULT_ARTIFACT_BASE_URL="http://edge.deploy.test:38080"`) { + t.Fatalf("script missing refreshed artifact URL:\n%s", script) + } + if !strings.Contains(string(script), `DEFAULT_EDGE_ADDR="edge.deploy.test:39090"`) { + t.Fatalf("script missing refreshed edge addr:\n%s", script) + } + if !strings.Contains(out.String(), `curl -fsSL http://edge.deploy.test:38080/bootstrap/node-darwin-arm64.sh | bash -s test-token`) { + t.Fatalf("unexpected register output:\n%s", out.String()) + } +} + func TestResolveAdvertiseHostPrefersExplicit(t *testing.T) { got := resolveAdvertiseHost("explicit.example.test") if got.Host != "explicit.example.test" || got.Source != "explicit" { @@ -1010,7 +1064,7 @@ func TestHelpDiscoversEdgeLocalDevFlow(t *testing.T) { } // 2. Assert absence of non-official/legacy paths (verify they aren't recommended) - for _, unwanted := range []string{"bin/edge.sh", "bin/node.sh", "dev-deploy"} { + for _, unwanted := range []string{"scripts/dev/edge.sh", "scripts/dev/node.sh", "dev-deploy"} { if strings.Contains(got, unwanted) { t.Errorf("root help contains legacy path reference: %q", unwanted) } diff --git a/apps/node/README.md b/apps/node/README.md index 3fb4bd3..c40e91e 100644 --- a/apps/node/README.md +++ b/apps/node/README.md @@ -33,7 +33,7 @@ Edge가 제시한 bootstrap 명령 한 줄을 실행하면 Node binary 다운로 make build-node # 버전 확인 -./bin/iop-node version +./build/bin/iop-node version # 저수준 직접 실행은 내부 진단에서만 사용한다. ``` @@ -50,7 +50,7 @@ iop-node serve iop-node version ``` -원격 edge에 붙는 사용자/field 테스트는 Edge가 제시한 bootstrap 명령을 실행한다. repo root의 `bin/node.sh`는 과거 개발 진단 helper로만 취급하고, 문서나 runbook의 공식 사용자 경로로 안내하지 않는다. +원격 edge에 붙는 사용자/field 테스트는 Edge가 제시한 bootstrap 명령을 실행한다. repo root의 `scripts/dev/node.sh`는 과거 개발 진단 helper로만 취급하고, 문서나 runbook의 공식 사용자 경로로 안내하지 않는다. edge 예시 설정은 cli adapter의 `opencode` profile을 사용한다. `configs/edge.yaml`의 `console.target`을 `claude`, `claude-tui`, `antigravity`, `codex`, `opencode`, `cline-dgx` 같은 profile 이름으로 바꾸면 같은 실행 파이프라인에서 다른 CLI target을 검증할 수 있다. diff --git a/docs/edge-local-dev-guide.md b/docs/edge-local-dev-guide.md index bc5e17e..79909e3 100644 --- a/docs/edge-local-dev-guide.md +++ b/docs/edge-local-dev-guide.md @@ -8,12 +8,12 @@ - `node.yaml` 생성, 편집, 확인 - `edge.yaml`의 `nodes[]` 수동 작성 - `iop-node serve --config ...` 직접 실행 -- `bin/*.sh` helper나 별도 dev deploy 바이너리를 공식 경로로 사용 +- `scripts/dev/*.sh` helper나 별도 dev deploy 바이너리를 공식 경로로 사용 -## 1. 빌드 +## 1. 빌드와 Edge 배포 패키지 공식 빌드 진입점은 `make build` 하나로 둔다. -이 명령은 Edge와 Node를 함께 빌드하고, 현재 host에서 바로 쓸 수 있는 바이너리만 `bin/`에 맞춰 둔다. +이 명령은 Edge와 Node를 함께 빌드하고, 현재 host에서 바로 쓸 수 있는 바이너리만 `build/bin/`에 맞춰 둔다. ```bash make build @@ -29,32 +29,51 @@ make build-node 산출물: ```text -bin/iop-edge -bin/iop-node +build/bin/iop-edge +build/bin/iop-node ``` -## 2. Bundle 디렉터리 준비 +Edge host에 배포할 때는 Node target artifact를 먼저 준비한 뒤 Edge archive를 만든다. -하나의 디렉터리에 `iop-edge`와 `iop-node` 바이너리가 함께 있다고 가정한다. +```bash +make pack-node-target NODE_TARGET=darwin-arm64 +make pack-edge +``` + +Intel Mac Node면 `NODE_TARGET=darwin-amd64`를 사용한다. +Edge만 새로 빌드한 경우에는 기존 `build/artifacts/`를 유지한 상태에서 `make pack-edge`만 다시 실행한다. +Node binary를 새로 빌드한 경우에는 `make pack-node-target NODE_TARGET=-` 후 `make pack-edge`를 다시 실행한다. + +배포 산출물: ```text -/opt/iop-dev/ - iop-edge - iop-node +build/packages/iop-edge--.tar.gz ``` -repo-local 테스트는 `bin/`을 그대로 bundle 디렉터리로 사용할 수 있다. +## 2. Edge 패키지 압축 해제 + +Edge host에서는 archive 하나만 옮긴 뒤 압축을 푼다. ```bash -cd bin +tar -xzf build/packages/iop-edge-$(go env GOOS)-$(go env GOARCH).tar.gz -C /opt +cd /opt/iop-edge-$(go env GOOS)-$(go env GOARCH) ``` -별도 디렉터리에서 테스트할 때는 repo root에서 빌드된 바이너리만 옮긴 뒤 그 디렉터리에서 실행한다. +압축 해제 후 기본 구조: + +```text +iop-edge +artifacts/ +logs/ +``` + +repo-local에서 archive 없이 확인할 때는 새 bundle 디렉터리에 Edge binary와 artifacts를 함께 둔다. ```bash -mkdir -p /opt/iop-dev -cp bin/iop-edge bin/iop-node /opt/iop-dev/ -cd /opt/iop-dev +mkdir -p /tmp/iop-edge-dev +cp build/bin/iop-edge /tmp/iop-edge-dev/ +cp -R build/artifacts /tmp/iop-edge-dev/ +cd /tmp/iop-edge-dev ``` ## 3. Edge config 생성 @@ -102,30 +121,21 @@ connected nodes /logs/ ``` -## 5. Bootstrap artifact 준비 +## 5. Bootstrap artifact 확인 -Node host에서 bootstrap 명령까지 테스트하려면 `iop-edge serve`가 제공할 artifact 폴더를 준비한다. - -```bash -./iop-edge bootstrap pack -``` - -기본 산출물: +Edge archive에는 `make pack-node-target`으로 준비한 Node artifact가 들어 있어야 한다. ```text -/artifacts/ +artifacts/ bootstrap/node--.sh -/iop-node -/SHA256SUMS ``` -Mac Node host용 artifact가 필요하면 repo root에서 대상 platform을 지정해 pack한다. +`node register`는 해당 target의 `artifacts//iop-node`가 있으면 현재 `edge.yaml` 기준으로 bootstrap script와 checksum을 다시 생성한다. +즉 build machine에서 만든 archive를 다른 Edge host에 풀어도, Edge host에서 config를 확정한 뒤 등록하면 Node가 받을 URL과 Edge 주소가 현재 host 기준으로 맞춰진다. -```bash -make pack-node-target NODE_TARGET=darwin-arm64 -``` - -Intel Mac이면 `NODE_TARGET=darwin-amd64`를 사용한다. +새 Node binary를 Edge host에서 직접 교체한 경우에만 `./iop-edge bootstrap pack --target - --node-binary `로 다시 pack한다. ## 6. Node 등록과 bootstrap 출력 @@ -147,6 +157,7 @@ Ollama Node로 등록할 때: ``` 이 명령은 `edge.yaml`의 `nodes[]`를 생성 또는 갱신하고, 마지막에 Node host에서 실행할 bootstrap 명령을 출력한다. +`--target` 값은 `artifacts//`에 들어 있는 Node artifact와 같아야 한다. 출력 예: diff --git a/bin/edge.sh b/scripts/dev/edge.sh similarity index 86% rename from bin/edge.sh rename to scripts/dev/edge.sh index 4520766..fff4be1 100755 --- a/bin/edge.sh +++ b/scripts/dev/edge.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" CONFIG_FILE="${IOP_EDGE_CONFIG:-$REPO_ROOT/configs/edge.yaml}" cd "$REPO_ROOT" diff --git a/bin/node.sh b/scripts/dev/node.sh similarity index 90% rename from bin/node.sh rename to scripts/dev/node.sh index bb269be..db32522 100755 --- a/bin/node.sh +++ b/scripts/dev/node.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" CONFIG_FILE="${IOP_NODE_CONFIG:-$REPO_ROOT/configs/node.yaml}" cd "$REPO_ROOT" @@ -26,7 +26,7 @@ echo "[node] waiting for edge at $EDGE_HOST:$EDGE_PORT timeout=${WAIT_TIMEOUT}s" deadline=$((SECONDS + WAIT_TIMEOUT)) while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/"$1"/"$2"' _ "$EDGE_HOST" "$EDGE_PORT" 2>/dev/null; do if (( SECONDS >= deadline )); then - echo "[node] edge is not reachable at $EDGE_HOST:$EDGE_PORT; start ./bin/edge.sh first or update configs/node.yaml transport.edge_addr" >&2 + echo "[node] edge is not reachable at $EDGE_HOST:$EDGE_PORT; start ./scripts/dev/edge.sh first or update configs/node.yaml transport.edge_addr" >&2 exit 1 fi sleep "$WAIT_INTERVAL" diff --git a/bin/web.sh b/scripts/dev/web.sh similarity index 94% rename from bin/web.sh rename to scripts/dev/web.sh index 0a3c9a5..bd549bc 100755 --- a/bin/web.sh +++ b/scripts/dev/web.sh @@ -2,7 +2,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" PORTAL_DIR="$REPO_ROOT/apps/portal" WEB_HOST="${IOP_WEB_HOST:-0.0.0.0}" diff --git a/scripts/e2e-openai-ollama.sh b/scripts/e2e-openai-ollama.sh index 6b659ea..3366d6c 100755 --- a/scripts/e2e-openai-ollama.sh +++ b/scripts/e2e-openai-ollama.sh @@ -23,6 +23,7 @@ cleanup() { trap cleanup EXIT PORT=$((31000 + RANDOM % 5000)) +BOOTSTRAP_PORT=$((21000 + RANDOM % 5000)) OPENAI_PORT=$((36000 + RANDOM % 5000)) OLLAMA_PORT=$((41000 + RANDOM % 5000)) EDGE_METRICS_PORT=$((46000 + RANDOM % 5000)) @@ -116,6 +117,9 @@ server: listen: "127.0.0.1:$PORT" metrics: port: $EDGE_METRICS_PORT +bootstrap: + listen: "127.0.0.1:$BOOTSTRAP_PORT" + artifact_dir: "$TMP_DIR/artifacts" openai: enabled: true listen: "127.0.0.1:$OPENAI_PORT" @@ -157,7 +161,7 @@ EOF EDGE_OUT="$TMP_DIR/edge.out" NODE_OUT="$TMP_DIR/node.out" mkfifo "$TMP_DIR/edge_fifo" -IOP_EDGE_CONFIG="$EDGE_CONFIG" "$REPO_ROOT/bin/edge.sh" < "$TMP_DIR/edge_fifo" > "$EDGE_OUT" 2>&1 & +IOP_EDGE_CONFIG="$EDGE_CONFIG" "$REPO_ROOT/scripts/dev/edge.sh" < "$TMP_DIR/edge_fifo" > "$EDGE_OUT" 2>&1 & EDGE_PID=$! exec 3> "$TMP_DIR/edge_fifo" EDGE_FD_OPEN=1 @@ -165,7 +169,7 @@ EDGE_FD_OPEN=1 wait_port 127.0.0.1 "$PORT" "edge node transport" wait_port 127.0.0.1 "$OPENAI_PORT" "edge openai api" -IOP_NODE_CONFIG="$NODE_CONFIG" "$REPO_ROOT/bin/node.sh" > "$NODE_OUT" 2>&1 & +IOP_NODE_CONFIG="$NODE_CONFIG" "$REPO_ROOT/scripts/dev/node.sh" > "$NODE_OUT" 2>&1 & NODE_PID=$! deadline=$((SECONDS + 30)) diff --git a/scripts/e2e-smoke.sh b/scripts/e2e-smoke.sh index c8a41c7..b8258d7 100755 --- a/scripts/e2e-smoke.sh +++ b/scripts/e2e-smoke.sh @@ -4,11 +4,11 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -echo "[e2e] NOTE: auxiliary smoke only; completion requires bin/edge.sh + bin/node.sh user-flow verification." +echo "[e2e] NOTE: auxiliary smoke only; completion requires scripts/dev/edge.sh + scripts/dev/node.sh user-flow verification." if command -v shellcheck >/dev/null 2>&1; then echo "[e2e] running shellcheck..." - shellcheck "$0" "$REPO_ROOT/bin/edge.sh" "$REPO_ROOT/bin/node.sh" + shellcheck "$0" "$REPO_ROOT/scripts/dev/edge.sh" "$REPO_ROOT/scripts/dev/node.sh" else echo "[e2e] shellcheck not found, skipping" fi @@ -20,6 +20,7 @@ EDGE_CONFIG="$TMP_DIR/edge.yaml" NODE_CONFIG="$TMP_DIR/node.yaml" PORT=$((30000 + RANDOM % 10000)) +BOOTSTRAP_PORT=$((20000 + RANDOM % 10000)) EDGE_METRICS_PORT=$((40000 + RANDOM % 10000)) NODE_METRICS_PORT=$((50000 + RANDOM % 10000)) PROFILE="${IOP_E2E_PROFILE:-mock}" @@ -65,6 +66,9 @@ server: listen: "127.0.0.1:$PORT" metrics: port: $EDGE_METRICS_PORT +bootstrap: + listen: "127.0.0.1:$BOOTSTRAP_PORT" + artifact_dir: "$TMP_DIR/artifacts" nodes: - id: test-node alias: test-node @@ -127,6 +131,9 @@ server: listen: "127.0.0.1:$PORT" metrics: port: $EDGE_METRICS_PORT +bootstrap: + listen: "127.0.0.1:$BOOTSTRAP_PORT" + artifact_dir: "$TMP_DIR/artifacts" nodes: - id: test-node alias: test-node @@ -164,7 +171,7 @@ NODE_OUT="$TMP_DIR/node_out" rm -f "$TMP_DIR/edge_fifo" mkfifo "$TMP_DIR/edge_fifo" -IOP_EDGE_CONFIG="$EDGE_CONFIG" "$REPO_ROOT/bin/edge.sh" < "$TMP_DIR/edge_fifo" > "$EDGE_OUT" 2>&1 & +IOP_EDGE_CONFIG="$EDGE_CONFIG" "$REPO_ROOT/scripts/dev/edge.sh" < "$TMP_DIR/edge_fifo" > "$EDGE_OUT" 2>&1 & EDGE_PID=$! exec 3> "$TMP_DIR/edge_fifo" @@ -178,7 +185,7 @@ while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/'"$PORT" 2>/dev/ sleep 0.5 done -IOP_NODE_CONFIG="$NODE_CONFIG" "$REPO_ROOT/bin/node.sh" > "$NODE_OUT" 2>&1 & +IOP_NODE_CONFIG="$NODE_CONFIG" "$REPO_ROOT/scripts/dev/node.sh" > "$NODE_OUT" 2>&1 & NODE_PID=$! LAST_CMD_START_LINE=1 @@ -549,5 +556,5 @@ if [ $FAIL -eq 1 ]; then fi echo "[e2e] Auxiliary smoke test PASSED." -echo "[e2e] Completion still requires bin/edge.sh + bin/node.sh user-flow verification." +echo "[e2e] Completion still requires scripts/dev/edge.sh + scripts/dev/node.sh user-flow verification." exit 0