deploy: configure NC01 HWLAB monitor exposure

This commit is contained in:
root
2026-07-08 05:34:11 +02:00
parent 5dfb78f000
commit a328aa909e
41 changed files with 2522 additions and 110 deletions
+10 -1
View File
@@ -45,6 +45,7 @@ export function parseSecretSyncOptions(args: string[]): SecretSyncOptions {
const base = parseConfirmOptions(args);
let node: string | null = null;
let lane: string | null = null;
const secretIds: string[] = [];
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === "--confirm" || arg === "--dry-run") continue;
@@ -62,9 +63,17 @@ export function parseSecretSyncOptions(args: string[]): SecretSyncOptions {
index += 1;
continue;
}
if (arg === "--secret-id") {
const value = args[index + 1];
if (value === undefined || value.startsWith("--")) throw new Error("--secret-id requires a value");
if (!/^[A-Za-z0-9._-]+$/u.test(value)) throw new Error("--secret-id must be a simple YAML secret id");
if (!secretIds.includes(value)) secretIds.push(value);
index += 1;
continue;
}
throw new Error(`unsupported secret-sync option: ${arg}`);
}
return { ...base, node, lane };
return { ...base, node, lane, secretIds };
}
export function parseLaneConfirmOptions(args: string[]): LaneConfirmOptions {
+1
View File
@@ -71,6 +71,7 @@ export function agentRunHelp(): unknown {
"bun scripts/cli.ts agentrun control-plane status --node D601 --lane v02",
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --dry-run",
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --confirm",
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --secret-id tool-github-pr-token --confirm",
"bun scripts/cli.ts agentrun control-plane restart --node D601 --lane v02 --dry-run",
"bun scripts/cli.ts agentrun control-plane restart --node D601 --lane v02 --confirm",
"bun scripts/cli.ts agentrun control-plane trigger-current --node D601 --lane v02 --dry-run",
+1
View File
@@ -219,6 +219,7 @@ export interface ConfirmOptions {
export interface SecretSyncOptions extends ConfirmOptions {
node: string | null;
lane: string | null;
secretIds: string[];
}
export interface LaneConfirmOptions extends ConfirmOptions {
+10 -4
View File
@@ -350,6 +350,7 @@ export function yamlLanePipelineRunManifest(spec: AgentRunLaneSpec, sourceCommit
{ name: "source-branch", value: spec.source.branch },
{ name: "gitops-branch", value: spec.gitops.branch },
{ name: "revision", value: sourceCommit },
...(sourceStageRef === null ? [] : [{ name: "source-stage-ref", value: sourceStageRef }]),
{ name: "registry-prefix", value: spec.ci.registryPrefix },
{ name: "tools-image", value: spec.ci.toolsImage },
],
@@ -476,6 +477,7 @@ export function yamlLaneGitMirrorSshSetupShellLines(spec: AgentRunLaneSpec): str
const proxyHost = spec.gitMirror.githubProxy.host;
const proxyPort = spec.gitMirror.githubProxy.port;
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
const noProxy = "localhost,127.0.0.1,::1,.svc,.svc.cluster.local,.cluster.local,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,hyueapi.com,.hyueapi.com";
const proxySummary = `agentrun git-mirror-egress-proxy node=${spec.nodeId} lane=${spec.lane} host=${proxyHost} port=${proxyPort} ssh=GIT_SSH-wrapper source=yaml`;
const proxyCommand = `ProxyCommand=node /tmp/agentrun-github-proxy-connect.cjs ${proxyHost} ${proxyPort} %h %p`;
return [
@@ -545,6 +547,8 @@ export function yamlLaneGitMirrorSshSetupShellLines(spec: AgentRunLaneSpec): str
`export http_proxy=${shQuote(proxyUrl)}`,
`export https_proxy=${shQuote(proxyUrl)}`,
`export all_proxy=${shQuote(proxyUrl)}`,
`export NO_PROXY=${shQuote(noProxy)}`,
`export no_proxy=${shQuote(noProxy)}`,
"export GIT_SSH=/tmp/agentrun-git-ssh-proxy.sh",
"unset GIT_SSH_COMMAND",
];
@@ -558,8 +562,8 @@ export function yamlLaneGitMirrorSyncShell(spec: AgentRunLaneSpec): string {
`source_branch=${shQuote(spec.source.branch)}`,
`source_stage_ref_prefix=${shQuote(agentRunSourceSnapshotStageRefPrefix(spec))}`,
`gitops_branch=${shQuote(spec.gitops.branch)}`,
`remote=${shQuote(spec.source.remote)}`,
"repo=\"/cache/${repository}.git\"",
"remote=\"ssh://git@ssh.github.com:443/${repository}.git\"",
"mkdir -p \"$(dirname \"$repo\")\"",
"if [ -d \"$repo/objects\" ] && [ -f \"$repo/HEAD\" ]; then",
" git --git-dir=\"$repo\" remote set-url origin \"$remote\" || git --git-dir=\"$repo\" remote add origin \"$remote\"",
@@ -606,8 +610,8 @@ export function yamlLaneGitMirrorFlushShell(spec: AgentRunLaneSpec): string {
...yamlLaneGitMirrorSshSetupShellLines(spec),
`repository=${shQuote(spec.source.repository)}`,
`gitops_branch=${shQuote(spec.gitops.branch)}`,
`remote=${shQuote(spec.gitMirror.writeUrl)}`,
"repo=\"/cache/${repository}.git\"",
"remote=\"ssh://git@ssh.github.com:443/${repository}.git\"",
"test -d \"$repo\"",
"git --git-dir=\"$repo\" remote set-url origin \"$remote\" || git --git-dir=\"$repo\" remote add origin \"$remote\"",
"local_gitops=$(git --git-dir=\"$repo\" rev-parse --verify \"refs/heads/${gitops_branch}^{commit}\" 2>/dev/null || true)",
@@ -703,6 +707,7 @@ export type LaneSecretSource = {
sourceRef: string;
sourceMode: "env" | "file";
sourceKey: string | null;
sourceFormat?: "env" | "raw-token" | null;
targetRef: { namespace: string; name: string; key: string };
transform?: "local-postgres-database" | "local-postgres-user" | "local-postgres-database-url";
};
@@ -719,8 +724,8 @@ export function readSecretSourceValue(spec: AgentRunLaneSpec, source: LaneSecret
value = readFileSync(sourcePath, "utf8");
} else {
if (source.sourceKey === null) throw new Error(`secret source ${sourceRef} is missing sourceKey`);
const values = parseEnvFile(readFileSync(sourcePath, "utf8"));
const envValue = values.get(source.sourceKey);
const text = readFileSync(sourcePath, "utf8");
const envValue = source.sourceFormat === "raw-token" ? text.trim() : parseEnvFile(text).get(source.sourceKey);
if (envValue === undefined || envValue.length === 0) throw new Error(`secret source ${sourceRef} is missing required key ${source.sourceKey}`);
value = envValue;
}
@@ -837,6 +842,7 @@ export function collectLaneSecretSources(spec: AgentRunLaneSpec): LaneSecretSour
sourceRef: secret.sourceRef,
sourceMode: secret.sourceMode,
sourceKey: secret.sourceKey,
sourceFormat: secret.sourceFormat,
targetRef: secret.targetRef,
});
}
+11 -5
View File
@@ -178,15 +178,19 @@ export async function restartYamlLane(config: UniDeskConfig, options: LaneConfir
export async function secretSync(config: UniDeskConfig, options: SecretSyncOptions): Promise<Record<string, unknown>> {
const { configPath, spec } = resolveAgentRunLaneTarget(options);
const sources = collectLaneSecretSources(spec);
const allSources = collectLaneSecretSources(spec);
const selectedIds = new Set(options.secretIds);
const sources = selectedIds.size === 0 ? allSources : allSources.filter((source) => selectedIds.has(source.id));
if (sources.length === 0) {
return {
ok: false,
command: "agentrun control-plane secret-sync",
mode: "yaml-declared-node-lane",
configPath,
target: agentRunLaneSummary(spec),
target: compactAgentRunLaneStatusTarget(spec),
degradedReason: "lane-secret-sources-not-declared",
requestedSecretIds: options.secretIds,
declaredSecretIds: allSources.map((source) => source.id),
valuesPrinted: false,
};
}
@@ -211,10 +215,11 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
mode: "dry-run",
mutation: false,
configPath,
target: agentRunLaneSummary(spec),
target: compactAgentRunLaneStatusTarget(spec),
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
next: {
confirm: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane} --confirm`,
confirm: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --confirm`,
status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`,
},
valuesPrinted: false,
@@ -228,7 +233,8 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
mode: "confirmed-sync",
mutation: true,
configPath,
target: agentRunLaneSummary(spec),
target: compactAgentRunLaneStatusTarget(spec),
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
result: payload,
capture: compactCapture(result, { full: result.exitCode !== 0, stdoutTailChars: 3000, stderrTailChars: 3000 }),
+2 -15
View File
@@ -128,22 +128,9 @@ export type AgentRunBridgeCaptureResult = SshCaptureResult & { bridgeExecution?:
export let localBackendCoreStatusCache: LocalBackendCoreStatus | null = null;
export async function capture(config: UniDeskConfig, target: string, args: string[]): Promise<AgentRunBridgeCaptureResult> {
const result = await runSshCommandCapture(config, target, args);
const plan = agentRunBridgeCapturePlan(config, target);
if (plan.backend === "remote-frontend-websocket" && plan.remoteHost !== null) {
return await captureRemote(config, plan, target, args);
}
const local = attachBridgeExecution(await runSshCommandCapture(config, target, args), plan);
const fallbackHost = agentRunBridgeRemoteHost(config);
if (local.exitCode !== 0 && fallbackHost !== null && bridgeExecutionFailureKind(local)?.degradedReason === "capture-backend-unavailable") {
const fallbackPlan: AgentRunBridgeCapturePlan = {
...plan,
backend: "remote-frontend-websocket",
remoteHost: fallbackHost,
reason: "local-capture-backend-unavailable",
};
return await captureRemote(config, fallbackPlan, target, args);
}
return local;
return attachBridgeExecution(result, { ...plan, reason: `unified-ssh-capture:${plan.reason}` });
}
export async function captureRemote(config: UniDeskConfig, plan: AgentRunBridgeCapturePlan, target: string, args: string[]): Promise<AgentRunBridgeCaptureResult> {
+5 -2
View File
@@ -1242,15 +1242,18 @@ function yamlLaneK3sBuildProxyEnv(spec: AgentRunLaneSpec): Array<{ name: string;
}
function yamlLaneK3sBuildSourceShell(spec: AgentRunLaneSpec, sourceCommit: string): string {
const useDirectSourceRemote = spec.source.remote.startsWith("http://gitea-http.") || spec.source.remote.startsWith("https://gitea.");
const readUrl = useDirectSourceRemote ? spec.source.remote : spec.gitMirror.readUrl;
return [
"set -eu",
`read_url=${shQuote(spec.gitMirror.readUrl)}`,
`read_url=${shQuote(readUrl)}`,
`source_commit=${shQuote(sourceCommit)}`,
`source_stage_ref=${shQuote(agentRunSourceSnapshotRef(spec, sourceCommit))}`,
`use_direct_source_remote=${useDirectSourceRemote ? "true" : "false"}`,
"rm -rf /workspace/repo",
"git clone --no-checkout \"$read_url\" /workspace/repo",
"cd /workspace/repo",
"git fetch origin \"+$source_stage_ref:refs/remotes/origin/unidesk-source-snapshot\"",
"if [ \"$use_direct_source_remote\" != true ]; then git fetch origin \"+$source_stage_ref:refs/remotes/origin/unidesk-source-snapshot\"; fi",
"git checkout --detach \"$source_commit\"",
"actual=$(git rev-parse HEAD)",
"test \"$actual\" = \"$source_commit\"",