You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The examples are smoke-gated rigorously, but the templates and snippets, the parts users copy most directly, are not. Smoke runs a copy of the headless template rather than the shipped file. Nothing keeps the two identical, so a regression in the shipped template passes CI. The extension add-on template is never loaded into Blender at all.
Evidence
.github/workflows/blender-smoke.yml:157-164 runs tests/smoke/tmpl_gltf.py. Today it is byte-identical to templates/headless-batch-script-template/script.py (verified with diff -q), but no check enforces that.
tests/smoke/run_smoke.py:7 claims the copies catch drift. Because nothing compares them, they hide it.
tests/smoke/tmpl_render.py:1 is a "Reproduction of the headless-batch-scripting SKILL worked example", another hand-maintained copy.
validate.yml:116-131 and :162-176: the 27 snippets and all template .py files only get py_compile. A snippet that calls a removed API compiles fine. See the shader-node-group inputs.new issue for a live example.
templates/extension-addon-template/ (__init__.py, blender_manifest.toml) is never installed, registered or unregistered in any Blender run.
templates/ai-asset-pipeline-template/: confirm whether it is smoke-run directly or also through a copy.
Suggested approach
Point the smoke step at templates/headless-batch-script-template/script.py directly and delete tests/smoke/tmpl_gltf.py. If a harness wrapper is needed, runpy the shipped file.
Add a smoke step that runs blender --command extension validate templates/extension-addon-template, then installs and enables it headless. Assert that register() adds the operator, panel and Scene pointer, and that unregister() removes them.
Longer term, give each snippet a minimal tests/smoke/catalog.json row, or one run_snippets.py that imports each snippet and calls its entry point on a factory-startup scene. Generalize the smoke harness to per-snippet coverage + emit a coverage table #30 closed the harness-generalisation idea; this is the missing coverage it was meant to deliver.
Done when
No hand-copied template lives under tests/smoke/.
The extension template is validated, registered and unregistered in CI on 5.2 and 4.5, with a falsifier: break unregister() symmetry and observe red.
Why it matters
The examples are smoke-gated rigorously, but the templates and snippets, the parts users copy most directly, are not. Smoke runs a copy of the headless template rather than the shipped file. Nothing keeps the two identical, so a regression in the shipped template passes CI. The extension add-on template is never loaded into Blender at all.
Evidence
.github/workflows/blender-smoke.yml:157-164runstests/smoke/tmpl_gltf.py. Today it is byte-identical totemplates/headless-batch-script-template/script.py(verified withdiff -q), but no check enforces that.tests/smoke/run_smoke.py:7claims the copies catch drift. Because nothing compares them, they hide it.tests/smoke/tmpl_render.py:1is a "Reproduction of the headless-batch-scripting SKILL worked example", another hand-maintained copy.validate.yml:116-131and:162-176: the 27 snippets and all template.pyfiles only getpy_compile. A snippet that calls a removed API compiles fine. See the shader-node-groupinputs.newissue for a live example.templates/extension-addon-template/(__init__.py,blender_manifest.toml) is never installed, registered or unregistered in any Blender run.templates/ai-asset-pipeline-template/: confirm whether it is smoke-run directly or also through a copy.Suggested approach
templates/headless-batch-script-template/script.pydirectly and deletetests/smoke/tmpl_gltf.py. If a harness wrapper is needed,runpythe shipped file.blender --command extension validate templates/extension-addon-template, then installs and enables it headless. Assert thatregister()adds the operator, panel andScenepointer, and thatunregister()removes them.tests/smoke/catalog.jsonrow, or onerun_snippets.pythat imports each snippet and calls its entry point on a factory-startup scene. Generalize the smoke harness to per-snippet coverage + emit a coverage table #30 closed the harness-generalisation idea; this is the missing coverage it was meant to deliver.Done when
tests/smoke/.unregister()symmetry and observe red.