fix(cicd): preserve refresh evidence in live status
This commit is contained in:
@@ -635,6 +635,7 @@ async function applyController(registry: BranchFollowerRegistry, options: Parsed
|
||||
|
||||
async function buildStatus(registry: BranchFollowerRegistry, options: ParsedOptions): Promise<Record<string, unknown>> {
|
||||
let k8s = readK8sState(registry, options);
|
||||
const beforeRefreshStateByFollower = k8s.stateByFollower;
|
||||
const wantsLive = options.live || (!options.noLive && Object.keys(k8s.stateByFollower).length === 0);
|
||||
const refresh = wantsLive && !options.inCluster ? runControllerReconcileJob(registry, options, { dryRun: true, wait: true, recordState: true }) : null;
|
||||
if (refresh !== null) k8s = readK8sState(registry, options);
|
||||
@@ -644,8 +645,9 @@ async function buildStatus(registry: BranchFollowerRegistry, options: ParsedOpti
|
||||
const detailedFollowers = options.followerId !== null || options.full;
|
||||
for (const follower of selected) {
|
||||
const stored = k8s.stateByFollower[follower.id] ?? {};
|
||||
const fallbackStored = refresh === null ? {} : beforeRefreshStateByFollower[follower.id] ?? {};
|
||||
const live = shouldLive && follower.enabled ? await readAdapterStatus(registry, follower, options) : null;
|
||||
followers.push(mergeFollowerStatus(registry, follower, stored, live, shouldLive, detailedFollowers));
|
||||
followers.push(mergeFollowerStatus(registry, follower, stored, live, shouldLive, detailedFollowers, fallbackStored));
|
||||
}
|
||||
return {
|
||||
ok: k8s.ok && followers.every((item) => item.ok !== false),
|
||||
@@ -666,6 +668,7 @@ async function buildStatus(registry: BranchFollowerRegistry, options: ParsedOpti
|
||||
|
||||
async function runOnce(registry: BranchFollowerRegistry, options: ParsedOptions): Promise<Record<string, unknown>> {
|
||||
if (!options.inCluster) {
|
||||
const before = readK8sState(registry, options);
|
||||
const refresh = runControllerReconcileJob(registry, options, { dryRun: options.dryRun, wait: true, recordState: true });
|
||||
const k8s = readK8sState(registry, options);
|
||||
const selected = selectFollowers(registry, options, { includeDisabled: false });
|
||||
@@ -679,7 +682,7 @@ async function runOnce(registry: BranchFollowerRegistry, options: ParsedOptions)
|
||||
execution: "k8s-native-reconcile-job",
|
||||
registry: registrySummary(registry),
|
||||
job: refresh,
|
||||
followers: selected.map((follower) => mergeFollowerStatus(registry, follower, k8s.stateByFollower[follower.id] ?? {}, null, false)),
|
||||
followers: selected.map((follower) => mergeFollowerStatus(registry, follower, k8s.stateByFollower[follower.id] ?? {}, null, false, false, before.stateByFollower[follower.id] ?? {})),
|
||||
warnings: refresh.ok ? [] : [`reconcile job failed: ${refresh.message}`],
|
||||
next: {
|
||||
status: "bun scripts/cli.ts cicd branch-follower status",
|
||||
@@ -1943,6 +1946,7 @@ function mergeFollowerStatus(
|
||||
live: AdapterSummary | null,
|
||||
liveRequested: boolean,
|
||||
detailed: boolean,
|
||||
fallbackStored: Record<string, unknown> = {},
|
||||
): Record<string, unknown> {
|
||||
const storedSource = asOptionalRecord(stored.source);
|
||||
const storedTarget = asOptionalRecord(stored.target);
|
||||
@@ -1956,6 +1960,7 @@ function mergeFollowerStatus(
|
||||
observedSha,
|
||||
livePayload: asOptionalRecord(live?.payload),
|
||||
storedCommand: asOptionalRecord(stored.command),
|
||||
fallbackStoredCommand: asOptionalRecord(fallbackStored.command),
|
||||
});
|
||||
const reconcileTimeline = compactReconcileTimeline(asOptionalRecord(stored.command)?.reconcileTimeline, follower.id) ?? {
|
||||
bounded: true,
|
||||
|
||||
@@ -23,14 +23,14 @@ export function followerEvidenceSummary(input: {
|
||||
observedSha: string | null;
|
||||
livePayload: Record<string, unknown> | null;
|
||||
storedCommand: Record<string, unknown> | null;
|
||||
fallbackStoredCommand?: Record<string, unknown> | null;
|
||||
}): Record<string, unknown> | null {
|
||||
const livePayload = input.livePayload;
|
||||
const storedPayload = asOptionalRecord(input.storedCommand?.payload);
|
||||
const payload = livePayload ?? storedPayload;
|
||||
if (payload === null) return null;
|
||||
const tekton = asOptionalRecord(payload.tekton);
|
||||
const pipeline = asOptionalRecord(payload.pipeline);
|
||||
const refresh = asOptionalRecord(payload.refreshEvidence);
|
||||
const fallbackStoredPayload = asOptionalRecord(input.fallbackStoredCommand?.payload);
|
||||
const tekton = firstRecord(asOptionalRecord(livePayload?.tekton), asOptionalRecord(storedPayload?.tekton), asOptionalRecord(fallbackStoredPayload?.tekton));
|
||||
const pipeline = firstRecord(asOptionalRecord(livePayload?.pipeline), asOptionalRecord(storedPayload?.pipeline), asOptionalRecord(fallbackStoredPayload?.pipeline));
|
||||
const refresh = firstRecord(asOptionalRecord(storedPayload?.refreshEvidence), asOptionalRecord(fallbackStoredPayload?.refreshEvidence), asOptionalRecord(livePayload?.refreshEvidence));
|
||||
if (tekton === null && pipeline === null && refresh === null) return null;
|
||||
const pipelineRefName = stringOrNull(tekton?.pipelineRefName);
|
||||
const pipelineName = stringOrNull(asOptionalRecord(pipeline?.metadata)?.name);
|
||||
@@ -39,6 +39,7 @@ export function followerEvidenceSummary(input: {
|
||||
return {
|
||||
pipelineRunRefName: pipelineRefName,
|
||||
pipeline,
|
||||
refreshBoundedReason: refresh === null ? "missing-from-live-and-stored-evidence" : null,
|
||||
refresh: refresh === null
|
||||
? null
|
||||
: {
|
||||
@@ -50,6 +51,13 @@ export function followerEvidenceSummary(input: {
|
||||
};
|
||||
}
|
||||
|
||||
function firstRecord(...values: Array<Record<string, unknown> | null>): Record<string, unknown> | null {
|
||||
for (const value of values) {
|
||||
if (value !== null) return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function asOptionalRecord(value: unknown): Record<string, unknown> | null {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : null;
|
||||
}
|
||||
|
||||
@@ -253,7 +253,15 @@ function evidenceRowsForFollower(item: Record<string, unknown>): unknown[][] {
|
||||
]);
|
||||
}
|
||||
const refresh = asOptionalRecord(evidence.refresh);
|
||||
if (refresh !== null) rows.push([item.id, "refresh", stringOrNull(refresh.status) ?? "-", `${shortSha(stringOrNull(refresh.sourceCommit))}/${boolMatch(refresh.pipelineRefMatches)}/${boolMatch(refresh.pipelineSpecMatches)}`, stringOrNull(refresh.pipeline) ?? "-"]);
|
||||
rows.push([
|
||||
item.id,
|
||||
"refresh",
|
||||
refresh === null ? "missing" : stringOrNull(refresh.status) ?? "-",
|
||||
refresh === null
|
||||
? stringOrNull(evidence.refreshBoundedReason) ?? "-"
|
||||
: `${shortSha(stringOrNull(refresh.sourceCommit))}/${boolMatch(refresh.pipelineRefMatches)}/${boolMatch(refresh.pipelineSpecMatches)}`,
|
||||
refresh === null ? "-" : stringOrNull(refresh.pipeline) ?? "-",
|
||||
]);
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user