feat: add HWLAB runtime lane control CLI
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { activeV02PipelineRuns, g14ObservabilityQueryAssertion, gitMirrorFlushJobManifest, gitMirrorStatusSummary, gitMirrorSyncJobManifest, gitMirrorV02SyncRequirement, hwlabG14Help, hwlabG14MonitorStateFileName, parseGitMirrorStatusRefs, parseK8sCpuMillicores, parseK8sMemoryMiB, parsePipelineTaskRunMetrics, parseV02TriggerSnapshot, rolloutRecordBody, semanticChangelogBullets, summarizeV02CdStatus, v02CloseoutVerdict, v02CommitAlignment, v02ControlPlaneRefreshScriptHash, v02ControlPlaneRenderScript, v02ExistingPipelineRunReuseDecision, v02FalseGreenGuard, v02GitMirrorPreSyncWaitMs, v02LatestOnlyTargetValidation, v02PipelineServiceIds, v02PrAutomationCommentBody, v02ReusableGitMirrorPreSyncMarker, v02ReusableRefreshMarker, v02StatusHistoryPolicy, v02TaskRunPerformanceSummary } from "./src/hwlab-g14";
|
||||
import { hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec } from "./src/hwlab-g14-lanes";
|
||||
import { runCommand } from "./src/command";
|
||||
|
||||
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
||||
@@ -44,6 +45,29 @@ assertCondition(
|
||||
"v0.2 control-plane help must expose targeted PipelineRun/source-commit status, closeout inspection, and cleanup",
|
||||
hwlabHelpUsage,
|
||||
);
|
||||
assertCondition(
|
||||
hwlabHelpUsage.some((line) => line.includes("control-plane status --lane v03"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("control-plane apply --lane v03 --dry-run"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("control-plane trigger-current --lane v03 --dry-run"))
|
||||
&& JSON.stringify(hwlabG14Help()).includes("runtime lane v02/v03"),
|
||||
"v0.3 control-plane help must expose the runtime lane bootstrap status/apply/trigger entrypoints",
|
||||
hwlabHelpUsage,
|
||||
);
|
||||
const v03LaneSpec = hwlabRuntimeLaneSpec("v03");
|
||||
assertCondition(
|
||||
JSON.stringify(hwlabRuntimeLaneIds()) === JSON.stringify(["v02", "v03"])
|
||||
&& v03LaneSpec.sourceBranch === "v0.3"
|
||||
&& v03LaneSpec.gitopsBranch === "v0.3-gitops"
|
||||
&& v03LaneSpec.workspace === "/root/hwlab-v03"
|
||||
&& v03LaneSpec.cicdRepo === "/root/hwlab-v03-cicd.git"
|
||||
&& v03LaneSpec.runtimeNamespace === "hwlab-v03"
|
||||
&& v03LaneSpec.runtimeRenderDir === "runtime-v03"
|
||||
&& v03LaneSpec.pipeline === "hwlab-v03-ci-image-publish"
|
||||
&& v03LaneSpec.publicWebUrl.endsWith(":19766")
|
||||
&& v03LaneSpec.publicApiUrl.endsWith(":19767"),
|
||||
"runtime lane spec must make v0.3 expansion a config-driven lane instead of scattered literals",
|
||||
v03LaneSpec,
|
||||
);
|
||||
assertCondition(
|
||||
hwlabHelpUsage.some((line) => line.includes("monitor-prs --lane v02"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("monitor-prs --lane v02 --status"))
|
||||
@@ -52,6 +76,12 @@ assertCondition(
|
||||
"v0.2 PR monitor help must expose the auto CI/CD lane, status query, latest-only CD, and dedupe comment state",
|
||||
hwlabG14Help(),
|
||||
);
|
||||
assertCondition(
|
||||
hwlabHelpUsage.some((line) => line.includes("git-mirror apply --lane v02 --confirm"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("git-mirror apply --lane v03 --confirm")),
|
||||
"git mirror help must expose lane-selected apply so v0.3 mirror config is not rendered through v0.2",
|
||||
hwlabHelpUsage,
|
||||
);
|
||||
assertCondition(
|
||||
hwlabHelpUsage.some((line) => line.includes("secret status --lane v02 --name hwlab-v02-openfga"))
|
||||
&& hwlabHelpUsage.some((line) => line.includes("secret ensure --lane v02 --name hwlab-v02-openfga --confirm"))
|
||||
@@ -268,8 +298,10 @@ assertCondition(
|
||||
&& renderScript.includes("git -C \"$worktree_dir\" checkout --detach \"$source_commit\"")
|
||||
&& renderScript.includes("npm ci --ignore-scripts --no-audit --prefer-offline")
|
||||
&& renderScript.includes("bun install --frozen-lockfile --ignore-scripts")
|
||||
&& renderScript.includes("scripts/run-bun.mjs")
|
||||
&& renderScript.includes("--lane \"$render_lane\"")
|
||||
&& renderScript.includes("/tmp/hwlab-v02-control-plane-source-aaaaaaaaaaaa-"),
|
||||
"v0.2 control-plane render must use an isolated temp clone with lockfile-based dependencies so same-commit concurrent triggers do not share worktree metadata",
|
||||
"v0.2 control-plane render must use an isolated temp clone with lockfile-based dependencies and the modular Bun renderer fallback",
|
||||
renderScript,
|
||||
);
|
||||
assertCondition(
|
||||
@@ -308,10 +340,11 @@ assertCondition(
|
||||
);
|
||||
assertCondition(
|
||||
sourceText.includes("function runG14K3sRemoteAsync")
|
||||
&& sourceText.includes("label: \"v02-control-plane-apply\"")
|
||||
&& sourceText.includes("function applyRuntimeLaneControlPlaneFiles")
|
||||
&& sourceText.includes("label: `${spec.lane}-control-plane-apply`")
|
||||
&& sourceText.includes("remote async command timed out after")
|
||||
&& sourceText.includes("return runG14K3sRemoteAsync({"),
|
||||
"v0.2 control-plane apply must use short start/poll remote-async semantics instead of one long G14:k3s apply call",
|
||||
"runtime lane control-plane apply must use short start/poll remote-async semantics instead of one long G14:k3s apply call",
|
||||
);
|
||||
const existingPipelineRunReuse = v02ExistingPipelineRunReuseDecision({
|
||||
sourceCommit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
export type HwlabRuntimeLane = "v02" | "v03";
|
||||
|
||||
export interface HwlabRuntimeLaneConfig {
|
||||
readonly lane: HwlabRuntimeLane;
|
||||
readonly minor: number;
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeLaneSpec {
|
||||
readonly lane: HwlabRuntimeLane;
|
||||
readonly minor: number;
|
||||
readonly version: string;
|
||||
readonly sourceBranch: string;
|
||||
readonly workspace: string;
|
||||
readonly cicdRepo: string;
|
||||
readonly cicdRepoLock: string;
|
||||
readonly app: string;
|
||||
readonly pipeline: string;
|
||||
readonly pipelineRunPrefix: string;
|
||||
readonly serviceAccountName: string;
|
||||
readonly controlPlaneFieldManager: string;
|
||||
readonly gitUrl: string;
|
||||
readonly gitReadUrl: string;
|
||||
readonly gitWriteUrl: string;
|
||||
readonly gitopsBranch: string;
|
||||
readonly catalogPath: string;
|
||||
readonly runtimePath: string;
|
||||
readonly runtimeNamespace: string;
|
||||
readonly runtimeRenderDir: string;
|
||||
readonly tektonDir: string;
|
||||
readonly argoApplicationFile: string;
|
||||
readonly registryPrefix: string;
|
||||
readonly baseImage: string;
|
||||
readonly serviceIds: readonly string[];
|
||||
readonly publicWebUrl: string;
|
||||
readonly publicApiUrl: string;
|
||||
}
|
||||
|
||||
export const HWLAB_RUNTIME_LANE_CONFIGS = [
|
||||
{ lane: "v02", minor: 2 },
|
||||
{ lane: "v03", minor: 3 },
|
||||
] as const satisfies readonly HwlabRuntimeLaneConfig[];
|
||||
|
||||
const HWLAB_GIT_URL = "git@github.com:pikasTech/HWLAB.git";
|
||||
const HWLAB_GIT_READ_URL = "http://git-mirror-http.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
const HWLAB_GIT_WRITE_URL = "http://git-mirror-write.devops-infra.svc.cluster.local/pikasTech/HWLAB.git";
|
||||
const HWLAB_REGISTRY_PREFIX = "127.0.0.1:5000/hwlab";
|
||||
const HWLAB_BASE_IMAGE = "127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim";
|
||||
const HWLAB_SERVICE_IDS = [
|
||||
"hwlab-cloud-api",
|
||||
"hwlab-cloud-web",
|
||||
"hwlab-gateway",
|
||||
"hwlab-edge-proxy",
|
||||
"hwlab-agent-skills",
|
||||
] as const;
|
||||
|
||||
function buildRuntimeLaneSpec(config: HwlabRuntimeLaneConfig): HwlabRuntimeLaneSpec {
|
||||
const version = `v0.${config.minor}`;
|
||||
const lane = config.lane;
|
||||
return {
|
||||
lane,
|
||||
minor: config.minor,
|
||||
version,
|
||||
sourceBranch: version,
|
||||
workspace: `/root/hwlab-${lane}`,
|
||||
cicdRepo: `/root/hwlab-${lane}-cicd.git`,
|
||||
cicdRepoLock: `/tmp/hwlab-${lane}-cicd-repo.lock`,
|
||||
app: `hwlab-g14-${lane}`,
|
||||
pipeline: `hwlab-${lane}-ci-image-publish`,
|
||||
pipelineRunPrefix: `hwlab-${lane}-ci-poll`,
|
||||
serviceAccountName: `hwlab-${lane}-tekton-runner`,
|
||||
controlPlaneFieldManager: `unidesk-hwlab-${lane}-control-plane`,
|
||||
gitUrl: HWLAB_GIT_URL,
|
||||
gitReadUrl: HWLAB_GIT_READ_URL,
|
||||
gitWriteUrl: HWLAB_GIT_WRITE_URL,
|
||||
gitopsBranch: `${version}-gitops`,
|
||||
catalogPath: `deploy/artifact-catalog.${lane}.json`,
|
||||
runtimePath: `deploy/gitops/g14/runtime-${lane}`,
|
||||
runtimeNamespace: `hwlab-${lane}`,
|
||||
runtimeRenderDir: `runtime-${lane}`,
|
||||
tektonDir: `tekton-${lane}`,
|
||||
argoApplicationFile: `application-${lane}.yaml`,
|
||||
registryPrefix: HWLAB_REGISTRY_PREFIX,
|
||||
baseImage: HWLAB_BASE_IMAGE,
|
||||
serviceIds: HWLAB_SERVICE_IDS,
|
||||
publicWebUrl: `http://74.48.78.17:${19466 + config.minor * 100}`,
|
||||
publicApiUrl: `http://74.48.78.17:${19467 + config.minor * 100}`,
|
||||
};
|
||||
}
|
||||
|
||||
const RUNTIME_LANE_SPECS = Object.fromEntries(
|
||||
HWLAB_RUNTIME_LANE_CONFIGS.map((config) => [config.lane, buildRuntimeLaneSpec(config)]),
|
||||
) as Record<HwlabRuntimeLane, HwlabRuntimeLaneSpec>;
|
||||
|
||||
export function isHwlabRuntimeLane(value: string): value is HwlabRuntimeLane {
|
||||
return Object.prototype.hasOwnProperty.call(RUNTIME_LANE_SPECS, value);
|
||||
}
|
||||
|
||||
export function hwlabRuntimeLaneSpec(lane: HwlabRuntimeLane): HwlabRuntimeLaneSpec {
|
||||
return RUNTIME_LANE_SPECS[lane];
|
||||
}
|
||||
|
||||
export function hwlabRuntimeLaneIds(): HwlabRuntimeLane[] {
|
||||
return HWLAB_RUNTIME_LANE_CONFIGS.map((config) => config.lane);
|
||||
}
|
||||
+605
-115
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user