diff --git a/scripts/src/hwlab-g14.ts b/scripts/src/hwlab-g14.ts index 328d0780..014f258c 100644 --- a/scripts/src/hwlab-g14.ts +++ b/scripts/src/hwlab-g14.ts @@ -1725,6 +1725,7 @@ function compactGitMirrorStatus(status: Record, sourceCommit: s ok: status.ok === true, readUrl: status.readUrl ?? V02_GIT_READ_URL, writeUrl: status.writeUrl ?? V02_GIT_WRITE_URL, + elapsedMs: status.elapsedMs ?? null, legacyCronJobExists: nested(status, ["legacyCronJob", "exists"]) === true, required: requirement.required, sourceCommit, @@ -1823,91 +1824,107 @@ function preSyncV02GitMirror(sourceCommit: string, options: Pick { - const resources = g14K3s([ - "kubectl", - "get", - "deploy,svc,pvc,cm", - "-n", - GIT_MIRROR_NAMESPACE, - "-l", - "app.kubernetes.io/name=git-mirror", - "-o", - "name", - ], 60_000); - const legacyCronJob = g14K3s([ - "kubectl", - "get", - "cronjob", - "-n", - GIT_MIRROR_NAMESPACE, - GIT_MIRROR_LEGACY_CRONJOB, - "--ignore-not-found", - "-o", - "name", - ], 60_000); - const jobs = g14K3s([ - "kubectl", - "get", - "job", - "-n", - GIT_MIRROR_NAMESPACE, - "-l", - "app.kubernetes.io/name=git-mirror", - "--sort-by=.metadata.creationTimestamp", - "-o", - "custom-columns=NAME:.metadata.name,SUCCEEDED:.status.succeeded,FAILED:.status.failed,START:.status.startTime,COMPLETION:.status.completionTime", - "--no-headers", - ], 60_000); - const cache = g14K3s([ - "kubectl", - "exec", - "-n", - GIT_MIRROR_NAMESPACE, - "deploy/git-mirror-http", - "--", - "sh", - "-lc", + const startedAtMs = Date.now(); + const cacheScript = [ + "printf 'lastSync='; cat /cache/HWLAB.last-sync.json 2>/dev/null || true; printf '\\n'", + "printf 'lastWrite='; cat /cache/HWLAB.last-write.json 2>/dev/null || true; printf '\\n'", + "printf 'lastFlush='; cat /cache/HWLAB.last-flush.json 2>/dev/null || true; printf '\\n'", + "printf 'refs='", + "node - <<'NODE' 2>/dev/null || true", + "const { execFileSync } = require('node:child_process');", + "const repo = '/cache/pikasTech/HWLAB.git';", + "function rev(ref) {", + " try {", + " return execFileSync('git', ['--git-dir=' + repo, 'rev-parse', ref], { encoding: 'utf8' }).trim();", + " } catch {", + " return null;", + " }", + "}", + "const localGitops = rev('refs/heads/v0.2-gitops');", + "const githubGitops = rev('refs/mirror-stage/heads/v0.2-gitops');", + "console.log(JSON.stringify({", + " refs: {", + " localV02: rev('refs/heads/v0.2'),", + " localG14: rev('refs/heads/G14'),", + " localGitops,", + " githubGitops,", + " },", + " pendingFlush: Boolean(localGitops && githubGitops && localGitops !== githubGitops),", + "}));", + "NODE", + ].join("\n"); + const script = [ + "set +e", + "section() {", + " name=\"$1\"", + " shift", + " printf '__UNIDESK_SECTION_BEGIN__ %s\\n' \"$name\"", + " \"$@\"", + " code=$?", + " printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"", + "}", [ - "printf 'lastSync='; cat /cache/HWLAB.last-sync.json 2>/dev/null || true; printf '\\n'", - "printf 'lastWrite='; cat /cache/HWLAB.last-write.json 2>/dev/null || true; printf '\\n'", - "printf 'lastFlush='; cat /cache/HWLAB.last-flush.json 2>/dev/null || true; printf '\\n'", - "printf 'refs='", - "node - <<'NODE' 2>/dev/null || true", - "const { execFileSync } = require('node:child_process');", - "const repo = '/cache/pikasTech/HWLAB.git';", - "function rev(ref) { try { return execFileSync('git', ['--git-dir=' + repo, 'rev-parse', ref], { encoding: 'utf8' }).trim(); } catch { return null; } }", - "const localGitops = rev('refs/heads/v0.2-gitops');", - "const githubGitops = rev('refs/mirror-stage/heads/v0.2-gitops');", - "console.log(JSON.stringify({ refs: { localV02: rev('refs/heads/v0.2'), localG14: rev('refs/heads/G14'), localGitops, githubGitops }, pendingFlush: Boolean(localGitops && githubGitops && localGitops !== githubGitops) }));", - "NODE", - ].join("\n"), - ], 60_000); + "section resources kubectl get deploy,svc,pvc,cm", + `-n ${shellQuote(GIT_MIRROR_NAMESPACE)}`, + "-l app.kubernetes.io/name=git-mirror", + "-o name", + ].join(" "), + [ + "section legacyCronJob kubectl get cronjob", + `-n ${shellQuote(GIT_MIRROR_NAMESPACE)}`, + shellQuote(GIT_MIRROR_LEGACY_CRONJOB), + "--ignore-not-found", + "-o name", + ].join(" "), + [ + `section jobs kubectl get job -n ${shellQuote(GIT_MIRROR_NAMESPACE)}`, + "-l app.kubernetes.io/name=git-mirror", + "--sort-by=.metadata.creationTimestamp", + "-o custom-columns=NAME:.metadata.name,SUCCEEDED:.status.succeeded,FAILED:.status.failed,START:.status.startTime,COMPLETION:.status.completionTime", + "--no-headers", + ].join(" "), + [ + "section cache kubectl exec", + `-n ${shellQuote(GIT_MIRROR_NAMESPACE)}`, + "deploy/git-mirror-http", + "-- sh -lc", + shellQuote(cacheScript), + ].join(" "), + ].join("\n"); + const bundle = g14K3s(["script", "--", script], 60_000); + const sections = parseShellSections(statusText(bundle)); + const resources = sections.resources; + const legacyCronJob = sections.legacyCronJob; + const jobs = sections.jobs; + const cache = sections.cache; + const bundleStderr = bundle.stderr.trim().slice(0, 2000); return { - ok: isCommandSuccess(resources), + ok: isCommandSuccess(bundle) && shellSectionOk(resources), command: "hwlab g14 git-mirror status", namespace: GIT_MIRROR_NAMESPACE, readUrl: V02_GIT_READ_URL, writeUrl: V02_GIT_WRITE_URL, + elapsedMs: Date.now() - startedAtMs, resources: { - ok: isCommandSuccess(resources), - names: statusText(resources).split(/\r?\n/u).map((line) => line.trim()).filter(Boolean), - stderr: resources.stderr.trim().slice(0, 2000), + ok: shellSectionOk(resources), + names: String(resources?.stdout ?? "").split(/\r?\n/u).map((line) => line.trim()).filter(Boolean), + stderr: shellSectionOk(resources) ? "" : bundleStderr, }, legacyCronJob: { - ok: isCommandSuccess(legacyCronJob), - exists: statusText(legacyCronJob).trim().length > 0, - name: statusText(legacyCronJob).trim() || null, + ok: shellSectionOk(legacyCronJob), + exists: String(legacyCronJob?.stdout ?? "").trim().length > 0, + name: String(legacyCronJob?.stdout ?? "").trim() || null, cleanupCommand: "bun scripts/cli.ts hwlab g14 git-mirror apply --confirm", }, jobs: { - ok: isCommandSuccess(jobs), - raw: statusText(jobs), - stderr: jobs.stderr.trim().slice(0, 2000), + ok: shellSectionOk(jobs), + raw: String(jobs?.stdout ?? "").trim(), + stderr: shellSectionOk(jobs) ? "" : bundleStderr, }, cache: { - ok: isCommandSuccess(cache), - raw: statusText(cache), - stderr: cache.stderr.trim().slice(0, 2000), + ok: shellSectionOk(cache), + raw: String(cache?.stdout ?? "").trim(), + stderr: shellSectionOk(cache) ? "" : bundleStderr, }, next: { apply: "bun scripts/cli.ts hwlab g14 git-mirror apply --confirm",