chore(compat): land closeout — pinned cosign + JSON-only diff + minrows floor
All checks were successful
addon-qualify / qualify (push) Successful in 12s
All checks were successful
addon-qualify / qualify (push) Successful in 12s
This commit is contained in:
@@ -52,7 +52,6 @@ ERROR_CLASS_MAP = {
|
||||
'app-name': 'settings-page-broken',
|
||||
'menu-icon': 'menu-icon-missing',
|
||||
'hoot-import': 'bundle-module-missing',
|
||||
'webpack-name': 'bundle-module-missing',
|
||||
'webpack-chunk': 'bundle-module-missing',
|
||||
}
|
||||
|
||||
@@ -135,13 +134,16 @@ def build_rows(qualifier_results: list[dict],
|
||||
Skips addons whose manifest didn't parse (no addonVersion) — the
|
||||
matrix needs both code and version to be useful, and we'd rather
|
||||
drop a row than seed it with empty strings the aggregator would
|
||||
later have to special-case.
|
||||
later have to special-case. Dropped addons are reported on stderr
|
||||
so a regression in one __manifest__.py is visible (M4 fix).
|
||||
"""
|
||||
rows: list[dict] = []
|
||||
dropped: list[str] = []
|
||||
for r in qualifier_results:
|
||||
code = r['addon']
|
||||
version, odoo_major = manifests.get(code, ('', ''))
|
||||
if not version or not odoo_major:
|
||||
dropped.append(code)
|
||||
continue
|
||||
pg_major = pg_by_major.get(odoo_major, '')
|
||||
if r.get('qualified'):
|
||||
@@ -162,6 +164,10 @@ def build_rows(qualifier_results: list[dict],
|
||||
rows.append(row)
|
||||
rows.sort(key=lambda r: (r['addonCode'], r['addonVersion'],
|
||||
r['odooMajor'], r['postgresMajor']))
|
||||
if dropped:
|
||||
sys.stderr.write(
|
||||
f'WARN: {len(dropped)} addon(s) dropped (manifest unparseable or version unrecognised): '
|
||||
+ ', '.join(dropped) + '\n')
|
||||
return rows
|
||||
|
||||
|
||||
@@ -187,6 +193,9 @@ def main(argv: list[str]) -> int:
|
||||
help='JSON map: odoo_major → recommended postgres_major')
|
||||
p.add_argument('--source', type=str, default='qualify-addon-v1',
|
||||
help='source identifier persisted in compat_seed_stamps.source')
|
||||
p.add_argument('--min-rows', type=int, default=0,
|
||||
help='minimum row count; emit failure exits non-zero (M2 sanity floor). '
|
||||
'Set per-major to catch silent qualifier breakage that would ship an empty seed.')
|
||||
args = p.parse_args(argv[1:])
|
||||
|
||||
if not args.addons_root.is_dir():
|
||||
@@ -207,6 +216,17 @@ def main(argv: list[str]) -> int:
|
||||
qualifier_results = run_qualifier(args.qualifier, addon_dirs)
|
||||
rows = build_rows(qualifier_results, manifests, pg_by_major)
|
||||
|
||||
# M2 — refuse to ship a suspiciously small bootstrap. Caller picks
|
||||
# the floor based on expected catalog size; matching the floor with
|
||||
# one safety margin (e.g. branch has 10 addons → --min-rows 8)
|
||||
# catches "qualifier crashed mid-pass" without flapping on legit
|
||||
# one-or-two-addon removals.
|
||||
if args.min_rows > 0 and len(rows) < args.min_rows:
|
||||
sys.stderr.write(
|
||||
f'ERROR: produced {len(rows)} rows, expected at least {args.min_rows} — '
|
||||
'refusing to ship a thin bootstrap (set --min-rows lower if catalog has shrunk)\n')
|
||||
return 2
|
||||
|
||||
# No generatedAt field — it would change every run and defeat the
|
||||
# workflow's "git diff --quiet → no commit" idempotency. The git
|
||||
# commit timestamp + stampId in commit message carry the same info.
|
||||
|
||||
Reference in New Issue
Block a user