From dbcbf2867769a7def7552ee9a148d3fa6da44ad6 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 21 Jun 2026 14:54:44 +0000 Subject: [PATCH] fix: restore D601 git mirror SSH transport --- config/hwlab-node-control-plane.yaml | 7 +------ scripts/src/hwlab-node-impl.ts | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/config/hwlab-node-control-plane.yaml b/config/hwlab-node-control-plane.yaml index cdc1f0b2..01ea5dfb 100644 --- a/config/hwlab-node-control-plane.yaml +++ b/config/hwlab-node-control-plane.yaml @@ -117,12 +117,7 @@ targets: mode: node-global required: true githubTransport: - mode: https - username: x-access-token - tokenSecretName: git-mirror-github-token - tokenSecretKey: GITHUB_TOKEN - tokenSourceRef: /root/unidesk/.state/secrets/github/hwlab-git-mirror.env - tokenSourceKey: GH_TOKEN + mode: ssh tekton: pipelineName: hwlab-d601-v03-ci-image-publish serviceAccountName: hwlab-d601-v03-tekton-runner diff --git a/scripts/src/hwlab-node-impl.ts b/scripts/src/hwlab-node-impl.ts index 6631cf79..c894d5dc 100644 --- a/scripts/src/hwlab-node-impl.ts +++ b/scripts/src/hwlab-node-impl.ts @@ -2943,6 +2943,7 @@ function nodeRuntimeGitMirrorRun(scoped: ReturnType/dev/null", "kubectl create -f \"$manifest_path\"", - `deadline=$(( $(date +%s) + ${scoped.timeoutSeconds} ))`, + `deadline=$(( $(date +%s) + ${waitTimeoutSeconds} ))`, "while :; do", " status=$(kubectl get job -n \"$namespace\" \"$job\" -o jsonpath='succeeded={.status.succeeded} failed={.status.failed}' 2>/dev/null || true)", " succeeded=$(printf '%s\\n' \"$status\" | awk '{for (i = 1; i <= NF; i++) { split($i, a, \"=\"); if (a[1] == \"succeeded\") print a[2]; }}')", @@ -3011,7 +3012,7 @@ function nodeRuntimeGitMirrorRun(scoped: ReturnType= retryMaxAttempts; - const stopped = retryExhausted || retryableFailure?.stopped === true; + const stopped = !actionSucceeded && (retryExhausted || retryableFailure?.stopped === true || retryableFailure === null); return { ok: actionSucceeded && (status === undefined || status.ok === true), command: `hwlab nodes git-mirror ${scoped.action} --node ${scoped.node} --lane ${scoped.lane}`, @@ -3057,6 +3058,9 @@ function nodeRuntimeGitMirrorRetryableFailure( ): Record | null { const text = `${result.stdout}\n${result.stderr}`; const proxyConnectFailure = /hwlab git-mirror proxy-connect:/iu.test(text); + const waitTimeoutFailure = result.exitCode === 45 + || result.exitCode === 124 + || /UNIDESK_SSH_RUNTIME_TIMEOUT|ssh-runtime-timeout|ssh\/tran operation exceeded|job,pod/iu.test(text); const scriptTransportMismatch = (mirror.githubTransport.mode === "ssh" && /transport=https[\s\S]*https auth: missing GITHUB_TOKEN/iu.test(text)) || (mirror.githubTransport.mode === "https" && /transport=ssh\b/iu.test(text)); @@ -3080,6 +3084,15 @@ function nodeRuntimeGitMirrorRetryableFailure( } const authFailure = /Authentication failed|Invalid username or password|Repository not found|could not read Username|could not read Password|terminal prompts disabled|https auth: missing GITHUB_TOKEN/iu.test(text); if (authFailure) { + const authFix = mirror.githubTransport.mode === "ssh" + ? { + fixSecret: `apply the YAML-declared SSH private key Secret ${mirror.secretName} through the node control-plane infra apply path`, + status: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${scoped.node} --lane ${scoped.lane}`, + } + : { + fixSecret: "apply the YAML-declared githubTransport token source through the node control-plane infra apply path", + status: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${scoped.node} --lane ${scoped.lane}`, + }; return { retryable: false, retryAttempt: attempt, @@ -3087,18 +3100,16 @@ function nodeRuntimeGitMirrorRetryableFailure( retryLabel: `${attempt}/${retryMaxAttempts}`, retryExhausted: false, stopped: true, - reason: `Git mirror GitHub ${mirror.githubTransport.mode} authentication failed. This is not retryable; fix the YAML-declared token source/Secret instead of consuming retry budget.`, + reason: `Git mirror GitHub ${mirror.githubTransport.mode} authentication failed. This is not retryable; fix the YAML-declared ${mirror.githubTransport.mode === "ssh" ? "SSH key Secret" : "token source/Secret"} instead of consuming retry budget.`, refSources: nodeRuntimeGitMirrorRefSources(scoped, mirror), githubTransport: nodeRuntimeGitMirrorGithubTransportSummary(mirror), - next: { - fixSecret: "apply the YAML-declared githubTransport token source through the node control-plane infra apply path", - status: `bun scripts/cli.ts hwlab nodes git-mirror status --node ${scoped.node} --lane ${scoped.lane}`, - }, + next: authFix, valuesPrinted: false, }; } const retryable = partialSuccess !== null || proxyConnectFailure + || waitTimeoutFailure || /kex_exchange_identification|Connection closed by remote host|Could not read from remote repository|ssh.github.com|github.com|fetch-pack|early EOF/iu.test(text); if (!retryable) return null; const retryLabel = `${attempt}/${retryMaxAttempts}`; @@ -3114,6 +3125,8 @@ function nodeRuntimeGitMirrorRetryableFailure( nextRetryDelayMs: exhausted ? null : nodeRuntimeGitMirrorRetryDelayMs(attempt), reason: partialSuccess !== null ? "GitOps push appears to have succeeded, but the post-push fetch/recheck failed. Standard git-mirror stops without host workspace fallback." + : waitTimeoutFailure + ? "Git mirror job wait exceeded the controlled short-connection budget. Standard git-mirror retries with exponential backoff and stops when retry budget is exhausted." : proxyConnectFailure ? "Git mirror job hit a retryable YAML-first proxy CONNECT failure. Standard git-mirror keeps using the configured node-global proxy and stops when retry budget is exhausted." : `Git mirror job hit a retryable upstream GitHub ${mirror.githubTransport.mode} transport/fetch failure. Standard git-mirror stops without host workspace fallback.`,