From 72e7d64c2b925e75a0467511f0e02a100060b8b5 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 17 Oct 2026 13:07:34 -0400 Subject: [PATCH] [CI] (scripts/ci): let skip-census rows be optional - a baseline row may carry "optional": "": the lane's absence is a note, and when it runs it is checked like any other lane - write keeps an optional row (names resolved) when the run did not produce that lane, and keeps the reason on rows it rewrites - self-test: an absent optional lane is green, a present one with a new skip is red, a plain lane stays required --- scripts/ci/skip_census.py | 43 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/scripts/ci/skip_census.py b/scripts/ci/skip_census.py index b2bde5d6..af0ce252 100644 --- a/scripts/ci/skip_census.py +++ b/scripts/ci/skip_census.py @@ -21,7 +21,10 @@ into the tree (scripts/data/skip_census_baseline.json): the lane is missing entirely, which is reported on its own line; * a skip that turned into a pass is reported, never red - rewrite the baseline in the commit that earns it so the improvement is locked in; - * new lanes and new names are reported, never red. + * new lanes and new names are reported, never red; + * a lane whose row carries "optional": "" runs only on some paths (for example only when + a build-equality guard falls back); its absence is a note, and when it runs it is checked + like any other lane. A deliberate retirement edits the baseline in the same commit and names the cases in the commit message (PLAN-P13 ยง4.2). @@ -110,14 +113,34 @@ def resolve_baseline(baseline): names = row['names'] if 'names' in row else baseline[row['names_from']]['names'] resolved[lane] = {'names': sorted({normalize_name(n) for n in names}), 'skipped': sorted({normalize_name(n) for n in row['skipped']})} + if row.get('optional'): + resolved[lane]['optional'] = row['optional'] return resolved +def keep_optional_rows(written, previous): + """`write` from a run that did not run an optional lane keeps that lane's row, with its names + resolved, and every optional row keeps its reason.""" + resolved = resolve_baseline(previous) + for lane, row in previous.items(): + if not row.get('optional'): + continue + if lane in written: + written[lane]['optional'] = row['optional'] + else: + written[lane] = {'skipped': resolved[lane]['skipped'], 'names': resolved[lane]['names'], + 'optional': row['optional']} + return dict(sorted(written.items())) + + def compare(lanes, baseline): red, info = [], [] for lane, known in sorted(baseline.items()): current = lanes.get(lane) if current is None: + if known.get('optional'): + info.append(f"lane {lane}: not run (optional: {known['optional']})") + continue red.append(f'lane {lane}: no JUnit at all in this run (the job did not run or did not upload)') continue allowed = set(known['skipped']) @@ -158,8 +181,11 @@ def run(argv): if args.report: args.report.write_text(json.dumps(to_baseline(lanes), indent=1) + '\n') if args.command == 'write': + written = to_baseline(lanes) + if args.baseline.exists(): + written = keep_optional_rows(written, json.loads(args.baseline.read_text())) args.baseline.parent.mkdir(parents=True, exist_ok=True) - args.baseline.write_text(json.dumps(to_baseline(lanes), indent=1) + '\n') + args.baseline.write_text(json.dumps(written, indent=1) + '\n') print(f'wrote {args.baseline}') return 0 if not args.baseline.exists(): @@ -215,6 +241,19 @@ def self_test(): junit(lost / 'junit-other' / 'other.xml', [('A', 'pass')]) assert quiet(['check', str(lost), '--baseline', str(base)]) == 1, 'a lane that vanished must be red' assert quiet(['check', str(tmp / 'empty'), '--baseline', str(base)]) == 1, 'no JUnit must be red' + # An optional lane: absent is a note, present is checked, and a plain lane stays required. + optional = tmp / 'optional.json' + rows = json.loads(base.read_text()) + rows['junit-other/other'] = {'skipped': [], 'names': ['A'], 'optional': 'runs on the fallback only'} + optional.write_text(json.dumps(rows)) + assert quiet(['check', str(good), '--baseline', str(optional)]) == 0, 'an absent optional lane is a note' + both = tmp / 'both' + junit(both / 'junit-unit' / 'unit.xml', [('A', 'pass'), ('B', 'skip'), ('C', 'pass')]) + junit(both / 'junit-other' / 'other.xml', [('A', 'skip')]) + assert quiet(['check', str(both), '--baseline', str(optional)]) == 1, 'a present optional lane is checked' + assert quiet(['check', str(lost), '--baseline', str(optional)]) == 1, 'a plain lane is still required' + kept = keep_optional_rows(to_baseline(collect(good)), rows) + assert kept['junit-other/other'] == rows['junit-other/other'], 'write keeps an absent optional row' assert quiet(['check', str(good), '--baseline', str(tmp / 'none.json')]) == 1, 'no baseline must be red' assert normalize_name('S/T.Case/Leaf # GetParam() = 64-byte object <46-CA 08-EB>') == 'S/T.Case/Leaf' assert normalize_name('T.Plain') == 'T.Plain'