fix: trigger sentinel follower via k8s api

This commit is contained in:
Codex
2026-07-03 07:34:58 +00:00
parent d4c2a55031
commit b556bb3647
3 changed files with 272 additions and 8 deletions
+44 -3
View File
@@ -136,7 +136,14 @@ export {
const SPEC_REF = "PJ2026-01060508 Web哨兵 draft-2026-07-01-p16-cicd-source-snapshot";
type SourceResolveMode = "cached" | "sync";
export type SourceResolveMode = "cached" | "sync";
export interface SentinelSourceOverride {
readonly commit: string;
readonly stageRef?: string | null;
readonly mirrorCommit?: string | null;
readonly sourceAuthority: "git-mirror-snapshot";
}
export function runWebProbeSentinelCommand(spec: HwlabRuntimeLaneSpec, options: WebProbeSentinelOptions): RenderedCliResult {
if (options.kind === "config") return withWebProbeSentinelConfigRendered(webProbeSentinelConfigPlan(spec, options.action, options.sentinelId));
@@ -534,7 +541,13 @@ function sentinelAlreadyCurrentControlResult(state: SentinelCicdState, observed:
};
}
function loadSentinelCicdState(spec: HwlabRuntimeLaneSpec, sentinelId: string | null, timeoutSeconds: number, sourceResolveMode: SourceResolveMode): SentinelCicdState {
export function loadSentinelCicdState(
spec: HwlabRuntimeLaneSpec,
sentinelId: string | null,
timeoutSeconds: number,
sourceResolveMode: SourceResolveMode,
sourceOverride: SentinelSourceOverride | null = null,
): SentinelCicdState {
const sentinel = resolveWebProbeSentinel(spec, sentinelId);
const configPlan = webProbeSentinelConfigPlan(spec, "status", sentinel.id);
const runtime = recordTarget(readWebProbeSentinelConfigRefTarget(spec, sentinel.configRefs.runtime), sentinel.configRefs.runtime);
@@ -549,7 +562,9 @@ function loadSentinelCicdState(spec: HwlabRuntimeLaneSpec, sentinelId: string |
const nodeId = stringField(controlPlaneTarget, "node");
const controlPlaneNode = recordTarget(valueAtPath(controlPlaneConfig, `nodes.${nodeId}`), `${configRefFile(controlPlaneRef)}#nodes.${nodeId}`);
validateSentinelSourceAuthority(cicd);
const sourceHead = resolveSourceHead(spec, cicd, controlPlaneTarget, controlPlaneNode, timeoutSeconds, sourceResolveMode);
const sourceHead = sourceOverride === null
? resolveSourceHead(spec, cicd, controlPlaneTarget, controlPlaneNode, timeoutSeconds, sourceResolveMode)
: sourceHeadFromOverride(cicd, sourceOverride);
const image = sentinelImagePlan(spec, cicd, sourceHead);
const manifests = renderSentinelManifests(spec, sentinel.id, runtime, cicd, scenarios, publicExposure, secrets, image);
const manifestYaml = `${manifests.map((item) => Bun.YAML.stringify(item).trim()).join("\n---\n")}\n`;
@@ -573,6 +588,32 @@ function loadSentinelCicdState(spec: HwlabRuntimeLaneSpec, sentinelId: string |
};
}
function sourceHeadFromOverride(cicd: Record<string, unknown>, override: SentinelSourceOverride): SourceHead {
if (!/^[0-9a-f]{40}$/iu.test(override.commit)) throw new Error(`sentinel source override commit must be a full sha, got ${override.commit}`);
const stageRef = override.stageRef ?? sentinelSourceSnapshotRef(cicd, override.commit);
if (!stageRef.startsWith("refs/")) throw new Error(`sentinel source override stageRef must be a git ref, got ${stageRef}`);
const mirrorCommit = override.mirrorCommit ?? override.commit;
if (!/^[0-9a-f]{40}$/iu.test(mirrorCommit)) throw new Error(`sentinel source override mirrorCommit must be a full sha, got ${mirrorCommit}`);
return {
ok: true,
repository: stringAt(cicd, "source.repository"),
branch: stringAt(cicd, "source.branch"),
commit: override.commit,
stageRef,
mirrorCommit,
sourceAuthority: override.sourceAuthority,
latestDrift: mirrorCommit !== override.commit,
result: {
exitCode: 0,
timedOut: false,
stdoutBytes: 0,
stderrBytes: 0,
stdoutPreview: "source supplied by cicd branch-follower k8s git-mirror snapshot",
stderrPreview: "",
},
};
}
function resolveSourceHead(
spec: HwlabRuntimeLaneSpec,
cicd: Record<string, unknown>,