Files
pikasTech-unidesk/scripts/src/hwlab-g14/source.ts
T
2026-06-25 16:16:25 +00:00

122 lines
6.1 KiB
TypeScript

// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. source module for scripts/src/hwlab-g14.ts.
// Moved mechanically from scripts/src/hwlab-g14.ts:1205-1308 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 type { CommandJsonResult } from "./types";
import { g14HostScript } from "./images";
import { statusText } from "./pr-monitor";
import { commandJson, isCommandSuccess, nested, shellQuote, shortSha } from "./remote";
import { V02_GIT_URL, V02_LANE_SPEC } from "./types";
export function runtimeLaneCicdRepoEnsureScript(spec: HwlabRuntimeLaneSpec): string {
return [
`cicd_repo=${shellQuote(spec.cicdRepo)}`,
`cicd_url=${shellQuote(spec.gitUrl)}`,
`cicd_branch=${shellQuote(spec.sourceBranch)}`,
`cicd_repo_lock=${shellQuote(spec.cicdRepoLock)}`,
"cicd_repo_ensure_fetch() {",
" mkdir -p \"$(dirname \"$cicd_repo\")\" || return $?",
" if [ -d \"$cicd_repo/objects\" ] && [ -f \"$cicd_repo/HEAD\" ]; then",
" :",
" elif [ -e \"$cicd_repo\" ]; then",
` echo "${spec.version} CI/CD repo path exists but is not a bare git repo: $cicd_repo" >&2`,
" return 41",
" else",
" git clone --bare \"$cicd_url\" \"$cicd_repo\" || return $?",
" fi",
" git --git-dir=\"$cicd_repo\" remote set-url origin \"$cicd_url\" 2>/dev/null || git --git-dir=\"$cicd_repo\" remote add origin \"$cicd_url\" || return $?",
" git --git-dir=\"$cicd_repo\" config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*' || return $?",
" git --git-dir=\"$cicd_repo\" fetch origin \"+refs/heads/$cicd_branch:refs/remotes/origin/$cicd_branch\" --prune || return $?",
"}",
"cicd_repo_lock_mode=none",
"if command -v flock >/dev/null 2>&1; then",
" exec 9>\"$cicd_repo_lock\"",
` flock -w 120 9 || { echo "timed out waiting for ${spec.version} CI/CD repo lock: $cicd_repo_lock" >&2; exit 42; }`,
" cicd_repo_lock_mode=flock",
"else",
" cicd_repo_lock_dir=\"$cicd_repo_lock.d\"",
" cicd_repo_lock_attempt=0",
" while ! mkdir \"$cicd_repo_lock_dir\" 2>/dev/null; do",
" cicd_repo_lock_attempt=$((cicd_repo_lock_attempt + 1))",
` if [ "$cicd_repo_lock_attempt" -ge 120 ]; then echo "timed out waiting for ${spec.version} CI/CD repo lock: $cicd_repo_lock_dir" >&2; exit 42; fi`,
" sleep 1",
" done",
" cicd_repo_lock_mode=dir",
"fi",
"cicd_repo_status=0",
"cicd_repo_ensure_fetch || cicd_repo_status=$?",
"if [ \"$cicd_repo_lock_mode\" = flock ]; then flock -u 9 >/dev/null 2>&1 || true; fi",
"if [ \"$cicd_repo_lock_mode\" = dir ]; then rmdir \"$cicd_repo_lock_dir\" >/dev/null 2>&1 || true; fi",
`if [ "$cicd_repo_status" -ne 0 ]; then echo "${spec.version} CI/CD repo refresh failed status=$cicd_repo_status repo=$cicd_repo" >&2; exit "$cicd_repo_status"; fi`,
].join("\n");
}
export function v02CicdRepoEnsureScript(): string {
return runtimeLaneCicdRepoEnsureScript(V02_LANE_SPEC);
}
export function resolveV02Head(): { sourceCommit: string | null; result: CommandJsonResult } {
const result = g14HostScript([
"set -eu",
v02CicdRepoEnsureScript(),
"git --git-dir=\"$cicd_repo\" rev-parse refs/remotes/origin/v0.2",
].join("\n"), 180_000);
if (!isCommandSuccess(result)) return { sourceCommit: null, result };
const output = String(nested(result.parsed, ["data", "stdout"]) ?? result.stdout).trim();
const match = /[0-9a-f]{40}/iu.exec(output);
return { sourceCommit: match?.[0] ?? null, result };
}
export function getV02Head(): string | null {
return resolveV02Head().sourceCommit;
}
export function resolveV02LatestRemoteHead(): { sourceCommit: string | null; result: CommandJsonResult } {
const result = commandJson(["git", "ls-remote", V02_GIT_URL, "refs/heads/v0.2"], 30_000);
if (!isCommandSuccess(result)) return { sourceCommit: null, result };
const output = statusText(result);
const match = /^[0-9a-f]{40}/imu.exec(output);
return { sourceCommit: match?.[0] ?? null, result };
}
export function resolveRuntimeLaneHead(spec: HwlabRuntimeLaneSpec): { sourceCommit: string | null; result: CommandJsonResult } {
const result = g14HostScript([
"set -eu",
runtimeLaneCicdRepoEnsureScript(spec),
`git --git-dir="$cicd_repo" rev-parse refs/remotes/origin/${spec.sourceBranch}`,
].join("\n"), 180_000);
if (!isCommandSuccess(result)) return { sourceCommit: null, result };
const output = String(nested(result.parsed, ["data", "stdout"]) ?? result.stdout).trim();
const match = /[0-9a-f]{40}/iu.exec(output);
return { sourceCommit: match?.[0] ?? null, result };
}
export function resolveRuntimeLaneLatestRemoteHead(spec: HwlabRuntimeLaneSpec): { sourceCommit: string | null; result: CommandJsonResult } {
const result = commandJson(["git", "ls-remote", spec.gitUrl, `refs/heads/${spec.sourceBranch}`], 30_000);
if (!isCommandSuccess(result)) return { sourceCommit: null, result };
const output = statusText(result);
const match = /^[0-9a-f]{40}/imu.exec(output);
return { sourceCommit: match?.[0] ?? null, result };
}
export function runtimeLanePipelineRunName(spec: HwlabRuntimeLaneSpec, sourceCommit: string): string {
return `${spec.pipelineRunPrefix}-${shortSha(sourceCommit)}`;
}
export function runtimeLaneRerunPipelineRunName(spec: HwlabRuntimeLaneSpec, sourceCommit: string, now = new Date()): string {
const stamp = now.toISOString().replace(/\D/gu, "").slice(0, 14);
return `${runtimeLanePipelineRunName(spec, sourceCommit)}-r${stamp}`;
}
export function v02PipelineRunName(sourceCommit: string): string {
return runtimeLanePipelineRunName(V02_LANE_SPEC, sourceCommit);
}