From b6c92281c33273c628bb34e86b2314da29e8db4c Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Sat, 12 Sep 2026 07:31:53 -0400 Subject: [PATCH 1/4] ci: add opt-in 5.1 smoke via needs-5.1 and dispatch Default PR matrix stays 4.5 and 5.2. labeled is required so the label actually starts a job. Dispatch takes a series input. Monday cron is unchanged. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor --- .github/workflows/blender-smoke.yml | 59 +++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/.github/workflows/blender-smoke.yml b/.github/workflows/blender-smoke.yml index aed52e3..3c4cf66 100644 --- a/.github/workflows/blender-smoke.yml +++ b/.github/workflows/blender-smoke.yml @@ -2,37 +2,88 @@ name: Blender Smoke Test # Executes the snippets' and skills' headline examples inside REAL Blender, headless, # on the current stable (5.2.x LTS) and the fallback LTS (4.5.x) on every PR, -# plus 5.1.x on the weekly cron, and fails on any error or +# plus 5.1.x on the weekly cron, the opt-in `needs-5.1` PR label, or a +# workflow_dispatch series input, and fails on any error or # empty-output assertion. Shipped examples go through tests/smoke/run_example.py # (catalog.json): SKIP is exit 77 + SMOKE_SKIP below --min-version, never exit 0. # Post-exit sidecars are opt-in. A leg with zero PASSes is red. # py_compile (in validate.yml) cannot catch API-level regressions # like the EEVEE-id inversion, the slotted-actions boundary, the driver TypeError, or the # dead SDF link -- this gate runs the code so those surface in CI, not in users' files. +# +# Default PR matrix stays 5.2 + 4.5. `labeled` is in pull_request.types so +# applying `needs-5.1` starts a 5.1 job; other labels are ignored and must +# not cancel an in-progress default run. Auto-label does not apply needs-5.1. +# Manual dispatch: Actions > Blender Smoke Test > Run workflow > pick series. on: - workflow_dispatch: {} + workflow_dispatch: + inputs: + series: + description: Blender series to smoke (single version, on-demand) + required: true + type: choice + options: + - "5.2" + - "5.1" + - "4.5" + default: "5.2" schedule: - cron: "0 7 * * 1" # weekly, Monday 07:00 UTC pull_request: branches: [main] + types: [opened, synchronize, reopened, labeled] permissions: contents: read concurrency: - group: blender-smoke-${{ github.ref }} + # Isolate labeled runs so auto-label (`ci`, `documentation`, ...) does not + # cancel the default 4.5/5.2 jobs. synchronize still cancels the previous + # synchronize on the same PR. + group: blender-smoke-${{ github.event.pull_request.number || github.ref }}${{ github.event.action == 'labeled' && format('-label-{0}', github.event.label.name) || '' }} cancel-in-progress: true jobs: + resolve-matrix: + name: Resolve smoke matrix + runs-on: ubuntu-latest + if: github.event.action != 'labeled' || github.event.label.name == 'needs-5.1' + outputs: + series: ${{ steps.set.outputs.series }} + steps: + - id: set + env: + EVENT_NAME: ${{ github.event_name }} + EVENT_ACTION: ${{ github.event.action }} + DISPATCH_SERIES: ${{ github.event.inputs.series }} + PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }} + run: | + set -euo pipefail + if [ "$EVENT_NAME" = "schedule" ]; then + json='["5.2","5.1","4.5"]' + elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then + json=$(printf '["%s"]' "$DISPATCH_SERIES") + elif [ "$EVENT_ACTION" = "labeled" ]; then + json='["5.1"]' + elif echo ",$PR_LABELS," | grep -q ",needs-5.1,"; then + json='["5.2","5.1","4.5"]' + else + json='["5.2","4.5"]' + fi + echo "series=$json" >> "$GITHUB_OUTPUT" + echo "Smoke matrix: $json" + smoke: name: Blender ${{ matrix.series }} smoke + needs: resolve-matrix + if: needs.resolve-matrix.result == 'success' runs-on: ubuntu-latest timeout-minutes: 45 strategy: fail-fast: false matrix: - series: ${{ github.event_name == 'schedule' && fromJSON('["5.2","5.1","4.5"]') || fromJSON('["5.2","4.5"]') }} + series: ${{ fromJSON(needs.resolve-matrix.outputs.series) }} steps: - uses: actions/checkout@v7 From db52126bf4d064c61dcfe8df9bd60c64a1738576 Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Sat, 12 Sep 2026 07:31:54 -0400 Subject: [PATCH 2/4] docs: document the 5.1 smoke lever for contributors Place the how-to in CONTRIBUTING.md, where version targeting already lives, and point at it from the workflow header, README, AGENTS.md, and the PR template. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- AGENTS.md | 5 ++++- CLAUDE.md | 2 +- CONTRIBUTING.md | 13 +++++++++++++ README.md | 4 ++-- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ccdb85a..aeeab41 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,7 +17,7 @@ Label every claim. - **live-run-proven:** exact binary path + the version that binary printed (`blender --version`). Headless harness only. Live MCP does not count. - **inspection-only:** read the skill / diff / RNA docs; no process ran. -`blender-smoke.yml` has no `push` trigger. Post-merge smoke evidence is the PR-head 5.2 + 4.5 jobs (state the versions from those logs). +`blender-smoke.yml` has no `push` trigger. Post-merge smoke evidence is the PR-head 5.2 + 4.5 jobs (state the versions from those logs). Apply `needs-5.1` when 5.1 must be CI-proven on the PR; default matrix does not include it. ## Release-owned fields — do not hand-edit diff --git a/AGENTS.md b/AGENTS.md index 7ce0ebd..aaef214 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -157,7 +157,10 @@ way, and a one-paragraph rationale. 30 to 80 lines is the right size. the manifest `version` line (see `release.yml` below) — never hand-edit it. - `blender-smoke.yml` executes every shipped example (check-only, no render) plus snippet/template smoke tests inside REAL headless Blender, on - 5.2 LTS and 4.5 LTS for every PR (5.1 on the weekly cron). Examples run + 5.2 LTS and 4.5 LTS for every PR. 5.1 is weekly cron, the opt-in + `needs-5.1` PR label (`pull_request` types include `labeled`), or + `workflow_dispatch` with a `series` input. Auto-label does not apply + `needs-5.1`. Contributor-facing notes live in CONTRIBUTING.md. Examples run through `tests/smoke/run_example.py` (catalog: `tests/smoke/catalog.json`). SKIP is exit 77 plus a `SMOKE_SKIP:` reason, and only when `--min-version` is above this Blender; exit 0 with that marker is a vacuous pass and fails. diff --git a/CLAUDE.md b/CLAUDE.md index c349846..d22ab52 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -102,7 +102,7 @@ AI asset pipeline track: `decimate_to_budget.py`, `convex_hull_collider.py`, `lo Runnable scripts at `examples//`, each asserting a real API contract with deterministic checks (exit non-zero on failure) and optionally rendering a still via -`--output`. All of them run headless on Blender 5.2 LTS and 4.5 LTS in `blender-smoke.yml` (5.1 on the weekly cron); +`--output`. All of them run headless on Blender 5.2 LTS and 4.5 LTS in `blender-smoke.yml` (5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch); their renders ship in the site gallery at `docs/gallery/`. `examples/gallery.json` is the gallery's source of truth. When authoring a new one, copy the anatomy of `examples/bmesh-gear/` (script structure, README shape, dark-studio render recipe) and diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f133ab..b386437 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,6 +99,19 @@ else: ... ``` +## Blender smoke on pull requests + +Default PR smoke is Blender 5.2 and 4.5 (`.github/workflows/blender-smoke.yml`). +5.1 is not in that matrix. + +- Apply the `needs-5.1` label when the change can diverge on 5.1 (bake, UV + RNA, version-branched API). That starts a 5.1 smoke job. Auto-label will + not apply this; it is opt-in. +- Run any series on demand: Actions > Blender Smoke Test > Run workflow, + pick the branch and the `series` input. +- Monday 07:00 UTC cron still runs 5.2, 5.1, and 4.5. Do not treat cron as + PR evidence. + ## Standards-version Markers Files that participate in ecosystem drift checking must carry a `standards-version` marker matching the current meta-repo `STANDARDS_VERSION` (which is decoupled from this repo's `VERSION`): diff --git a/README.md b/README.md index 1b4a4ec..fd7c1ec 100644 --- a/README.md +++ b/README.md @@ -66,13 +66,13 @@ blender --background --python examples/bmesh-gear/bmesh_gear.py -- | Version | Status | | --- | --- | | Blender 5.2 LTS | Primary target (current stable; all examples assume 5.2 unless a 4.5 path is shown) | -| Blender 5.1 | Prior stable (weekly smoke only) | +| Blender 5.1 | Prior stable (weekly cron; PR via `needs-5.1` or manual dispatch) | | Blender 4.5 LTS | Fallback supported (skills show both code paths where 4.x and 5.x APIs diverge) | ## Examples Runnable, smoke-gated demos live in [`examples/`](examples/) — each is executed headless on -Blender 5.2 LTS and 4.5 LTS by the `blender-smoke` workflow (5.1 on the weekly cron), so the screenshots reflect code +Blender 5.2 LTS and 4.5 LTS by the `blender-smoke` workflow (5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch), so the screenshots reflect code that actually runs. Browse them all with filters and full-size renders in the **[examples gallery](https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/)**, or expand a category below. From 0d32dbd4833e3632684c538137abc26a9e8a1c0b Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Sat, 12 Sep 2026 07:38:45 -0400 Subject: [PATCH 3/4] test: canary to prove 5.1 smoke goes red Temporary SystemExit(1) in bmesh-gear so the labeled 5.1 job is observed failing. Reverted in the next commit. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor --- examples/bmesh-gear/bmesh_gear.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/bmesh-gear/bmesh_gear.py b/examples/bmesh-gear/bmesh_gear.py index 3c17888..a40a6fb 100644 --- a/examples/bmesh-gear/bmesh_gear.py +++ b/examples/bmesh-gear/bmesh_gear.py @@ -194,6 +194,7 @@ def main(): p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"), help="render engine for --output (cycles for GPU-less hosts)") args = p.parse_args(argv) + raise SystemExit(1) # phase-4 canary: prove 5.1 smoke fails obj = build_gear() code = check(obj) From dc8072c7cadc040fd1479604bae97be27e63954b Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Sat, 12 Sep 2026 07:41:37 -0400 Subject: [PATCH 4/4] Revert "test: canary to prove 5.1 smoke goes red" This reverts commit 0d32dbd4833e3632684c538137abc26a9e8a1c0b. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --- examples/bmesh-gear/bmesh_gear.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/bmesh-gear/bmesh_gear.py b/examples/bmesh-gear/bmesh_gear.py index a40a6fb..3c17888 100644 --- a/examples/bmesh-gear/bmesh_gear.py +++ b/examples/bmesh-gear/bmesh_gear.py @@ -194,7 +194,6 @@ def main(): p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"), help="render engine for --output (cycles for GPU-less hosts)") args = p.parse_args(argv) - raise SystemExit(1) # phase-4 canary: prove 5.1 smoke fails obj = build_gear() code = check(obj)