Public: anyone can read this; the crew can change it.

A pure read names the tests failing on three or more open pulls: a clash between pulls, not separate bugs #6558

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/6551-a-pure-read-names-the-tests-failing-on-t → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/6551-a-pure-read-names-the-tests-failing-on-t was merged into main as 51adf09.

Review

Sign in to review this change.
2 files changed +68 −0
src/flow/shared_red.ts added +41
@@ -0,0 +1,41 @@
1 /**
2 * Shared red (#6551): a test failing on three or more open pulls is a clash
3 * between pulls, not separate bugs; name it once so the pulls are re-checked
4 * together after the fix. Pure: rows in, rows out.
5 */
6
7 export const SHARED_RED_PULLS = 3;
8
9 export interface RedRow {
10 readonly pull: number;
11 readonly failingTests: readonly string[];
12 }
13
14 export interface SharedRed {
15 readonly test: string;
16 readonly pulls: number[];
17 }
18
19 /** Tests failing on at least three distinct pulls, most pulls first, ties by test name. */
20 export function sharedRed(rows: readonly RedRow[]): SharedRed[] {
21 const byTest = new Map<string, Set<number>>();
22 for (const row of rows) {
23 for (const test of row.failingTests) {
24 let pulls = byTest.get(test);
25 if (!pulls) byTest.set(test, (pulls = new Set()));
26 pulls.add(row.pull);
27 }
28 }
29 const out: SharedRed[] = [];
30 for (const [test, pulls] of byTest) {
31 if (pulls.size >= SHARED_RED_PULLS) out.push({ test, pulls: [...pulls].sort((a, b) => a - b) });
32 }
33 return out.sort((a, b) => b.pulls.length - a.pulls.length || (a.test < b.test ? -1 : a.test > b.test ? 1 : 0));
34 }
35
36 /** One sentence per shared test; empty when none. */
37 export function sharedRedSays(rows: readonly RedRow[]): string[] {
38 return sharedRed(rows).map(

Sentence says only the count; once wired, a person needs the pull numbers too (s.pulls is right there). Consider appending them in the caller, not here, to keep the issue's wording.

39 (s) => `${s.test} fails on ${s.pulls.length} pulls: one clash, re-check together after the fix`,
40 );
41 }
test/flow-shared-red.test.ts added +27
@@ -0,0 +1,27 @@
1 import { expect, test } from "bun:test";
2 import { sharedRed, sharedRedSays } from "../src/flow/shared_red.ts";
3
4 const r = (pull: number, ...failingTests: string[]) => ({ pull, failingTests });
5
6 test("below the threshold nothing is shared", () => {
7 expect(sharedRed([r(1, "a"), r(2, "a")])).toEqual([]);
8 expect(sharedRedSays([r(1, "a"), r(2, "a")])).toEqual([]);
9 });
10
11 test("at the threshold a test is named with its pulls", () => {
12 expect(sharedRed([r(3, "a"), r(1, "a"), r(2, "a", "b")])).toEqual([{ test: "a", pulls: [1, 2, 3] }]);
13 });
14
15 test("most pulls first, ties by name", () => {
16 const rows = [r(1, "z", "b"), r(2, "z", "b"), r(3, "z", "b"), r(4, "z")];
17 expect(sharedRed(rows).map((s) => s.test)).toEqual(["z", "b"]);
18 });
19
20 test("a pull counts once per test", () => {
21 expect(sharedRed([r(1, "a", "a"), r(1, "a"), r(2, "a")])).toEqual([]);
22 });
23
24 test("says the clash", () => {
25 const rows = [r(1, "size"), r(2, "size"), r(3, "size")];
26 expect(sharedRedSays(rows)).toEqual(["size fails on 3 pulls: one clash, re-check together after the fix"]);
27 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs