Files
pikasTech-unidesk/scripts/src/platform-infra-gitea-disclosure.ts
T

387 lines
16 KiB
TypeScript

export interface MirrorWebhookDisclosureSelection {
repoKey: string | null;
deliveryId: string | null;
}
export function rawMirrorWebhookStatus(result: Record<string, unknown>): Record<string, unknown> {
return {
ok: result.ok === true,
action: "platform-infra-gitea-mirror-webhook-status",
mutation: false,
view: "raw",
target: result.target,
raw: record(result.remote),
safety: {
explicitRawRequired: true,
valuesPrinted: false,
stdoutGuard: "The YAML-configured stdout guard remains active; oversized raw evidence is written once to the protected dump path.",
},
};
}
export function buildMirrorWebhookStatusDisclosure(
result: Record<string, unknown>,
selection: MirrorWebhookDisclosureSelection,
): Record<string, unknown> {
const target = record(result.target);
const targetId = stringValue(target.id, "<node>");
const webhook = record(result.webhook);
const webhookRetry = record(webhook.ingressRetry);
const webhookHookReconcile = record(webhook.hookReconcile);
const webhookBridge = record(webhook.bridge);
const bridge = record(result.bridge);
const durableInbox = record(bridge.durableInbox);
const failedDeliveryRecovery = record(durableInbox.failedDeliveryRecovery);
const allRecoveryEntries = arrayRecords(failedDeliveryRecovery.entries);
const allRepositories = arrayRecords(result.repositories);
const inboxDeliveries = arrayRecords(durableInbox.deliveries);
const bridgeLogs = record(result.bridgeLogs);
const allLogEvents = arrayRecords(bridgeLogs.events);
const aggregateView = selection.repoKey === null && selection.deliveryId === null;
let selectedRepoKey = selection.repoKey;
let effectiveDeliveryId = selection.deliveryId;
let selectedInbox = selection.deliveryId === null
? undefined
: inboxDeliveries.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId
&& (selection.repoKey === null || stringValue(item.repo, "") === selection.repoKey));
if (selectedRepoKey === null && selectedInbox !== undefined) selectedRepoKey = stringValue(selectedInbox.repo, "") || null;
if (selectedRepoKey === null && selection.deliveryId !== null) {
const event = allLogEvents.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId);
selectedRepoKey = event === undefined ? null : stringValue(event.repo, "") || null;
}
let selectedRepository = selectedRepoKey === null
? undefined
: allRepositories.find((item) => stringValue(item.key, "") === selectedRepoKey);
if (selectedRepository === undefined && selection.deliveryId !== null) {
selectedRepository = allRepositories.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId);
if (selectedRepoKey === null && selectedRepository !== undefined) selectedRepoKey = stringValue(selectedRepository.key, "") || null;
}
if (effectiveDeliveryId === null && selectedRepository !== undefined) effectiveDeliveryId = stringValue(selectedRepository.deliveryId, "") || null;
if (selectedInbox === undefined && effectiveDeliveryId !== null) {
selectedInbox = inboxDeliveries.find((item) => stringValue(item.deliveryId, "") === effectiveDeliveryId
&& (selectedRepoKey === null || stringValue(item.repo, "") === selectedRepoKey));
}
if (selectedInbox === undefined && selectedRepository !== undefined) {
const repositoryInbox = record(selectedRepository.durableInboxRecord);
if (stringValue(repositoryInbox.deliveryId, "") === (effectiveDeliveryId ?? "")) selectedInbox = repositoryInbox;
}
const repositories = selectedRepoKey === null
? allRepositories
: allRepositories.filter((item) => stringValue(item.key, "") === selectedRepoKey);
const selectedRepositoryName = selectedRepository === undefined ? null : stringValue(selectedRepository.repository, "") || null;
const recoveryEntries = allRecoveryEntries.filter((item) => {
if (selectedRepositoryName !== null && stringValue(item.repository, "") !== selectedRepositoryName) return false;
if (effectiveDeliveryId !== null && stringValue(item.deliveryId, "") !== effectiveDeliveryId) return false;
return true;
});
const matchingLogEvents = allLogEvents.filter((item) => {
if (selectedRepoKey !== null && stringValue(item.repo, "") !== selectedRepoKey) return false;
if (effectiveDeliveryId !== null && stringValue(item.deliveryId, "") !== effectiveDeliveryId) return false;
return true;
});
const selectedLogEvents = matchingLogEvents.slice(aggregateView ? -3 : -4).map(webhookLogEventSummary);
const deliveryFound = effectiveDeliveryId !== null && (
selectedInbox !== undefined
|| (selectedRepository !== undefined && stringValue(selectedRepository.deliveryId, "") === effectiveDeliveryId)
|| matchingLogEvents.length > 0
);
const selectionError = selection.repoKey !== null && selectedRepository === undefined
? "repository-not-observed"
: selection.deliveryId !== null && !deliveryFound
? "delivery-not-observed-in-retained-evidence"
: null;
const selectedDelivery = selectedInbox === undefined ? null : webhookDeliverySummary(selectedInbox);
const currentDeliveries = repositories
.map((repo) => record(repo.durableInboxRecord))
.filter((item) => stringValue(item.deliveryId, "") !== "")
.map(webhookDeliveryAggregateSummary);
const firstError = firstWebhookStatusError({
repository: selectedRepository ?? allRepositories.find((repo) => compactErrorValue(repo.error) !== null),
delivery: selectedInbox,
logEvents: matchingLogEvents,
durableInbox,
bridgeLogs,
mirrorStatus: record(result.mirrorStatus),
});
const selectorArgs = [
selectedRepoKey === null ? "" : ` --repo ${selectedRepoKey}`,
effectiveDeliveryId === null ? "" : ` --delivery-id ${effectiveDeliveryId}`,
].join("");
const commandBase = `bun scripts/cli.ts platform-infra gitea mirror webhook status --target ${targetId}${selectorArgs}`;
const repoCommands = allRepositories.slice(0, 8).map((repo) => {
const key = stringValue(repo.key, "");
return {
key,
deliveryId: stringValue(repo.deliveryId, "") || null,
command: `bun scripts/cli.ts platform-infra gitea mirror webhook status --target ${targetId} --repo ${key}`,
};
});
return {
ok: result.ok === true && selectionError === null,
action: "platform-infra-gitea-mirror-webhook-status",
mutation: false,
view: selection.deliveryId !== null ? "delivery-drill-down" : selection.repoKey !== null ? "repository-drill-down" : "domain-aggregate",
target: {
id: target.id,
route: target.route,
namespace: target.namespace,
role: target.role,
},
selection: {
requestedRepoKey: selection.repoKey,
selectedRepoKey,
requestedDeliveryId: selection.deliveryId,
effectiveDeliveryId,
repositoryFound: selection.repoKey === null || selectedRepository !== undefined,
deliveryFound: selection.deliveryId === null || deliveryFound,
error: selectionError,
},
webhook: {
enabled: webhook.enabled === true,
direction: webhook.direction,
publicUrlSha256: webhookHookReconcile.desiredUrlSha256,
events: webhook.events,
responseBudgetMs: webhook.responseBudgetMs,
ingressAttemptBudgetMs: webhook.ingressAttemptBudgetMs,
ingressResponseHeaderTimeoutMs: webhook.ingressResponseHeaderTimeoutMs,
retry: {
enabled: webhookRetry.enabled === true,
maxAttempts: webhookRetry.maxAttempts,
initialDelayMs: webhookRetry.initialDelayMs,
maxDelayMs: webhookRetry.maxDelayMs,
},
bridge: {
deploymentName: webhookBridge.deploymentName,
serviceName: webhookBridge.serviceName,
},
hookReconcile: {
enabled: webhookHookReconcile.enabled === true,
ownerTargetId: webhookHookReconcile.ownerTargetId,
runningOnTarget: webhookHookReconcile.runningOnTarget === true,
intervalMs: webhookHookReconcile.intervalMs,
requestTimeoutMs: webhookHookReconcile.requestTimeoutMs,
topologySha256: webhookHookReconcile.topologySha256,
},
},
bridge: {
deployment: bridge.deployment,
ready: bridge.ready === true,
readyReplicas: bridge.readyReplicas,
serviceExists: bridge.serviceExists === true,
durableInbox: {
ready: durableInbox.ready === true,
storageReady: durableInbox.storageReady === true,
capacityAvailable: durableInbox.capacityAvailable === true,
counts: durableInbox.counts,
retainedDeliveryCount: inboxDeliveries.length,
totalBytes: durableInbox.totalBytes,
maxBytes: durableInbox.maxBytes,
errorType: durableInbox.errorType ?? null,
journal: durableInbox.journal,
failedDeliveryRecovery: {
enabled: failedDeliveryRecovery.enabled === true,
ready: failedDeliveryRecovery.ready === true,
state: failedDeliveryRecovery.state,
counts: failedDeliveryRecovery.counts,
entries: recoveryEntries.map(failedDeliveryRecoveryEntrySummary),
},
},
},
repositories: repositories.map(webhookRepositorySummary),
deliveries: selection.repoKey === null && selection.deliveryId === null ? currentDeliveries : selectedDelivery === null ? [] : [selectedDelivery],
retry: selectedInbox === undefined ? null : {
state: selectedInbox.state,
totalAttempts: selectedInbox.totalAttempts,
cycleAttempt: selectedInbox.cycleAttempt,
nextAttemptAt: selectedInbox.nextAttemptAt ?? null,
lastError: compactErrorValue(selectedInbox.lastError),
},
logs: {
exitCode: bridgeLogs.exitCode,
matched: matchingLogEvents.length,
returned: selectedLogEvents.length,
omitted: Math.max(0, matchingLogEvents.length - selectedLogEvents.length),
events: selectedLogEvents,
errorTail: compactErrorValue(bridgeLogs.errorTail),
},
diagnostics: {
mirrorStatus: {
exitCode: record(result.mirrorStatus).exitCode,
errorTail: compactErrorValue(record(result.mirrorStatus).errorTail),
},
firstError,
},
disclosure: {
rawOmitted: true,
retainedInboxRecords: inboxDeliveries.length,
rawRequiresExplicitFlag: true,
valuesPrinted: false,
},
next: {
repositories: repoCommands,
full: `${commandBase} --full`,
raw: `${commandBase} --raw`,
},
};
}
function failedDeliveryRecoveryEntrySummary(item: Record<string, unknown>): Record<string, unknown> {
return {
repository: item.repository,
hookId: item.hookId,
deliveryId: item.deliveryId,
state: item.state,
attempts: item.attempts,
cooldownMs: item.cooldownMs,
nextAt: item.nextAt ?? null,
updatedAt: item.updatedAt,
lastStatusCode: item.lastStatusCode ?? null,
completionReason: item.completionReason ?? null,
};
}
function webhookRepositorySummary(repo: Record<string, unknown>): Record<string, unknown> {
const selected = record(repo.selectedPushDelivery);
const topology = record(repo.hookTopology);
return {
key: repo.key,
repository: repo.repository,
branch: repo.branch,
hookReady: repo.hookReady === true,
githubHead: repo.githubHead,
branchCommit: repo.branchCommit,
snapshotCommit: repo.snapshotCommit,
authorityMatches: repo.authorityMatches === true,
stale: repo.bridgeEventStale === true,
staleReason: repo.staleReason ?? null,
deliveryId: selected.deliveryId ?? null,
deliveryAccepted: repo.deliveryAccepted === true,
selectedDelivery: {
deliveryId: selected.deliveryId ?? null,
hookId: selected.hookId ?? null,
status: selected.status ?? null,
statusCode: selected.statusCode ?? null,
deliveredAt: selected.deliveredAt ?? null,
accepted: repo.deliveryAccepted === true,
},
hookTopology: {
ready: topology.ready === true,
desiredUrlSha256: topology.desiredUrlSha256 ?? null,
desiredTopologyUrlSha256: Array.isArray(topology.desiredTopologyUrlSha256) ? topology.desiredTopologyUrlSha256 : [],
observedManagedUrlSha256: Array.isArray(topology.observedManagedUrlSha256) ? topology.observedManagedUrlSha256 : [],
driftTypes: Array.isArray(topology.driftTypes) ? topology.driftTypes : [],
},
durableState: repo.durableInboxState,
durableCommitted: repo.durableInboxCommitted === true,
error: compactErrorValue(repo.error),
};
}
function webhookDeliverySummary(delivery: Record<string, unknown>): Record<string, unknown> {
const result = record(delivery.result);
return {
deliveryId: delivery.deliveryId,
repo: delivery.repo,
repository: delivery.repository,
ref: delivery.ref,
requestedCommit: delivery.requestedCommit,
state: delivery.state,
acceptedSequence: delivery.acceptedSequence,
totalAttempts: delivery.totalAttempts,
cycleAttempt: delivery.cycleAttempt,
nextAttemptAt: delivery.nextAttemptAt ?? null,
updatedAt: delivery.updatedAt,
result: {
sourceCommit: result.sourceCommit,
authorityCommit: result.authorityCommit,
snapshotRef: result.snapshotRef,
disposition: result.disposition,
},
lastError: compactErrorValue(delivery.lastError),
};
}
function webhookDeliveryAggregateSummary(delivery: Record<string, unknown>): Record<string, unknown> {
const result = record(delivery.result);
return {
deliveryId: delivery.deliveryId,
repo: delivery.repo,
state: delivery.state,
totalAttempts: delivery.totalAttempts,
updatedAt: delivery.updatedAt,
requestedCommit: delivery.requestedCommit,
sourceCommit: result.sourceCommit,
disposition: result.disposition,
lastError: compactErrorValue(delivery.lastError),
};
}
function webhookLogEventSummary(event: Record<string, unknown>): Record<string, unknown> {
return {
event: event.event,
repo: event.repo,
deliveryId: event.deliveryId,
ok: event.ok === true,
terminal: event.terminal === true,
syncAttempt: event.syncAttempt,
disposition: event.disposition,
sourceCommit: event.sourceCommit,
authorityCommit: event.authorityCommit,
elapsedMs: event.elapsedMs,
errorType: event.errorType ?? null,
error: compactErrorValue(event.error),
};
}
function firstWebhookStatusError(input: {
repository?: Record<string, unknown>;
delivery?: Record<string, unknown>;
logEvents: Record<string, unknown>[];
durableInbox: Record<string, unknown>;
bridgeLogs: Record<string, unknown>;
mirrorStatus: Record<string, unknown>;
}): Record<string, unknown> | null {
const candidates: Array<[string, unknown]> = [
["repository", input.repository?.error],
["durable-inbox-record", input.delivery?.lastError],
["bridge-event", input.logEvents.find((event) => compactErrorValue(event.error) !== null)?.error],
["durable-inbox", input.durableInbox.errorType],
["bridge-logs", Number(input.bridgeLogs.exitCode) === 0 ? null : input.bridgeLogs.errorTail],
["mirror-status", Number(input.mirrorStatus.exitCode) === 0 ? null : input.mirrorStatus.errorTail],
];
for (const [domain, value] of candidates) {
const message = compactErrorValue(value);
if (message !== null) return { domain, message };
}
return null;
}
function compactErrorValue(value: unknown): string | null {
if (value === null || value === undefined || value === "") return null;
const text = typeof value === "string" ? value : JSON.stringify(value);
const compact = text.replace(/\s+/gu, " ").trim();
if (compact === "" || compact === "null" || compact === "{}") return null;
return compact.length > 240 ? `${compact.slice(0, 237)}...` : compact;
}
function record(value: unknown): Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : {};
}
function arrayRecords(value: unknown): Record<string, unknown>[] {
return Array.isArray(value)
? value.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)) as Record<string, unknown>[]
: [];
}
function stringValue(value: unknown, fallback = "-"): string {
if (typeof value === "string" && value.length > 0) return value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
return fallback;
}