Skip to content

ci: add Blender smoke-test workflow (runs examples in real Blender)#10

Merged
TMHSDigital merged 2 commits into
mainfrom
ci/blender-smoke-test
Jun 19, 2026
Merged

ci: add Blender smoke-test workflow (runs examples in real Blender)#10
TMHSDigital merged 2 commits into
mainfrom
ci/blender-smoke-test

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Summary

Adds a durable gate that executes the snippets' and skills' headline examples inside real Blender — headless, on the current stable (5.1.x) and active LTS (4.5.x) — and fails on any error or empty-output assertion. Every real bug this cycle (EEVEE-id inversion, slotted-actions boundary, driver TypeError, dead SDF link) passed py_compile and only surfaced by running in Blender; this closes that gap.

Adds only new files — no existing workflow touched, no shipped content changed, counts unchanged (12/6/2/17):

  • .github/workflows/blender-smoke.yml
  • tests/smoke/run_smoke.py (in-process content checks, self-contained — copies example code, does not import skills/snippets)
  • tests/smoke/{tmpl_gltf.py,tmpl_render.py,make_input.py} (template fixtures)

What it asserts (CONTENT, not "no exception")

  • F1 driver: attaches AND location.z strictly increases across frames.
  • F2 SDF remesh: GridToMesh link is valid AND yields >0 vertices.
  • EEVEE: version-branch helper assigns the id that exists on this build (the inversion guard); a 1-frame render is non-black (EEVEE where a GPU exists, else Cycles fallback — runner-safe).
  • slotted actions: correct branch per version; legacy action.fcurves present on 4.5 / AttributeError on 5.x.
  • save_pre: handler arg is a filepath string. mesh: foreach roundtrip; SUBSURF eval vcount > base.
  • templates (subprocess): glTF exit 0 + valid .glb; no-mesh exit 2; render exit 0.

The driver exits non-zero naming the first failing example — including on any unhandled exception, since blender --background otherwise exits 0 after printing a traceback (the documented headless gotcha).

Triggers & matrix

workflow_dispatch + weekly schedule (Mon 07:00 UTC) + pull_request on main (gates future example changes). Matrix resolves the latest 5.1.x and 4.5.x point release from download.blender.org and fails loudly if a build can't be fetched; a version guard asserts the downloaded build matches the matrix series. timeout-minutes: 30.

Verification (done before this PR)

  • Local green, both builds: ALL SMOKE CHECKS PASSED exit 0 on Blender 5.1.1 and 4.5.10 LTS, plus glTF exit 0 / no-mesh exit 2 / render exit 0.
  • Gate proven to bite: reverting F1's id_type='SCENE' in a scratch copy →
    SMOKE FAILED: unhandled TypeError in 'smoke_driver' ... DriverTarget.id expected a Object type, not Scene, exit 1.
  • This PR's own blender-smoke run (which downloads real Blender on the runner) is the on-runner confirmation.

Release interaction

Per release.yml (no paths filter, patch-default), a .github/-only push to main would cut a release. This adds no shipped content and warrants no version bump, so I will squash-merge with [skip ci] (option b) so no release is cut. release.yml itself is left unchanged (separate decision).

🤖 Generated with Claude Code

py_compile cannot catch API-level regressions (EEVEE-id inversion, slotted-actions boundary, driver TypeError, dead SDF link) -- all passed py_compile and only surfaced by running in real Blender. Adds .github/workflows/blender-smoke.yml (workflow_dispatch + weekly schedule + pull_request on main) matrixed over the current stable (5.1.x) and active LTS (4.5.x), resolving the latest point release from download.blender.org and failing loudly if a build can't be fetched. A self-contained driver (tests/smoke/run_smoke.py) executes the headline examples and asserts CONTENT (driver evaluates; SDF GridToMesh yields >0 verts; EEVEE id assigns + non-black render; slotted branch per version; save_pre arg is a filepath; foreach roundtrip; SUBSURF eval>base) and exits non-zero naming the first failing example -- including on any unhandled exception, since Blender otherwise exits 0 on a traceback. Both headless templates run as subprocesses (glTF exit 0 + valid .glb; no-mesh exit 2; render exit 0). Verified locally on 4.5.10 LTS and 5.1.1 green, and proven to fail (exit 1) when F1's id_type fix is reverted. No shipped content changed; counts unchanged (12/6/2/17).

Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
@github-actions github-actions Bot added the ci label Jun 19, 2026
Runner fix: GPU-less GitHub runners abort EEVEE GPU rendering with a C-level core dump (libEGL.so.1 missing, exit 134) that Python try/except cannot catch. Install Blender's GL runtime libs + xvfb and run Blender under xvfb-run; render the non-black frame with Cycles (CPU) instead of EEVEE. Gate fix: keep a dedicated, frame-independent EEVEE engine-id assertion (eevee-engine-id-assigns) that compares the helper's id against the version-expected id (BLENDER_EEVEE on 5.x, BLENDER_EEVEE_NEXT on 4.2-4.5) so the polarity bug (CRITICAL #1) stays guarded even though rendering is Cycles. Verified: green on 5.1.1 and 4.5.10; re-inverting get_eevee_engine_id() makes eevee-engine-id-assigns FAIL (exit 1) on both builds (enum not found).

Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
@TMHSDigital TMHSDigital merged commit 9ad35cd into main Jun 19, 2026
8 checks passed
@TMHSDigital TMHSDigital deleted the ci/blender-smoke-test branch June 19, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant