ci(pip-build): respect disable-build-* labels for ubuntu / macos#6091
Open
Fedr wants to merge 10 commits into
Open
ci(pip-build): respect disable-build-* labels for ubuntu / macos#6091Fedr wants to merge 10 commits into
Fedr wants to merge 10 commits into
Conversation
`test-pip-build` (the workflow_call into pip-build.yml) ignored the `disable-build-<platform>` PR labels and always tried to run the full manylinux + macOS matrix. That bit PR #6090: a `disable-build-linux-vcpkg` label suppressed the prepare-image step, but `test-pip-build` still tried to pull the branch-tagged Rocky Linux image and failed with `manifest unknown`. Plumb three new boolean inputs through pip-build.yml -- `disable_ubuntu_x64`, `disable_ubuntu_arm64`, `disable_macos` -- and gate the matching build/test jobs: - manylinux-pip-build / manylinux-pip-test: per-platform `if:` keyed on `matrix.platform` so x86_64 and aarch64 can be disabled independently (matches the `disable-build-ubuntu-{x64,arm64}` split elsewhere). - macos-pip-build / macos-pip-test: single `if:` gated on `disable_macos` (both x86 and arm64 macOS variants together, matching the single `disable-build-macos` label). `build-test-distribute.yml` derives the three flags from the same `build_enable_<platform>` outputs that `prepare-image` already uses on the adjacent line. Out of scope (not requested): `disable-build-windows` (windows-pip-build keeps running) and `disable-build-emscripten` (pip-build.yml has no emscripten target).
The previous attempt used a job-level `if:` referencing `matrix.platform`, but GitHub Actions rejects that for reusable-workflow jobs: Unrecognized named-value: 'matrix'. Located at position 2 within expression: (matrix.platform == 'x86_64' && inputs.disable_ubuntu_x64 != true) || ... (The contexts table at https://docs.github.com/en/actions/learn-github-actions/contexts lists `matrix` as available in `jobs.<job_id>.if`, but the parser disagrees for reusable workflows. The workflow file failed to load entirely; no jobs even started.) Switch the per-platform gating to `strategy.matrix.exclude` with input-driven expressions. When `inputs.disable_ubuntu_x64` is true, the exclude entry matches and removes the `x86_64` row from the matrix; when it's false, the entry resolves to the sentinel `__never__`, which doesn't match any real matrix platform, so nothing is excluded. Same shape for `aarch64`. Applied to both `manylinux-pip-build` and `manylinux-pip-test`. The macOS gate (`if: ${{ inputs.disable_macos != true }}`) only references `inputs` and was not affected by the parse error.
The previous attempt's `strategy.matrix.exclude` correctly removed the `platform=aarch64` base combos when `inputs.disable_ubuntu_arm64` was set, but a stray `(aarch64, ubuntu-24.04-arm, , arm64v8/)` test job still ran with an empty `os`/`py-version`, and the `aarch64` build still ran. Cause: GitHub processes matrix in the order base -> exclude -> include (https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#expanding-or-adding-matrix-configurations). A per-platform include entry (`{platform: "aarch64", runner: ..., ...}`) that has no surviving base combo to extend is treated as a brand-new combo by the include step. That orphan never gets re-filtered by exclude. Fix: remove the per-platform include entries entirely and derive `runs-on`, `container.image`, `container.options`, and the compiler / container-prefix values directly from `matrix.platform` inline. The matrix axis stays `platform: ["x86_64", "aarch64"]`, so exclude removes the row cleanly without leaving an include orphan. The `manylinux-pip-test` py-version include entries are left in place: each has a `py-version` key that matches a real base axis value, so they extend existing combos rather than create new ones, no orphan risk. The compiler was `/usr/bin/clang++` for both platforms, so hardcoding it in the build/bindings steps is a no-op behavior-wise.
The container.image expression on `manylinux-pip-test` was:
${{ matrix.platform == 'x86_64' && '' || 'arm64v8/' }}${{ matrix.os }}
That looks like a ternary picking `''` for x86_64 and `arm64v8/` for
aarch64, but GitHub Actions treats `''` as falsy, so for x86_64 it
evaluates `true && ''` -> `''`, then `'' || 'arm64v8/'` -> `'arm64v8/'`.
Result: x86_64 test runs tried to `docker pull arm64v8/rockylinux:8`
and failed with `no matching manifest for linux/amd64`.
Pick the full image name on each side so both operands of `&&` stay
truthy:
${{ matrix.platform == 'x86_64' && matrix.os || format('arm64v8/{0}', matrix.os) }}
The build-job image expression was unaffected because both literals
(`x64` / `arm64`) are non-empty. The `container.options` expression is
also unaffected because the aarch64 fallback is `' '` (a single space,
truthy in GHA) rather than empty.
MaxRayskiy
approved these changes
May 13, 2026
oitel
reviewed
May 14, 2026
Comment on lines
+321
to
+322
| # Honor `disable-build-<platform>` PR labels so test-pip-build skips the | ||
| # same platforms as the rest of CI. |
| # value, so the exclude has no effect when the input is false. | ||
| # Job-level `if:` can't reference `matrix.*` in a reusable workflow, | ||
| # hence the exclude-based approach. | ||
| exclude: |
Contributor
There was a problem hiding this comment.
Check the build-test-linux-vcpkg workflow on how to exclude matrix configurations based on workflow inputs.
| os: "ubuntu:25.10" | ||
| # Mirror the exclude on `manylinux-pip-build` so tests skip the same | ||
| # platforms. See the note there for the `__never__` sentinel. | ||
| exclude: |
Contributor
There was a problem hiding this comment.
Check the build-test-linux-vcpkg workflow on how to exclude matrix configurations based on workflow inputs.
Address review on #6091: - Drop the redundant `# Honor disable-build-<platform>` comment above the three `disable_*` inputs in build-test-distribute.yml. - Replace the `__never__`-sentinel `exclude:` on both manylinux-pip-build and manylinux-pip-test with the synthetic-axis pattern used in build-test-linux-vcpkg.yml: a one-element matrix axis carrying the `disable_*` input value, and an exclude rule that constrains on `{disable_<platform>: true, platform: <name>}`. When the input is false the rule never matches; when true it drops the matching platform leg.
…axis exclude Per review on #6091: keep the original matrix shape from master (base `platform: [...]` plus per-platform `include` entries feeding runner / os / container-options / container-prefix / compiler) and layer only the synthetic-axis `exclude:` from build-test-linux-vcpkg.yml on top. Reverts the inline `${{ matrix.platform == 'x86_64' && ... || ... }}` expressions for runs-on / container.image / container.options / CMAKE_CXX_COMPILER / CXX_FOR_ABI / CXX_FOR_BINDINGS that I had introduced when trying to avoid the post-exclude include orphan.
Drop the per-platform `include` entries on manylinux-pip-build and
manylinux-pip-test and compute `runs-on`, `container.image`,
`container.options`, and the `arm64v8/` prefix inline from
`matrix.platform`. The compiler (`/usr/bin/clang++`) is the same on both
platforms and is now lifted to a job-level `env.COMPILER` so the build
steps reference it once instead of repeating the literal.
The per-platform include was the source of the orphan combo that the
synthetic-axis exclude couldn't filter (GitHub processes matrix as
base -> exclude -> include, so an include constrained on an already-
excluded platform value spawns a fresh combo that bypasses exclude --
seen as `(aarch64, ubuntu-24.04-arm, , arm64v8/)` running with an empty
`os` and missing `py-version`).
The py-version include entries on manylinux-pip-test stay -- each has a
`py-version` key matching a real base axis value, so they extend
surviving combos rather than orphan.
Both inline conditional branches are non-empty (`format('arm64v8/{0}',
matrix.os)` rather than the literal `''` prefix) because GitHub Actions
treats empty string as falsy in `<cond> && X || Y`, which would
otherwise flip the prefix back to `arm64v8/` on x86_64.
Replace the inline `${{ matrix.platform == 'x86_64' && ... || ... }}`
ternaries on `manylinux-pip-build` / `manylinux-pip-test` with fully
data-driven matrices generated in the existing `setup` job.
The `setup` job now emits two new outputs:
- `build-matrix`: per-platform combos, with disabled platforms filtered
out.
- `test-matrix`: cartesian product (surviving platforms x supported
Python versions), again with disabled platforms filtered out.
The filter happens in a single bash + jq step. The consumer jobs become
trivial:
matrix:
include: ${{ fromJSON(needs.setup.outputs.build-matrix) }}
…and their bodies reference plain `${{ matrix.runner }}`, `${{ matrix.os
}}`, `${{ matrix.compiler }}`, `${{ matrix.container-prefix }}` -- the
master-equivalent shape. No synthetic axis, no `__never__` sentinel, no
`include` orphan can be created because there's no base x include split.
Each consumer job is gated by `if: needs.setup.outputs.<matrix> != '[]'`
so the whole job is skipped (rather than erroring on an empty matrix)
when both platforms are disabled.
oitel
approved these changes
May 15, 2026
| ]' | ||
|
|
||
| # Drop disabled platforms. | ||
| KEEP=$(jq -nc --argjson plats "$PLATS" --argjson dx "$DISABLE_X64" --argjson da "$DISABLE_ARM64" \ |
Contributor
There was a problem hiding this comment.
Make the jq calls multi-line for better readability.
Per review on #6091: reformat the three `jq` calls in setup's matrix step so each argument is on its own line and the filter program reads top-to-bottom. Behavior is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
test-pip-build(theworkflow_callintopip-build.yml) ignored thedisable-build-<platform>PR labels and always tried to run the full manylinux + macOS matrix. That bit #6090: adisable-build-linux-vcpkglabel suppressed the correspondingprepare-imagestep, buttest-pip-buildstill tried todocker pull meshlib/meshlib-rockylinux8-vcpkg-x64:<branch>and failed withmanifest unknown.Plumb three new boolean inputs through
pip-build.ymland gate the matching build / test jobs so the same labels that skip the rest of CI also skip the corresponding pip-build legs.Changes
.github/workflows/pip-build.yml:workflow_callinputsdisable_ubuntu_x64,disable_ubuntu_arm64,disable_macos(all defaultfalse, soworkflow_dispatch/releasetriggers keep the full matrix).setupjob gains two new outputs (build-matrix,test-matrix) populated by a single bash +jqstep:PLATSenumerates per-platform combos (the "include" part:runner/os-vcpkg/container-options/compiler/container-prefix).jqfilter drops disabled platforms (the "exclude" part).manylinux-pip-build/manylinux-pip-test: consume the prebuilt matrices viamatrix: { include: ${{ fromJSON(needs.setup.outputs.<matrix>) }} }. Job bodies reference plain${{ matrix.runner }}/${{ matrix.os }}/${{ matrix.compiler }}/${{ matrix.container-prefix }}— the master-equivalent shape, no ternaries, no synthetic axis. Each job hasif: needs.setup.outputs.<matrix> != '[]'so the both-disabled case skips cleanly rather than erroring on an empty matrix.macos-pip-build/macos-pip-test: single job-levelif: ${{ inputs.disable_macos != true }}(both x86 and arm64 macOS variants together — only onedisable-build-macoslabel exists)..github/workflows/build-test-distribute.yml: derive the three flags from the samebuild_enable_<platform>config outputs that the adjacentprepare-imagealready consumes, and pass them into thetest-pip-buildinvocation.Out of scope
disable-build-windows—windows-pip-buildkeeps running.disable-build-emscripten—pip-build.ymlhas no emscripten target.Why two-stage matrix instead of
matrix.excludewith synthetic axisA simpler
strategy.matrix.excludeapproach (syntheticdisable_ubuntu_*axis carrying the input, exclude rule keyed on it — the same pattern used inbuild-test-linux-vcpkg.yml) was tried first but ran into the include-orphan trap: GitHub processes matrix in the orderbase → exclude → include. Whenexcludewiped allplatform=aarch64base rows, the per-platform{platform: "aarch64", runner: ..., ...}includeentry had no surviving base to extend and was spawned as a fresh combo that bypassed exclude — observed as a(aarch64, ubuntu-24.04-arm, , arm64v8/)job running with an emptyos/ missingpy-versionthat tried todocker pull arm64v8/. (Thebuild-test-linux-vcpkg.ymlpattern doesn't hit this because its excludes only remove specific (compiler, config) tuples, never the wholearchaxis, so its per-compiler / per-arch includes always find a surviving combo to extend.)The two-stage approach sidesteps the orphan entirely: there is no base × include split — every combo comes in via
includedirectly, and filtering happens injq.Test plan
PR labels enable
test-pip-buildand selectively disable platforms (disable-build-{macos,ubuntu-arm64,linux-vcpkg,emscripten,windows}) to exercise the new gating end to end. Latest run:setupruns and emits filtered matrices.manylinux-pip-build (x86_64, ...)runs and passes — single combo, no aarch64.manylinux-pip-test (x86_64, ..., 3.8 … 3.14)runs and passes for all 7 py-versions — no orphan combo this time.jq).macos-pip-build/macos-pip-testskip cleanly (validates the macos gate).windows-pip-build+ 7 ×windows-pip-test (3.x)run and pass (validates the windows path is untouched).false, soworkflow_dispatch/releasetriggers keep the full matrix.