mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
885c1486bb
* test(ci): single-retry policy for enumerated contention-flaky files * fix: satisfy fallow * test(ci): read failures through a lane reporter so timeouts stay distinguishable * test(ci): cover the lane reporter and drop its duplicated boilerplate * chore(fallow): own the retry lane's tool-loaded export seams * test(ci): block retries on non-test failures and classify timeouts structurally * test(ci): decide retry eligibility from runner metadata and route gate verdicts through blockers * refactor(ci): name the retry policy's rules in code instead of comments * test(ci): mark runner-aborted timeouts inside the runner instead of inferring them * test(ci): make timeout provenance a per-run secret, not a writable flag Cover direct task.meta mutation in the real child-Vitest fixture gate. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(ci): retry the failed files in the first run's project and coverage modes Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: drop deleted repo-health file from the retry list after #1480 Rebase onto main post-#1480: the SkillGym/repo-health descope deleted scripts/repo-health/run.test.ts, whose CONTENTION_RETRY_FILES entry would now fail this PR's own missing-file check, and inlined the slow-test budgets into the reporter, resolving the budgets-module import. Envelope comments now point at scripts/lib/lane-envelope.ts instead of the closed #1430. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUv7bvbWNryuXgSBuqTtep --------- Co-authored-by: Michał Pierzchała <thymikee@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
// Standard artifact envelope for scheduled lanes.
|
|
//
|
|
// A scheduled lane can go dark or drift for weeks while PR CI stays green, so
|
|
// every artifact it uploads must say — without a human reading logs — which
|
|
// commit produced it, which tool/config version measured it, how long it took,
|
|
// and whether it passed. Freshness monitoring reads `finishedAt`/`result`; drift
|
|
// analysis reads `tool`/`configHash`.
|
|
//
|
|
// Lanes that adopt the envelope later should import this module rather than
|
|
// re-deriving the field names.
|
|
|
|
export const LANE_ENVELOPE_SCHEMA_VERSION = 1;
|
|
|
|
export type LaneResult = 'pass' | 'fail';
|
|
|
|
export type LaneEnvelope<T> = {
|
|
schemaVersion: number;
|
|
/** Stable lane id — the metric key freshness/health jobs group by. */
|
|
lane: string;
|
|
commit: string;
|
|
ref: string | undefined;
|
|
runUrl: string | undefined;
|
|
/** Tool versions, or content hashes where a version is not enough. */
|
|
tool: Record<string, string>;
|
|
configHash: string;
|
|
/** Only lanes with randomized input record a seed; `null` states "not applicable". */
|
|
seed: string | null;
|
|
startedAt: string;
|
|
finishedAt: string;
|
|
durationMs: number;
|
|
result: LaneResult;
|
|
/** Lane-specific payload; kept separate so the envelope shape stays stable. */
|
|
data: T;
|
|
};
|
|
|
|
export type LaneEnvelopeInput<T> = {
|
|
lane: string;
|
|
commit: string;
|
|
tool: Record<string, string>;
|
|
configHash: string;
|
|
startedAtMs: number;
|
|
result: LaneResult;
|
|
data: T;
|
|
seed?: string | null;
|
|
now?: number;
|
|
};
|
|
|
|
export function laneEnvelope<T>(input: LaneEnvelopeInput<T>): LaneEnvelope<T> {
|
|
const finished = input.now ?? Date.now();
|
|
const { GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID, GITHUB_REF_NAME } = process.env;
|
|
return {
|
|
schemaVersion: LANE_ENVELOPE_SCHEMA_VERSION,
|
|
lane: input.lane,
|
|
commit: input.commit,
|
|
ref: GITHUB_REF_NAME,
|
|
runUrl:
|
|
GITHUB_SERVER_URL && GITHUB_REPOSITORY && GITHUB_RUN_ID
|
|
? `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`
|
|
: undefined,
|
|
tool: input.tool,
|
|
configHash: input.configHash,
|
|
seed: input.seed ?? null,
|
|
startedAt: new Date(input.startedAtMs).toISOString(),
|
|
finishedAt: new Date(finished).toISOString(),
|
|
durationMs: Math.max(0, finished - input.startedAtMs),
|
|
result: input.result,
|
|
data: input.data,
|
|
};
|
|
}
|