fix: use k8s git mirror source snapshots

This commit is contained in:
Codex
2026-07-01 11:03:18 +00:00
parent b972ebd290
commit d687bdf668
20 changed files with 465 additions and 57 deletions
+18 -7
View File
@@ -13,7 +13,7 @@ import { runCommand, type CommandResult } from "../command";
import { startJob } from "../jobs";
import { classifySshTcpPoolFailure } from "../ssh";
import { HWLAB_NODE_CONTROL_PLANE_CONFIG_PATH, hwlabNodeControlPlaneInfraHelp, runHwlabNodeControlPlaneInfra } from "../hwlab-node-control-plane";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, hwlabRuntimeLaneSpecForNode, hwlabRuntimeNodeIds, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeObservabilityRecordingRuleSpec, type HwlabRuntimeObservabilitySpec, type HwlabRuntimeObservabilityWarningAlertSpec, type HwlabRuntimePublicExposureSpec, type HwlabRuntimeWebProbeAlertThresholdsSpec, type HwlabRuntimeWebProbeProjectManagementSpec } from "../hwlab-node-lanes";
import { hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, hwlabRuntimeLaneSpecForNode, hwlabRuntimeNodeIds, hwlabRuntimeSourceSnapshotStageRefPrefix, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec, type HwlabRuntimeObservabilityRecordingRuleSpec, type HwlabRuntimeObservabilitySpec, type HwlabRuntimeObservabilityWarningAlertSpec, type HwlabRuntimePublicExposureSpec, type HwlabRuntimeWebProbeAlertThresholdsSpec, type HwlabRuntimeWebProbeProjectManagementSpec } from "../hwlab-node-lanes";
import { nodeWebProbeScriptRunnerSource } from "../hwlab-node-web-probe-runner-source";
import { nodeWebObserveAnalyzerSource } from "../hwlab-node-web-observe-analyzer-source";
import { nodeWebObserveRunnerSource } from "../hwlab-node-web-observe-runner-source";
@@ -68,6 +68,7 @@ export function nodeRuntimeGitMirrorStatus(scoped: ReturnType<typeof parseNodeSc
`cache_host_path=${shellQuote(mirror.cacheHostPath ?? "")}`,
`source_repository=${shellQuote(mirror.sourceRepository)}`,
`source_branch=${shellQuote(mirror.sourceBranch)}`,
`source_stage_ref_prefix=${shellQuote(hwlabRuntimeSourceSnapshotStageRefPrefix(spec))}`,
`gitops_branch=${shellQuote(mirror.gitopsBranch)}`,
`github_transport_mode=${shellQuote(mirror.githubTransport.mode)}`,
`github_ssh_secret=${shellQuote(mirror.githubTransport.mode === "ssh" ? mirror.secretName : "")}`,
@@ -125,38 +126,42 @@ export function nodeRuntimeGitMirrorStatus(scoped: ReturnType<typeof parseNodeSc
" value = {}",
"sys.exit(0 if isinstance(value, dict) and value.get('localSource') else 1)",
"PY",
" summary_json=$(kubectl -n \"$namespace\" exec deploy/\"$read_deploy\" -- sh -lc \"source_repository=\\$1 source_branch=\\$2 gitops_branch=\\$3 node <<'NODE'",
" summary_json=$(kubectl -n \"$namespace\" exec deploy/\"$read_deploy\" -- sh -lc \"source_repository=\\$1 source_branch=\\$2 source_stage_ref_prefix=\\$3 gitops_branch=\\$4 node <<'NODE'",
"const { execFileSync } = require('node:child_process');",
"const { readFileSync, existsSync } = require('node:fs');",
"const repository = process.env.source_repository;",
"const sourceBranch = process.env.source_branch;",
"const sourceStageRefPrefix = process.env.source_stage_ref_prefix;",
"const gitopsBranch = process.env.gitops_branch;",
"const repoPath = '/cache/' + repository + '.git';",
"function readJson(path) { try { return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : null; } catch { return null; } }",
"function rev(ref) { try { return execFileSync('git', ['--git-dir=' + repoPath, 'rev-parse', '--verify', ref + '^{commit}'], { encoding: 'utf8' }).trim(); } catch { return null; } }",
"const localSource = rev('refs/heads/' + sourceBranch);",
"const githubSource = rev('refs/mirror-stage/heads/' + sourceBranch);",
"const sourceStageRef = githubSource ? sourceStageRefPrefix.replace(/\\/+$/, '') + '/' + githubSource : null;",
"const sourceSnapshot = sourceStageRef ? rev(sourceStageRef) : null;",
"const localGitops = rev('refs/heads/' + gitopsBranch);",
"const githubGitops = rev('refs/mirror-stage/heads/' + gitopsBranch);",
"const pendingFlush = Boolean(localGitops && (!githubGitops || localGitops !== githubGitops));",
"console.log(JSON.stringify({",
" localSource, githubSource, localGitops, githubGitops,",
" localSource, githubSource, sourceAuthority: 'git-mirror-snapshot', sourceStageRef, sourceSnapshot, localGitops, githubGitops,",
" refSources: {",
" localSource: 'refs/heads/' + sourceBranch,",
" githubSource: 'refs/mirror-stage/heads/' + sourceBranch,",
" sourceSnapshot: sourceStageRef,",
" localGitops: 'refs/heads/' + gitopsBranch,",
" githubGitops: 'refs/mirror-stage/heads/' + gitopsBranch,",
" githubFieldsAreMirrorStageCache: true",
" },",
" pendingFlush,",
" flushNeeded: pendingFlush,",
" githubInSync: Boolean(localSource && githubSource && localSource === githubSource && localGitops && githubGitops && localGitops === githubGitops),",
" githubInSync: Boolean(localSource && githubSource && localSource === githubSource && sourceSnapshot === githubSource && localGitops && githubGitops && localGitops === githubGitops),",
" statusSource: 'cache-ref-fallback',",
" lastSync: readJson('/cache/HWLAB.last-sync.json'),",
" lastFlush: readJson('/cache/HWLAB.last-flush.json')",
"}));",
"NODE",
"\" sh \"$source_repository\" \"$source_branch\" \"$gitops_branch\" 2>>/tmp/hwlab-node-gitmirror-status.err || true)",
"\" sh \"$source_repository\" \"$source_branch\" \"$source_stage_ref_prefix\" \"$gitops_branch\" 2>>/tmp/hwlab-node-gitmirror-status.err || true)",
"fi",
"if [ -z \"$summary_json\" ]; then summary_json='{}'; fi",
"read_deployment_ready=$(deploy_ready \"$namespace\" \"$read_deploy\")",
@@ -180,7 +185,8 @@ export function nodeRuntimeGitMirrorStatus(scoped: ReturnType<typeof parseNodeSc
" return os.environ.get(name) == 'true'",
"summary = load_env_json('SUMMARY_JSON')",
"github_transport = load_env_json('GITHUB_TRANSPORT_JSON')",
"ok = truth('read_deployment_ready') and truth('write_deployment_ready') and truth('read_service_exists') and truth('write_service_exists') and truth('read_endpoints_ready') and truth('write_endpoints_ready') and (truth('cache_pvc_exists') or truth('cache_host_path_exists')) and github_transport.get('ready') is not False and bool(summary.get('localSource'))",
"source_snapshot_ready = bool(summary.get('githubSource')) and summary.get('sourceSnapshot') == summary.get('githubSource')",
"ok = truth('read_deployment_ready') and truth('write_deployment_ready') and truth('read_service_exists') and truth('write_service_exists') and truth('read_endpoints_ready') and truth('write_endpoints_ready') and (truth('cache_pvc_exists') or truth('cache_host_path_exists')) and github_transport.get('ready') is not False and bool(summary.get('localSource')) and source_snapshot_ready",
"print(json.dumps({",
" 'ok': bool(ok),",
" 'resources': {",
@@ -727,10 +733,11 @@ export function withNodeRuntimeGitMirrorRendered(result: Record<string, unknown>
Object.keys(summary).length === 0
? "REFS\n-"
: webObserveTable(
["LOCAL_SOURCE", "GITHUB_SOURCE", "LOCAL_GITOPS", "GITHUB_GITOPS", "PENDING", "IN_SYNC"],
["LOCAL_SOURCE", "GITHUB_SOURCE", "SNAPSHOT", "LOCAL_GITOPS", "GITHUB_GITOPS", "PENDING", "IN_SYNC"],
[[
shortValue(summary.localSource),
shortValue(summary.githubSource),
shortValue(summary.sourceSnapshot),
shortValue(summary.localGitops),
shortValue(summary.githubGitops),
webObserveText(summary.pendingFlush),
@@ -783,6 +790,10 @@ export function compactNodeRuntimeGitMirrorStatus(status: Record<string, unknown
ok: status.ok === true,
localSource: summary.localSource ?? null,
githubSource: summary.githubSource ?? null,
sourceAuthority: summary.sourceAuthority ?? null,
sourceStageRef: summary.sourceStageRef ?? null,
sourceSnapshot: summary.sourceSnapshot ?? null,
sourceSnapshotReady: Boolean(summary.githubSource && summary.sourceSnapshot === summary.githubSource),
localGitops: summary.localGitops ?? null,
githubGitops: summary.githubGitops ?? null,
pendingFlush: summary.pendingFlush === true,