|
|
|
@@ -1,3 +1,5 @@
|
|
|
|
|
import { resolve } from "node:path";
|
|
|
|
|
|
|
|
|
|
import { runCommand } from "./command";
|
|
|
|
|
import { readEnvSourceFile, requiredEnvValue } from "./secrets";
|
|
|
|
|
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneSpecForNode, isHwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeNativeDevelopmentSpec } from "./hwlab-node-lanes";
|
|
|
|
@@ -12,6 +14,7 @@ export function hwlabNativeDevelopmentHelp(): Record<string, unknown> {
|
|
|
|
|
command: "hwlab nodes native-development workbench",
|
|
|
|
|
usage: [
|
|
|
|
|
"bun scripts/cli.ts hwlab nodes native-development workbench api|worker|web start|stop|restart|status|logs --node <node> --lane <lane>",
|
|
|
|
|
"bun scripts/cli.ts hwlab nodes native-development workbench cli <health|session|turn|events ...> --node <node> --lane <lane>",
|
|
|
|
|
"bun scripts/cli.ts hwlab nodes native-development caserun api|web start|stop|restart|status|logs --node <node> --lane <lane>",
|
|
|
|
|
],
|
|
|
|
|
contract: "L1 API/Web 用户入口只输出 owning YAML 解析出的固定 HTTPS 域名;IP、port 和 bind/probe 地址不作为用户入口。",
|
|
|
|
@@ -23,8 +26,6 @@ export function runHwlabNativeDevelopmentCommand(args: string[]): Record<string,
|
|
|
|
|
if (args.length === 0 || args.includes("--help") || args.includes("-h")) return hwlabNativeDevelopmentHelp();
|
|
|
|
|
const [applicationRaw, serviceRaw, actionRaw] = args;
|
|
|
|
|
const application = parseApplication(applicationRaw);
|
|
|
|
|
const service = parseService(serviceRaw, application);
|
|
|
|
|
const action = parseAction(actionRaw);
|
|
|
|
|
const node = requiredOption(args, "--node");
|
|
|
|
|
const lane = requiredOption(args, "--lane");
|
|
|
|
|
if (!isHwlabRuntimeLane(lane)) throw new Error(`--lane must be declared in ${hwlabRuntimeLaneConfigPath()}`);
|
|
|
|
@@ -32,6 +33,27 @@ export function runHwlabNativeDevelopmentCommand(args: string[]): Record<string,
|
|
|
|
|
const native = spec.nativeDevelopment?.[application];
|
|
|
|
|
if (native === undefined) throw new Error(`${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.${application} is required`);
|
|
|
|
|
const env = application === "workbench" ? workbenchEnvironment(spec, native as HwlabRuntimeNativeDevelopmentSpec["workbench"]) : hwlabCaseRunNativeDevelopmentEnvironment(native as NonNullable<HwlabRuntimeNativeDevelopmentSpec["caserun"]>);
|
|
|
|
|
if (application === "workbench" && serviceRaw === "cli") {
|
|
|
|
|
const commandArgs = withoutOptions(args.slice(2), ["--node", "--lane"]);
|
|
|
|
|
if (commandArgs.length === 0) throw new Error("native-development workbench cli requires a Workbench command");
|
|
|
|
|
const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", "workbench", ...commandArgs];
|
|
|
|
|
const result = runCommand(command, spec.workspace, {
|
|
|
|
|
timeoutMs: cliTimeoutMs(commandArgs),
|
|
|
|
|
env: { ...process.env, ...env, WORKBENCH_API_URL: env.WORKBENCH_NATIVE_API_URL },
|
|
|
|
|
});
|
|
|
|
|
return {
|
|
|
|
|
ok: result.exitCode === 0,
|
|
|
|
|
command: "hwlab nodes native-development workbench cli",
|
|
|
|
|
node,
|
|
|
|
|
lane,
|
|
|
|
|
transport: commandArgs.includes("--over-api") ? "native-api" : "local-dispatcher",
|
|
|
|
|
configSource: `${hwlabRuntimeLaneConfigPath()}#lanes.${lane}.targets.${node}.nativeDevelopment.workbench`,
|
|
|
|
|
workbenchResult: parsePayload(result.stdout),
|
|
|
|
|
...(result.exitCode === 0 ? {} : { error: { code: "hwlab_native_cli_failed", exitCode: result.exitCode, stderr: result.stderr.trim().slice(-2000) } }),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const service = parseService(serviceRaw, application);
|
|
|
|
|
const action = parseAction(actionRaw);
|
|
|
|
|
const command = ["bun", "tools/hwlab-cli/bin/hwlab-cli.ts", application, "service", service, action];
|
|
|
|
|
const result = runCommand(command, spec.workspace, { timeoutMs: 15_000, env: { ...process.env, ...env } });
|
|
|
|
|
const payload = parsePayload(result.stdout);
|
|
|
|
@@ -119,6 +141,7 @@ export function hwlabNativeDevelopmentEnvironment(native: HwlabRuntimeNativeDeve
|
|
|
|
|
HWLAB_KAFKA_CLIENT_ID: native.kafka.clientId,
|
|
|
|
|
HWLAB_KAFKA_HWLAB_EVENT_GROUP_ID: native.kafka.hwlabEventConsumerGroupId,
|
|
|
|
|
WORKBENCH_NATIVE_SERVICE_STATE_DIR: native.stateDir,
|
|
|
|
|
WORKBENCH_NATIVE_STATE_FILE: resolve(spec.workspace, native.stateFile),
|
|
|
|
|
WORKBENCH_API_BIND_HOST: native.api.bindHost,
|
|
|
|
|
WORKBENCH_API_PROBE_HOST: native.api.probeHost,
|
|
|
|
|
WORKBENCH_PUBLIC_BASE_URL: native.publicExposure.publicBaseUrl,
|
|
|
|
@@ -170,6 +193,24 @@ function requiredOption(args: string[], option: string): string {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function withoutOptions(args: string[], options: string[]): string[] {
|
|
|
|
|
const result: string[] = [];
|
|
|
|
|
for (let index = 0; index < args.length; index += 1) {
|
|
|
|
|
if (options.includes(args[index])) {
|
|
|
|
|
index += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
result.push(args[index]);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function cliTimeoutMs(args: string[]): number {
|
|
|
|
|
const index = args.indexOf("--timeout-ms");
|
|
|
|
|
const requested = index >= 0 ? Number.parseInt(args[index + 1] ?? "", 10) : 0;
|
|
|
|
|
return Number.isSafeInteger(requested) && requested > 0 ? requested + 5_000 : 30_000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hwlabCaseRunNativeDevelopmentEnvironment(native: NonNullable<HwlabRuntimeNativeDevelopmentSpec["caserun"]>): NodeJS.ProcessEnv {
|
|
|
|
|
return {
|
|
|
|
|
CASERUN_NATIVE_SERVICE_STATE_DIR: native.stateDir,
|
|
|
|
|