refactor: move dev scripts to scripts/dev/ and update configurations
This commit is contained in:
parent
5c3fef65e9
commit
e02ae80ce6
15 changed files with 229 additions and 90 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -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/
|
||||
|
|
|
|||
42
Makefile
42
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 <goos>-<goarch>" >&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=<goos>-<goarch> 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
|
||||
|
|
|
|||
|
|
@ -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-*-<command>]` 또는 명확한 성공/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 <token>` 형태를 기준으로 한다. 다른 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 실제 구동 수행 여부를 명시한다. 수행하지 못한 필수 검증은 이유와 남은 위험을 함께 적는다.
|
||||
|
||||
|
|
|
|||
|
|
@ -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-name>/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]` 출력에 모두 표시되었는가
|
||||
|
|
|
|||
|
|
@ -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=<goos>-<goarch>` 후 `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 명령
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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을 검증할 수 있다.
|
||||
|
||||
|
|
|
|||
|
|
@ -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=<goos>-<goarch>` 후 `make pack-edge`를 다시 실행한다.
|
||||
|
||||
배포 산출물:
|
||||
|
||||
```text
|
||||
/opt/iop-dev/
|
||||
iop-edge
|
||||
iop-node
|
||||
build/packages/iop-edge-<edge-os>-<edge-arch>.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
|
|||
<bundle-dir>/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
|
||||
<bundle-dir>/artifacts/
|
||||
artifacts/
|
||||
bootstrap/node-<os>-<arch>.sh
|
||||
<os>-<arch>/iop-node
|
||||
<os>-<arch>/SHA256SUMS
|
||||
```
|
||||
|
||||
Mac Node host용 artifact가 필요하면 repo root에서 대상 platform을 지정해 pack한다.
|
||||
`node register`는 해당 target의 `artifacts/<target>/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 <goos>-<goarch> --node-binary <path>`로 다시 pack한다.
|
||||
|
||||
## 6. Node 등록과 bootstrap 출력
|
||||
|
||||
|
|
@ -147,6 +157,7 @@ Ollama Node로 등록할 때:
|
|||
```
|
||||
|
||||
이 명령은 `edge.yaml`의 `nodes[]`를 생성 또는 갱신하고, 마지막에 Node host에서 실행할 bootstrap 명령을 출력한다.
|
||||
`--target` 값은 `artifacts/<target>/`에 들어 있는 Node artifact와 같아야 한다.
|
||||
|
||||
출력 예:
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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"
|
||||
|
|
@ -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}"
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue