mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 01:29:56 +00:00
* feat(release): accept exact-job recorded flakes in release validation A release lead can classify one failed Normal CI job of a Full Release Validation run as a flake through the trusted classification workflow. The receipt binds the exact job id and attempt, CI child run, FRV parent run and attempt, and Release SHA, and carries a tracking issue or PR plus a reason. Release Decision, the manifest, the publisher's live re-derivation, the step summary, and the GitHub release notes tail treat it as a visible advisory. Required classes and every other child stay blocking. * docs(release): fold recorded flakes into the shared release boundaries * fix(release): scope flake receipt discovery to the CI child run * fix(release): require main lineage for flake receipt producers * test(release): copy the flake classification module into tooling fixtures * fix(release): keep advisory-only release notes verifiable
68 lines
2 KiB
TypeScript
68 lines
2 KiB
TypeScript
export type FlakeClassification = {
|
|
schema: "openclaw.frv-flake-classification.v1";
|
|
parentRunId: string;
|
|
parentRunAttempt: number;
|
|
child: "normalCi";
|
|
childRunId: string;
|
|
childRunAttempt: number;
|
|
targetSha: string;
|
|
jobId: string;
|
|
jobName: string;
|
|
jobUrl: string;
|
|
conclusion: "failure" | "timed_out";
|
|
trackingUrl: string;
|
|
reason: string;
|
|
classifiedBy: string;
|
|
receiptRunId: string;
|
|
receiptRunAttempt: number;
|
|
};
|
|
export type FlakeJob = {
|
|
name: string;
|
|
status: string;
|
|
conclusion: string;
|
|
id?: number | string;
|
|
html_url?: string;
|
|
url?: string;
|
|
acceptedRunAttempt?: number;
|
|
run_attempt?: number;
|
|
};
|
|
export type FlakeChild = { key: string; runId: string; jobs: FlakeJob[] };
|
|
export type FlakeBinding = {
|
|
child?: FlakeChild;
|
|
parentRunId?: string;
|
|
parentRunAttempt?: number;
|
|
targetSha?: string;
|
|
};
|
|
export type FlakeGateEntry = { name: string; result: string; selected: boolean | string };
|
|
export type FlakeEvidence = {
|
|
flakeClassifications?: FlakeClassification[];
|
|
gateEntries?: FlakeGateEntry[];
|
|
};
|
|
export type FlakeApi = (
|
|
path: string,
|
|
options?: { format?: "json" | "text" | "bytes"; maxBytes?: number; signal?: AbortSignal },
|
|
) => Promise<unknown>;
|
|
export const RECORDED_FLAKE_DENIED_JOB_PATTERNS: readonly RegExp[];
|
|
export function isClassifiableFlakeJob(name: unknown): boolean;
|
|
export function validateFlakeClassification(
|
|
receipt: unknown,
|
|
expected?: FlakeBinding,
|
|
): FlakeClassification;
|
|
export function parseFlakeGateEntries(log: string): FlakeGateEntry[];
|
|
export function validateFlakeGateEntries(entries: unknown): FlakeGateEntry[];
|
|
export function recordFlakeClassification(options: {
|
|
inputs: Record<string, unknown>;
|
|
env?: NodeJS.ProcessEnv;
|
|
api?: FlakeApi;
|
|
}): Promise<FlakeClassification>;
|
|
export function loadFlakeClassifications(
|
|
options: FlakeBinding & {
|
|
repo?: string;
|
|
child: FlakeChild;
|
|
parentRunId: string;
|
|
parentRunAttempt: number;
|
|
targetSha: string;
|
|
api?: FlakeApi;
|
|
signal?: AbortSignal;
|
|
},
|
|
): Promise<FlakeEvidence>;
|