123 lines
6.5 KiB
TypeScript
123 lines
6.5 KiB
TypeScript
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. entry module for scripts/src/hwlab-g14.ts.
|
|
|
|
// Moved mechanically from scripts/src/hwlab-g14.ts:10619-12000 for #903.
|
|
|
|
import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { createHash, randomBytes } from "node:crypto";
|
|
import { repoRoot, rootPath, type Config } from "../config";
|
|
import { runCommand } from "../command";
|
|
import { cancelJob, listJobs, readJob, startJob } from "../jobs";
|
|
import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes";
|
|
|
|
import { runRuntimeLaneControlPlane, runV02ControlPlane } from "./control-plane";
|
|
import { runG14GitMirror } from "./git-mirror";
|
|
import { hwlabG14Help, monitorStatus } from "./help";
|
|
import { runG14ToolsImage, runG14UpstreamImage, startControlPlaneTriggerJob, startGitMirrorJob } from "./images";
|
|
import { runMonitorWorker } from "./monitor";
|
|
import { runG14Observability } from "./observability";
|
|
import { hwlabG14MonitorStateFileName, hwlabG14MonitorStateRole, parseControlPlaneOptions, parseGitMirrorOptions, parseLegacyRetirementOptions, parseObservabilityOptions, parseOptions, parseSecretOptions, parseToolsImageOptions, parseUpstreamImageOptions } from "./options";
|
|
import { monitorBaseBranch } from "./remote";
|
|
import { legacyG14RecordRolloutRetired, legacyG14RetirementBlocksMonitor, runLegacyG14Retirement } from "./retirement";
|
|
import { runG14Secret } from "./secrets";
|
|
import { G14_SOURCE_BRANCH, HWLAB_REPO } from "./types";
|
|
|
|
export async function runHwlabG14Command(_config: Config, args: string[]): Promise<Record<string, unknown>> {
|
|
if (args.length === 0 || args.includes("--help") || args.includes("-h")) return { ok: true, ...hwlabG14Help() };
|
|
const [action] = args;
|
|
if (action === "record-rollout") {
|
|
return legacyG14RecordRolloutRetired();
|
|
}
|
|
if (action === "control-plane") {
|
|
const options = parseControlPlaneOptions(args.slice(1));
|
|
if (options.action === "trigger-current" && options.confirm && !options.dryRun && !options.wait) {
|
|
return startControlPlaneTriggerJob(options);
|
|
}
|
|
if (isHwlabRuntimeLane(options.lane) && options.lane !== "v02") {
|
|
return runRuntimeLaneControlPlane(hwlabRuntimeLaneSpec(options.lane), options);
|
|
}
|
|
return runV02ControlPlane(options);
|
|
}
|
|
if (action === "retirement") {
|
|
const options = parseLegacyRetirementOptions(args.slice(1));
|
|
return runLegacyG14Retirement(options);
|
|
}
|
|
if (action === "secret") {
|
|
const options = parseSecretOptions(args.slice(1));
|
|
return runG14Secret(options);
|
|
}
|
|
if (action === "tools-image") {
|
|
const options = parseToolsImageOptions(args.slice(1));
|
|
return runG14ToolsImage(options);
|
|
}
|
|
if (action === "upstream-image") {
|
|
const options = parseUpstreamImageOptions(args.slice(1));
|
|
return runG14UpstreamImage(options);
|
|
}
|
|
if (action === "git-mirror") {
|
|
const options = parseGitMirrorOptions(args.slice(1));
|
|
if ((options.action === "sync" || options.action === "flush") && options.confirm && !options.dryRun && !options.wait) {
|
|
return startGitMirrorJob(options);
|
|
}
|
|
return runG14GitMirror(options);
|
|
}
|
|
if (action === "observability") {
|
|
const options = parseObservabilityOptions(args.slice(1));
|
|
return runG14Observability(options);
|
|
}
|
|
if (action !== "monitor-prs") {
|
|
return { ok: false, command: `hwlab g14 ${action ?? ""}`.trim(), degradedReason: "unsupported-command", message: "supported commands: hwlab g14 monitor-prs, hwlab g14 retirement, hwlab g14 control-plane, hwlab g14 secret, hwlab g14 git-mirror, hwlab g14 observability, hwlab g14 tools-image, hwlab g14 upstream-image" };
|
|
}
|
|
const options = parseOptions(args.slice(1));
|
|
if (options.worker) return runMonitorWorker(options);
|
|
if (args.includes("--status")) return monitorStatus(options);
|
|
const retirement = options.lane === "g14" ? legacyG14RetirementBlocksMonitor() : null;
|
|
if (retirement !== null) {
|
|
return {
|
|
ok: false,
|
|
command: "hwlab g14 monitor-prs",
|
|
lane: options.lane,
|
|
baseBranch: monitorBaseBranch(options.lane),
|
|
degradedReason: "legacy-g14-dev-prod-retired",
|
|
message: "Legacy G14 DEV/PROD has a retirement marker; start a runtime lane monitor with --lane v02/v03 or inspect retirement status.",
|
|
retirement,
|
|
next: {
|
|
retirementStatus: "bun scripts/cli.ts hwlab g14 retirement status",
|
|
v02Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02",
|
|
v03Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v03",
|
|
},
|
|
};
|
|
}
|
|
const command = ["bun", "scripts/cli.ts", "hwlab", "g14", "monitor-prs", "--worker", "--lane", options.lane, "--interval-seconds", String(options.intervalSeconds), "--timeout-seconds", String(options.timeoutSeconds), ...(options.once ? ["--once"] : []), ...(options.dryRun ? ["--dry-run"] : []), ...(options.maxCycles > 0 ? ["--max-cycles", String(options.maxCycles)] : [])];
|
|
const jobName = options.lane === "g14" ? "hwlab_g14_pr_monitor" : `hwlab_g14_${options.lane}_pr_monitor`;
|
|
const jobNote = options.lane === "g14"
|
|
? `Monitor ${HWLAB_REPO} PRs targeting ${G14_SOURCE_BRANCH} and roll merged changes to G14 DEV`
|
|
: `Monitor ${HWLAB_REPO} PRs targeting ${monitorBaseBranch(options.lane)}, merge ready PRs, trigger ${hwlabRuntimeLaneSpec(options.lane).version} CD, comment PR progress, and file failure issues`;
|
|
const job = startJob(jobName, command, jobNote);
|
|
const statusCommand = `bun scripts/cli.ts job status ${job.id} --tail-bytes 30000`;
|
|
const stateDir = rootPath(".state", "hwlab-g14");
|
|
mkdirSync(stateDir, { recursive: true });
|
|
const stateFileName = hwlabG14MonitorStateFileName(options);
|
|
const stateFileRole = hwlabG14MonitorStateRole(options);
|
|
const latestPath = join(stateDir, stateFileName);
|
|
const previousLatest = existsSync(latestPath) ? readFileSync(latestPath, "utf8") : null;
|
|
writeFileSync(latestPath, `${JSON.stringify({ jobId: job.id, createdAt: job.createdAt, statusCommand, role: stateFileRole, lane: options.lane, baseBranch: monitorBaseBranch(options.lane) }, null, 2)}\n`, "utf8");
|
|
return {
|
|
ok: true,
|
|
command: "hwlab g14 monitor-prs",
|
|
lane: options.lane,
|
|
baseBranch: monitorBaseBranch(options.lane),
|
|
mode: "async-job",
|
|
job,
|
|
statusCommand,
|
|
latestPath,
|
|
stateFileName,
|
|
stateFileRole,
|
|
previousLatest,
|
|
next: {
|
|
status: statusCommand,
|
|
tail: `tail -f ${job.stdoutFile}`,
|
|
},
|
|
};
|
|
}
|