Skip to content

Commit 8ccde0c

Browse files
refactor(flaky-history-analysis): update history table and window counts
1 parent 533b46b commit 8ccde0c

1 file changed

Lines changed: 30 additions & 11 deletions

File tree

.github/scripts/flaky-sticky-comment.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ const AI_ANALYSIS_PATH = join(WORKSPACE_ROOT, '.ai-pr-analyzer/flaky-ai-analysis
4343
const PRIOR_STATE_PATH = join(WORKSPACE_ROOT, '.ai-pr-analyzer/flaky-prior-state.json');
4444

4545
// Failure counts bucketed by lookback window (nested: a failure in 7d also
46-
// counts in 30d/90d/365d). Kept as a permissive Record so a future window edit
47-
// in Stage 1 doesn't require a matching type change here.
46+
// counts in 30d). Kept as a permissive Record so a future window edit in
47+
// Stage 1 doesn't require a matching type change here.
4848
type WindowCounts = Record<string, number>;
4949

5050
interface HistoryFile {
@@ -124,7 +124,7 @@ function readJsonOrEmpty<T>(path: string, emptyShape: T): T {
124124

125125
// Fallback window set used only if the Stage 1 artifact predates the `windows`
126126
// field; the live artifact always supplies its own list.
127-
const DEFAULT_WINDOWS = [7, 30, 90, 365];
127+
const DEFAULT_WINDOWS = [7, 15, 30];
128128

129129
// Serializes per-file state into a hidden HTML comment appended to the comment
130130
// body. Stage 1 reads this on the next push to decide which files need
@@ -133,16 +133,27 @@ function buildStateBlock(state: CommentState): string {
133133
return `${STATE_MARKER} ${JSON.stringify(state)} -->`;
134134
}
135135

136+
// Builds the table (or an empty-state fallback line) for the "Run history
137+
// flaky detection" section. tableFiles is the union of historically-flaky
138+
// files and files carrying an AI finding — see buildCommentBody — so an
139+
// empty list here only happens if that union itself is empty, which is a
140+
// rare safety fallback rather than the common case.
136141
function buildHistoryTable(
137-
flakyFiles: HistoryFile[],
142+
tableFiles: HistoryFile[],
138143
windows: number[],
139144
runsSampled: WindowCounts,
140145
): string {
141-
if (flakyFiles.length === 0) return '';
146+
if (tableFiles.length === 0) {
147+
const windowKeys = windows.map((d) => `${d}d`);
148+
const noRunsSampled = windowKeys.every((key) => !runsSampled[key]);
149+
return noRunsSampled
150+
? 'No previous run to analyse for these tests.'
151+
: 'No historical failures found for the changed tests in the sampled runs.';
152+
}
142153
const windowKeys = windows.map((d) => `${d}d`);
143154
const header = `| File | ${windowKeys.join(' | ')} |`;
144155
const divider = `|---|${windowKeys.map(() => '---|').join('')}`;
145-
const rows = flakyFiles
156+
const rows = tableFiles
146157
.map((f) => {
147158
// `failures/runs` — failures for the file over the number of countable
148159
// runs sampled in that window.
@@ -152,7 +163,7 @@ function buildHistoryTable(
152163
return `| \`${f.path}\` | ${cells} |`;
153164
})
154165
.join('\n');
155-
return `### Historical CI failures on main\n\nFailures / runs sampled per window (nested — a failure in 7d is also counted in 30d/90d/365d):\n\n${header}\n${divider}\n${rows}\n`;
166+
return `Failures / runs sampled per window:\n\n${header}\n${divider}\n${rows}\n`;
156167
}
157168

158169
function buildFindingsSection(findings: Finding[]): string {
@@ -199,19 +210,27 @@ function buildCommentBody({
199210
runsSampled: WindowCounts;
200211
stateBlock: string;
201212
}): string {
202-
const flakyFiles = historyFiles.filter((f) => f.flaky);
203-
const historyTable = buildHistoryTable(flakyFiles, windows, runsSampled);
213+
// A file surfaces in the run-history table if it's historically flaky OR
214+
// an AI finding calls it out — otherwise an AI-only finding (zero
215+
// historical failures) would make the table disappear even though the
216+
// finding itself renders.
217+
const findingFiles = new Set(findings.map((f) => f.file));
218+
const tableFiles = historyFiles.filter((f) => f.flaky || findingFiles.has(f.path));
219+
const historyTable = buildHistoryTable(tableFiles, windows, runsSampled);
204220
const findingsSection = buildFindingsSection(findings);
205221

206222
return `${MARKER}
207223
## 🧪 Flaky unit test detection
208224
209-
${historyTable}
225+
### Run history flaky detection
226+
210227
[View recent run history](${runHistoryUrl})
211228
212-
${findingsSection}
213229
Historical failure rate is a hint, not proof — review each suggestion in context. See the [flaky-test-detection skill](${SKILL_LINK}) for the full pattern reference and manual audit workflow.
214230
231+
${historyTable}
232+
233+
${findingsSection}
215234
_This check is informational only and does not block merging._
216235
${stateBlock}`;
217236
}

0 commit comments

Comments
 (0)