fix: bootstrap v03 provider secret
This commit is contained in:
+135
-35
@@ -2568,6 +2568,14 @@ function listV02PipelineRunsCompactFromText(text: string, commandOk: boolean, co
|
||||
return parsePipelineRunRows(text, limit, nowMs);
|
||||
}
|
||||
|
||||
interface CleanupPipelineRunRow {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
ageMinutes: number | null;
|
||||
status: string | null;
|
||||
reason: string | null;
|
||||
}
|
||||
|
||||
function pipelinePrefixesForLane(lane: G14ControlPlaneOptions["lane"]): string[] {
|
||||
if (isHwlabRuntimeLane(lane)) return [`${hwlabRuntimeLaneSpec(lane).pipelineRunPrefix}-`];
|
||||
if (lane === "g14") return ["hwlab-g14-ci-poll-"];
|
||||
@@ -2586,10 +2594,132 @@ function tailText(value: unknown, maxBytes = 2000): string {
|
||||
return text.length <= maxBytes ? text : text.slice(-maxBytes);
|
||||
}
|
||||
|
||||
function cleanupPipelineRunFieldsJsonPath(range: boolean): string {
|
||||
const body = [
|
||||
"{.metadata.name}",
|
||||
"{\"\\t\"}",
|
||||
"{.metadata.creationTimestamp}",
|
||||
"{\"\\t\"}",
|
||||
"{.status.conditions[0].status}",
|
||||
"{\"\\t\"}",
|
||||
"{.status.conditions[0].reason}",
|
||||
"{\"\\n\"}",
|
||||
].join("");
|
||||
return range ? `jsonpath={range .items[*]}${body}{end}` : `jsonpath=${body}`;
|
||||
}
|
||||
|
||||
function parseCleanupPipelineRunLine(line: string, nowMs: number): CleanupPipelineRunRow | null {
|
||||
const [name = "", createdAt = "", status = "", reason = ""] = line.trim().split("\t");
|
||||
if (name.length === 0) return null;
|
||||
const createdMs = Date.parse(createdAt);
|
||||
const ageMinutes = Number.isFinite(createdMs) ? Math.floor((nowMs - createdMs) / 60000) : null;
|
||||
return { name, createdAt, ageMinutes, status: status || null, reason: reason || null };
|
||||
}
|
||||
|
||||
function cleanupPipelineRunTargetCandidate(input: {
|
||||
targetPipelineRun: string;
|
||||
text: string;
|
||||
commandOk: boolean;
|
||||
exitCode: number | null;
|
||||
stderr: string;
|
||||
minAgeMinutes: number;
|
||||
nowMs: number;
|
||||
}): Record<string, unknown> {
|
||||
if (!input.commandOk) {
|
||||
const queryError = tailText(input.stderr);
|
||||
const notFound = /notfound|not found/i.test(queryError);
|
||||
return {
|
||||
name: input.targetPipelineRun,
|
||||
createdAt: null,
|
||||
ageMinutes: null,
|
||||
status: null,
|
||||
reason: notFound ? "target-pipelinerun-not-found" : "target-pipelinerun-query-failed",
|
||||
selected: false,
|
||||
queryExitCode: input.exitCode,
|
||||
...(queryError.length > 0 ? { queryError } : {}),
|
||||
};
|
||||
}
|
||||
const target = parseCleanupPipelineRunLine(input.text, input.nowMs);
|
||||
if (target === null || target.name !== input.targetPipelineRun) {
|
||||
return {
|
||||
name: input.targetPipelineRun,
|
||||
createdAt: null,
|
||||
ageMinutes: null,
|
||||
status: null,
|
||||
reason: "target-pipelinerun-query-empty",
|
||||
selected: false,
|
||||
queryOutputPreview: tailText(input.text),
|
||||
};
|
||||
}
|
||||
if (target.status !== "True" && target.status !== "False") {
|
||||
return {
|
||||
...target,
|
||||
selected: false,
|
||||
selectedReason: "target-pipelinerun-not-terminal",
|
||||
};
|
||||
}
|
||||
const ageMinutes = typeof target.ageMinutes === "number" ? target.ageMinutes : null;
|
||||
const belowMinAge = ageMinutes === null || ageMinutes < input.minAgeMinutes;
|
||||
return {
|
||||
...target,
|
||||
selected: !belowMinAge,
|
||||
...(belowMinAge
|
||||
? { selectedReason: ageMinutes === null ? "missing-creation-timestamp" : "below-min-age" }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function cleanupPipelineRunTargetCandidateFromTextForTest(input: {
|
||||
targetPipelineRun: string;
|
||||
text: string;
|
||||
commandOk?: boolean;
|
||||
exitCode?: number | null;
|
||||
stderr?: string;
|
||||
minAgeMinutes?: number;
|
||||
nowMs?: number;
|
||||
}): Record<string, unknown> {
|
||||
return cleanupPipelineRunTargetCandidate({
|
||||
targetPipelineRun: input.targetPipelineRun,
|
||||
text: input.text,
|
||||
commandOk: input.commandOk ?? true,
|
||||
exitCode: input.exitCode ?? 0,
|
||||
stderr: input.stderr ?? "",
|
||||
minAgeMinutes: input.minAgeMinutes ?? 60,
|
||||
nowMs: input.nowMs ?? Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
function listCleanupPipelineRuns(options: G14ControlPlaneOptions): Record<string, unknown>[] {
|
||||
if (options.lane !== "g14" && options.lane !== "all" && !isHwlabRuntimeLane(options.lane)) {
|
||||
throw new Error("control-plane cleanup-runs requires --lane v02|v03|g14|all");
|
||||
}
|
||||
const targetPipelineRun = options.pipelineRun ?? (options.sourceCommit === undefined
|
||||
? undefined
|
||||
: isHwlabRuntimeLane(options.lane)
|
||||
? runtimeLanePipelineRunName(hwlabRuntimeLaneSpec(options.lane), options.sourceCommit)
|
||||
: v02PipelineRunName(options.sourceCommit));
|
||||
const now = Date.now();
|
||||
if (targetPipelineRun !== undefined) {
|
||||
const targetResult = g14K3s([
|
||||
"kubectl",
|
||||
"get",
|
||||
"pipelinerun",
|
||||
"-n",
|
||||
CI_NAMESPACE,
|
||||
targetPipelineRun,
|
||||
"-o",
|
||||
cleanupPipelineRunFieldsJsonPath(false),
|
||||
], 60_000);
|
||||
return [cleanupPipelineRunTargetCandidate({
|
||||
targetPipelineRun,
|
||||
text: statusText(targetResult),
|
||||
commandOk: isCommandSuccess(targetResult),
|
||||
exitCode: targetResult.exitCode,
|
||||
stderr: commandErrorSummary(targetResult),
|
||||
minAgeMinutes: options.minAgeMinutes,
|
||||
nowMs: now,
|
||||
})];
|
||||
}
|
||||
const result = g14K3s([
|
||||
"kubectl",
|
||||
"get",
|
||||
@@ -2597,28 +2727,18 @@ function listCleanupPipelineRuns(options: G14ControlPlaneOptions): Record<string
|
||||
"-n",
|
||||
CI_NAMESPACE,
|
||||
"-o",
|
||||
'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.metadata.creationTimestamp}{"\\t"}{.status.conditions[0].status}{"\\t"}{.status.conditions[0].reason}{"\\n"}{end}',
|
||||
cleanupPipelineRunFieldsJsonPath(true),
|
||||
], 60_000);
|
||||
if (!isCommandSuccess(result)) {
|
||||
throw new Error(`failed to list hwlab-ci PipelineRuns: ${commandErrorSummary(result)}`);
|
||||
}
|
||||
const targetPipelineRun = options.pipelineRun ?? (options.sourceCommit === undefined
|
||||
? undefined
|
||||
: isHwlabRuntimeLane(options.lane)
|
||||
? runtimeLanePipelineRunName(hwlabRuntimeLaneSpec(options.lane), options.sourceCommit)
|
||||
: v02PipelineRunName(options.sourceCommit));
|
||||
const prefixes = pipelinePrefixesForLane(options.lane);
|
||||
const now = Date.now();
|
||||
const terminalRuns = statusText(result)
|
||||
.split(/\r?\n/u)
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
const [name = "", createdAt = "", status = "", reason = ""] = line.split("\t");
|
||||
const createdMs = Date.parse(createdAt);
|
||||
const ageMinutes = Number.isFinite(createdMs) ? Math.floor((now - createdMs) / 60000) : null;
|
||||
return { name, createdAt, ageMinutes, status: status || null, reason: reason || null };
|
||||
})
|
||||
.map((line) => parseCleanupPipelineRunLine(line, now))
|
||||
.filter((item): item is CleanupPipelineRunRow => item !== null)
|
||||
.filter((item) => item.name.length > 0 && prefixes.some((prefix) => item.name.startsWith(prefix)))
|
||||
.filter((item) => item.status === "True" || item.status === "False")
|
||||
.sort((a, b) => String(a.createdAt).localeCompare(String(b.createdAt)));
|
||||
@@ -2629,28 +2749,6 @@ function listCleanupPipelineRuns(options: G14ControlPlaneOptions): Record<string
|
||||
.sort((a, b) => String(b.createdAt).localeCompare(String(a.createdAt)))[0];
|
||||
if (latest !== undefined) protectedLatestByPrefix.set(prefix, latest.name);
|
||||
}
|
||||
if (targetPipelineRun !== undefined) {
|
||||
const target = terminalRuns.find((item) => item.name === targetPipelineRun);
|
||||
if (target === undefined) {
|
||||
return [{
|
||||
name: targetPipelineRun,
|
||||
createdAt: null,
|
||||
ageMinutes: null,
|
||||
status: null,
|
||||
reason: "target-pipelinerun-not-found-or-not-terminal",
|
||||
selected: false,
|
||||
}];
|
||||
}
|
||||
const ageMinutes = typeof target.ageMinutes === "number" ? target.ageMinutes : null;
|
||||
const belowMinAge = ageMinutes === null || ageMinutes < options.minAgeMinutes;
|
||||
return [{
|
||||
...target,
|
||||
selected: !belowMinAge,
|
||||
...(belowMinAge
|
||||
? { selectedReason: ageMinutes === null ? "missing-creation-timestamp" : "below-min-age" }
|
||||
: {}),
|
||||
}];
|
||||
}
|
||||
const candidates = terminalRuns
|
||||
.filter((item) => typeof item.ageMinutes === "number" && item.ageMinutes >= options.minAgeMinutes)
|
||||
.map((item) => {
|
||||
@@ -8808,6 +8906,8 @@ export function hwlabG14Help(): Record<string, unknown> {
|
||||
"bun scripts/cli.ts hwlab g14 secret ensure --lane v02 --name hwlab-v02-master-server-admin-api-key --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-v03-master-server-admin-api-key",
|
||||
"bun scripts/cli.ts hwlab nodes secret ensure --node G14 --lane v03 --name hwlab-v03-master-server-admin-api-key --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-v03-code-agent-provider",
|
||||
"bun scripts/cli.ts hwlab nodes secret ensure --node G14 --lane v03 --name hwlab-v03-code-agent-provider --confirm",
|
||||
"bun scripts/cli.ts hwlab g14 secret delete --lane v02 --name <obsolete-hwlab-v02-secret> --dry-run",
|
||||
"bun scripts/cli.ts hwlab g14 secret delete --lane v02 --name <obsolete-hwlab-v02-secret> --confirm",
|
||||
"bun scripts/cli.ts hwlab g14 git-mirror status",
|
||||
|
||||
Reference in New Issue
Block a user