Skip to content

Commit 449101a

Browse files
TMHSDigitalclaude
andcommitted
fix(smoke): version-gate the four falsifiers that target a 5.2-only API change
The first 4.5 legs with catalog falsifiers (#320) went red on exactly four rows: vse-linear-modifiers --assume-present, gn-socket-rename --legacy-ids, eval-mesh-datablock-name --assume-distinct-names and mesh-automasking-settings --assume-brush-attrs exited 0 instead of 4/5/6/5. That is their documented contract: each fakes the pre-5.2 API, so it can only fail where 5.2 removed or renamed it, and each README's measurement table records exit 0 on 4.5.11 and 5.1.2. The local seeding ran only on 5.2.1. - Falsifier entries accept "min_version"; run_catalog records a falsifier SKIP (with the reason) below it instead of launching Blender. - The four entries get "min_version": "5.2"; check_smoke_catalog validates the field; test_harness covers run-at-floor and skip-below-floor. - CLAUDE.md documents the field. Proof (local, .scratch/blender-4.5.11-windows-x64, --series 4.5): the four rows PASS their happy paths and SKIP the falsifier with the reason; anvil and farm-tractor falsifiers still run and PASS (exit 9). CI's other failed 4.5 leg (60506e8) had the same four failures and no others. Refs #320 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 08c6672 commit 449101a

5 files changed

Lines changed: 35 additions & 5 deletions

File tree

‎CLAUDE.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ The host runner is `tests/smoke/run_example.py`. Shipped examples are listed in
179179
- **Falsifiers in CI:** every catalog row carries `falsifiers`, at least one
180180
`{"args": [...], "expect_exit": N}` (N not 0, 1 or 77) or, for a contract
181181
the sidecar check owns, `{"args": [...], "expect_sidecar_fail": true}`.
182+
A falsifier that targets a version-specific API change takes
183+
`"min_version": "5.2"` and is recorded as SKIP below it (its README must
184+
say it exits 0 there).
182185
`run_catalog.py` runs each after the row's happy path; it passes only on
183186
exactly that exit. `tests/check_smoke_catalog.py` rejects a row without one
184187
and any unknown key. The weekly cron also runs the full showcase sweep

‎tests/check_smoke_catalog.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import argparse
2323
import json
24+
import re
2425
import sys
2526
from pathlib import Path
2627

@@ -29,7 +30,7 @@
2930

3031
ROW_KEYS = {"name", "script", "args", "min_version", "expect_file",
3132
"expect_sidecar", "sidecar_contains", "falsifiers"}
32-
FALSIFIER_KEYS = {"args", "expect_exit", "expect_sidecar_fail"}
33+
FALSIFIER_KEYS = {"args", "expect_exit", "expect_sidecar_fail", "min_version"}
3334
FORBIDDEN_EXITS = {0, 1, 77}
3435

3536

@@ -62,6 +63,9 @@ def check_schema(row: dict) -> list[str]:
6263
errors.append(f"{where}: expect_exit {code!r} must be an int other than 0, 1, 77")
6364
elif not row.get("expect_sidecar"):
6465
errors.append(f"{where}: expect_sidecar_fail on a row with no expect_sidecar")
66+
mv = f.get("min_version")
67+
if mv is not None and not (isinstance(mv, str) and re.fullmatch(r"[0-9]+[.][0-9]+", mv)):
68+
errors.append(f"{where}: min_version {mv!r} must look like '5.2'")
6569
return errors
6670

6771

‎tests/smoke/catalog.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@
7979
{"name": "unapplied-scale-gltf", "script": "examples/unapplied-scale-gltf/unapplied_scale_gltf.py", "falsifiers": [{"args": ["--identity"], "expect_exit": 3}]},
8080
{"name": "coincident-vert-weld", "script": "examples/coincident-vert-weld/coincident_vert_weld.py", "falsifiers": [{"args": ["--no-duplicate"], "expect_exit": 3}]},
8181
{"name": "bake-normal-high-to-low", "script": "examples/bake-normal-high-to-low/bake_normal_high_to_low.py", "falsifiers": [{"args": ["--flat-source"], "expect_exit": 5}]},
82-
{"name": "vse-linear-modifiers", "script": "examples/vse-linear-modifiers/vse_linear_modifiers.py", "falsifiers": [{"args": ["--assume-present"], "expect_exit": 4}]},
83-
{"name": "gn-socket-rename", "script": "examples/gn-socket-rename/gn_socket_rename.py", "falsifiers": [{"args": ["--legacy-ids"], "expect_exit": 5}]},
84-
{"name": "eval-mesh-datablock-name", "script": "examples/eval-mesh-datablock-name/eval_mesh_datablock_name.py", "falsifiers": [{"args": ["--assume-distinct-names"], "expect_exit": 6}]},
85-
{"name": "mesh-automasking-settings", "script": "examples/mesh-automasking-settings/mesh_automasking_settings.py", "falsifiers": [{"args": ["--assume-brush-attrs"], "expect_exit": 5}]},
82+
{"name": "vse-linear-modifiers", "script": "examples/vse-linear-modifiers/vse_linear_modifiers.py", "falsifiers": [{"args": ["--assume-present"], "expect_exit": 4, "min_version": "5.2"}]},
83+
{"name": "gn-socket-rename", "script": "examples/gn-socket-rename/gn_socket_rename.py", "falsifiers": [{"args": ["--legacy-ids"], "expect_exit": 5, "min_version": "5.2"}]},
84+
{"name": "eval-mesh-datablock-name", "script": "examples/eval-mesh-datablock-name/eval_mesh_datablock_name.py", "falsifiers": [{"args": ["--assume-distinct-names"], "expect_exit": 6, "min_version": "5.2"}]},
85+
{"name": "mesh-automasking-settings", "script": "examples/mesh-automasking-settings/mesh_automasking_settings.py", "falsifiers": [{"args": ["--assume-brush-attrs"], "expect_exit": 5, "min_version": "5.2"}]},
8686
{"name": "ray-cast-space", "script": "examples/ray-cast-space/ray_cast_space.py", "falsifiers": [{"args": ["--world-to-object"], "expect_exit": 4}]},
8787
{"name": "lattice-deform", "script": "examples/lattice-deform/lattice_deform.py", "falsifiers": [{"args": ["--bspline"], "expect_exit": 4}]},
8888
{"name": "solidify-even-thickness", "script": "examples/solidify-even-thickness/solidify_even_thickness.py", "falsifiers": [{"args": ["--no-even"], "expect_exit": 4}]},

‎tests/smoke/run_catalog.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import sys
2020

2121
HERE = os.path.dirname(os.path.abspath(__file__))
22+
sys.path.insert(0, HERE)
23+
from protocol import parse_version # noqa: E402
24+
from run_example import append_status # noqa: E402
2225

2326

2427
def main(argv=None):
@@ -101,6 +104,16 @@ def row_cmd(item, run_name, extra, falsifier=None):
101104
for fz in item.get("falsifiers") or []:
102105
fargs = [a.replace("$OUT", args.out) for a in fz["args"]]
103106
label = f"{name} [falsifier {' '.join(fz['args'])}]"
107+
floor = fz.get("min_version")
108+
if floor and parse_version(args.series) < parse_version(floor):
109+
# A falsifier that targets a version-specific API change has
110+
# nothing to break below it (its README records exit 0 there).
111+
detail = f"falsifier applies from Blender {floor}; this is {args.series}"
112+
print(f"[SKIP] {label}: {detail}", flush=True)
113+
if args.status:
114+
append_status(args.status, {"name": label, "status": "SKIP",
115+
"detail": detail, "falsifier": True})
116+
continue
104117
n_falsifiers += 1
105118
print(f"::group::{label}", flush=True)
106119
fcode = subprocess.call(row_cmd(item, label, base_args + fargs, fz))

‎tests/smoke/test_harness.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,16 @@ def test_failing_falsifier_is_red(self):
298298
self.assertEqual(code, 1)
299299
self.assertIn("a [falsifier --break]", err)
300300

301+
def test_falsifier_below_its_min_version_is_skipped(self):
302+
rows = [{"name": "a", "script": "a.py",
303+
"falsifiers": [{"args": ["--new-api"], "expect_exit": 4,
304+
"min_version": "5.2"}]}]
305+
code, seen, _ = self._run(rows, {}) # _run uses --series 5.2: runs
306+
self.assertEqual(seen, ["a", "a [falsifier --new-api]", "expect 4"])
307+
rows[0]["falsifiers"][0]["min_version"] = "9.9"
308+
code, seen, _ = self._run(rows, {})
309+
self.assertEqual((code, seen), (0, ["a"]))
310+
301311
def test_no_falsifiers_flag(self):
302312
rows = [{"name": "a", "script": "a.py",
303313
"falsifiers": [{"args": ["--break"], "expect_exit": 4}]}]

0 commit comments

Comments
 (0)