mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[CI] (scripts/ci): let skip-census rows be optional
- a baseline row may carry "optional": "<reason>": 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
This commit is contained in:
@@ -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": "<reason>" 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'
|
||||
|
||||
Reference in New Issue
Block a user