From 99d7f002e3ee85b6abcff8ec463e7b697f82899f Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Wed, 17 Jun 2026 08:13:18 +0200 Subject: [PATCH 1/2] start new dev branch; add audit file --- .audit/oberstet_fix_1848.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .audit/oberstet_fix_1848.md diff --git a/.audit/oberstet_fix_1848.md b/.audit/oberstet_fix_1848.md new file mode 100644 index 000000000..7aabf0da1 --- /dev/null +++ b/.audit/oberstet_fix_1848.md @@ -0,0 +1,8 @@ +- [ ] I did **not** use any AI-assistance tools to help create this pull request. +- [x] I **did** use AI-assistance tools to *help* create this pull request. +- [x] I have read, understood and followed the projects' [AI Policy](https://github.com/crossbario/autobahn-python/blob/main/AI_POLICY.md) when creating code, documentation etc. for this pull request. + +Submitted by: @oberstet +Date: 2026-06-17 +Related issue(s): #1848 +Branch: oberstet:fix_1848 From a948beaa066408c4b72e0885916497bc210c7818 Mon Sep 17 00:00:00 2001 From: Tobias Oberstein Date: Wed, 17 Jun 2026 08:20:58 +0200 Subject: [PATCH 2/2] Build missing ARM64 cp312/cp314 wheels; make release fileset symmetric (#1848) The per-version ARM64 build matrix introduced in commit 3d856f5 (to deduplicate wheels) only created jobs for cpy311 and cpy313, so no CPython 3.12 manylinux aarch64 wheel was ever published, and 3.14 was never added. The strict release fileset manifest shared the identical blind spot and so could not catch the gap (fail-closed validation can only require targets it is told about). Changes: - wheels-arm64.yml: add cpy312 and cpy314 matrix targets on manylinux_2_28_aarch64 (official PyPA images), mirroring cpy311/cpy313. Interpreters are provisioned via uv, so no image-bundled Python is required. - release.yml: wire the new ARM64 artifacts (artifact_arm64_cp312 / artifact_arm64_cp314 outputs, findArtifact lookups, and download-artifact steps in all three release sections) and add cpy312/cpy314 linux-aarch64-manylinux_2_28 to all three strict targets manifests so the gap is closed fail-closed. - release.yml: make the fileset symmetric across all four platforms. Every interpreter (cp311, cp312, cp313, cp314, pypy311) is now required on macOS/arm64, Linux/x86_64, Linux/aarch64, Windows/amd64. The macOS job already builds all interpreters via `just build-all`, but the manifest only required cp313/cp314/pypy311, so cp311/cp312 macOS wheels were built and then dropped as "extra" instead of published; they are now kept and required. Verified the pypy311 aarch64 manifest tag (manylinux_2_17) is correct: auditwheel down-tags the bookworm/trixie pypy wheels to manylinux2014_aarch64.manylinux_2_17_aarch64 (confirmed against the published 25.12.2 wheel), and the CPython aarch64 wheels carry manylinux_2_24_aarch64.manylinux_2_28_aarch64, which substring-matches the manylinux_2_28 target. Fixes #1848. Note: This work was completed with AI assistance (Claude Code). --- .github/workflows/release.yml | 82 ++++++++++++++++++++++++++++++ .github/workflows/wheels-arm64.yml | 20 ++++++++ docs/changelog.rst | 2 + 3 files changed, 104 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47a2963e2..0e676a969 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,9 @@ jobs: artifact_linux_no_nvx: ${{ steps.check.outputs.artifact_linux_no_nvx }} artifact_manylinux_x86_64: ${{ steps.check.outputs.artifact_manylinux_x86_64 }} artifact_arm64_cp311: ${{ steps.check.outputs.artifact_arm64_cp311 }} + artifact_arm64_cp312: ${{ steps.check.outputs.artifact_arm64_cp312 }} artifact_arm64_cp313: ${{ steps.check.outputs.artifact_arm64_cp313 }} + artifact_arm64_cp314: ${{ steps.check.outputs.artifact_arm64_cp314 }} artifact_arm64_pypy_bookworm: ${{ steps.check.outputs.artifact_arm64_pypy_bookworm }} artifact_arm64_pypy_trixie: ${{ steps.check.outputs.artifact_arm64_pypy_trixie }} @@ -142,7 +144,9 @@ jobs: // Query artifacts from wheels-arm64 workflow const wheelsArm64RunId = latestRuns['wheels-arm64']?.id; core.setOutput('artifact_arm64_cp311', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-cpython-3.11-manylinux_2_28_aarch64')); + core.setOutput('artifact_arm64_cp312', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-cpython-3.12-manylinux_2_28_aarch64')); core.setOutput('artifact_arm64_cp313', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-cpython-3.13-manylinux_2_28_aarch64')); + core.setOutput('artifact_arm64_cp314', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-cpython-3.14-manylinux_2_28_aarch64')); core.setOutput('artifact_arm64_pypy_bookworm', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-pypy-3.11-bookworm-manylinux_2_36_aarch64')); core.setOutput('artifact_arm64_pypy_trixie', await findArtifact(wheelsArm64RunId, 'artifacts-arm64-pypy-3.11-trixie-manylinux_2_38_aarch64')); @@ -422,6 +426,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.12 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp312 }} + path: ${{ github.workspace }}/wheelhouse-arm64/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 CPython 3.13 artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -433,6 +448,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.14 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp314 }} + path: ${{ github.workspace }}/wheelhouse-arm64/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 PyPy 3.11 Bookworm artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -813,10 +839,13 @@ jobs: mode: strict keep-metadata: true # Keep CHECKSUMS for user verification targets: | + cpy311-macos-arm64 cpy311-linux-x86_64-manylinux_2_28 cpy311-linux-aarch64-manylinux_2_28 cpy311-win-amd64 + cpy312-macos-arm64 cpy312-linux-x86_64-manylinux_2_28 + cpy312-linux-aarch64-manylinux_2_28 cpy312-win-amd64 cpy313-macos-arm64 cpy313-linux-x86_64-manylinux_2_28 @@ -824,6 +853,7 @@ jobs: cpy313-win-amd64 cpy314-macos-arm64 cpy314-linux-x86_64-manylinux_2_28 + cpy314-linux-aarch64-manylinux_2_28 cpy314-win-amd64 pypy311-macos-arm64 pypy311-linux-x86_64-manylinux_2_28 @@ -1251,6 +1281,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.12 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp312 }} + path: ${{ github.workspace }}/wheelhouse-arm64/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 CPython 3.13 artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -1262,6 +1303,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.14 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp314 }} + path: ${{ github.workspace }}/wheelhouse-arm64/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 PyPy 3.11 Bookworm artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -1642,10 +1694,13 @@ jobs: mode: strict keep-metadata: true # Keep CHECKSUMS for user verification targets: | + cpy311-macos-arm64 cpy311-linux-x86_64-manylinux_2_28 cpy311-linux-aarch64-manylinux_2_28 cpy311-win-amd64 + cpy312-macos-arm64 cpy312-linux-x86_64-manylinux_2_28 + cpy312-linux-aarch64-manylinux_2_28 cpy312-win-amd64 cpy313-macos-arm64 cpy313-linux-x86_64-manylinux_2_28 @@ -1653,6 +1708,7 @@ jobs: cpy313-win-amd64 cpy314-macos-arm64 cpy314-linux-x86_64-manylinux_2_28 + cpy314-linux-aarch64-manylinux_2_28 cpy314-win-amd64 pypy311-macos-arm64 pypy311-linux-x86_64-manylinux_2_28 @@ -2100,6 +2156,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.12 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp312 }} + path: ${{ github.workspace }}/dist/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 CPython 3.13 artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -2111,6 +2178,17 @@ jobs: retry-delay: 30 continue-on-error: true + - name: Download and verify ARM64 CPython 3.14 artifacts with retry logic + uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main + with: + name: ${{ needs.check-all-workflows.outputs.artifact_arm64_cp314 }} + path: ${{ github.workspace }}/dist/ + run-id: ${{ needs.check-all-workflows.outputs.wheels_arm64_run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + max-attempts: 5 + retry-delay: 30 + continue-on-error: true + - name: Download and verify ARM64 PyPy 3.11 Bookworm artifacts with retry logic uses: wamp-proto/wamp-cicd/actions/download-artifact-verified@main with: @@ -2262,10 +2340,13 @@ jobs: mode: strict # keep-metadata: false (default - removes CHECKSUMS for PyPI) targets: | + cpy311-macos-arm64 cpy311-linux-x86_64-manylinux_2_28 cpy311-linux-aarch64-manylinux_2_28 cpy311-win-amd64 + cpy312-macos-arm64 cpy312-linux-x86_64-manylinux_2_28 + cpy312-linux-aarch64-manylinux_2_28 cpy312-win-amd64 cpy313-macos-arm64 cpy313-linux-x86_64-manylinux_2_28 @@ -2273,6 +2354,7 @@ jobs: cpy313-win-amd64 cpy314-macos-arm64 cpy314-linux-x86_64-manylinux_2_28 + cpy314-linux-aarch64-manylinux_2_28 cpy314-win-amd64 pypy311-macos-arm64 pypy311-linux-x86_64-manylinux_2_28 diff --git a/.github/workflows/wheels-arm64.yml b/.github/workflows/wheels-arm64.yml index 4f27c7c68..30d90ec81 100644 --- a/.github/workflows/wheels-arm64.yml +++ b/.github/workflows/wheels-arm64.yml @@ -59,6 +59,16 @@ jobs: build_type: "official" python_versions: "cpy311" + # CPython 3.12 - manylinux_2_28_aarch64 (glibc 2.28) + # Modern baseline (Debian 10+, Ubuntu 18.04+, RHEL 8+) + - name: "cpython-3.12-manylinux_2_28_aarch64" + base_image: "quay.io/pypa/manylinux_2_28_aarch64" + manylinux_tag: "manylinux_2_28_aarch64" + glibc_version: "2.28" + python_impl: "cpython" + build_type: "official" + python_versions: "cpy312" + # CPython 3.13 - manylinux_2_28_aarch64 (glibc 2.28) # Modern baseline (Debian 10+, Ubuntu 18.04+, RHEL 8+) - name: "cpython-3.13-manylinux_2_28_aarch64" @@ -69,6 +79,16 @@ jobs: build_type: "official" python_versions: "cpy313" + # CPython 3.14 - manylinux_2_28_aarch64 (glibc 2.28) + # Modern baseline (Debian 10+, Ubuntu 18.04+, RHEL 8+) + - name: "cpython-3.14-manylinux_2_28_aarch64" + base_image: "quay.io/pypa/manylinux_2_28_aarch64" + manylinux_tag: "manylinux_2_28_aarch64" + glibc_version: "2.28" + python_impl: "cpython" + build_type: "official" + python_versions: "cpy314" + # ============================================================ # PyPy ARM64 wheels (using our custom manylinux images) # ============================================================ diff --git a/docs/changelog.rst b/docs/changelog.rst index b0cc8727e..2e4c55e2c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -31,6 +31,8 @@ Changelog * Fix NVX native-extension builds breaking under cross-compilation (e.g. Buildroot/Yocto for aarch64), where the cross toolchain rejected the host-only ``-march=native`` flag (``unknown value 'native' for '-march'``). The default architecture target is now the portable baseline for *all* build contexts (wheels, local source installs, and cross-compilation), with ``-march=native`` available opt-in via ``AUTOBAHN_ARCH_TARGET=native``. The target architecture is detected via ``sysconfig.get_platform()`` so the correct baseline is chosen when cross-compiling. Thanks to @jameshilliard for the original report and approach (#1834, #1835) * Fail the ``just build-all`` recipe (non-zero exit) when any per-interpreter wheel build fails, naming the interpreter(s). Previously a failed build was silently swallowed, producing a green wheels job with a missing wheel that was only caught downstream by strict release fileset validation (#1859) * Cap ``cbor2 < 6`` on PyPy/Windows only (via environment markers), keeping ``cbor2`` 6.x everywhere else. ``cbor2`` 6.x is Rust/pyo3-only with no PyPy/Windows wheel and no pure-Python fallback, so it cannot be installed on PyPy/Windows; the 5.x line ships a pure-Python wheel (and runs at near-native speed on PyPy). This unblocks building and installing autobahn on PyPy/Windows (#1859) +* Build and publish the missing CPython 3.12 and 3.14 ``manylinux_*_aarch64`` (ARM64) wheels. The per-version ARM64 build matrix (added in commit 3d856f5 to deduplicate wheels) only covered cp311 and cp313, so no cp312 aarch64 wheel was ever published (and cp314 was never added) - e.g. ``pip download autobahn --platform manylinux_2_34_aarch64`` for CPython 3.12 found no matching distribution. The strict release fileset manifest shared the same gap and so could not catch it; it now requires the cp312/cp314 aarch64 wheels (fail-closed). Thanks to @norrisjeremy for the report (#1848) +* Make the release fileset symmetric across all four platforms: every supported interpreter (cp311, cp312, cp313, cp314, pypy311) is now required on macOS/arm64, Linux/x86_64, Linux/aarch64, and Windows/amd64. The macOS job already built all interpreters via ``just build-all``, but the manifest only required cp313/cp314/pypy311, so the cp311/cp312 macOS wheels were built and then dropped as "extra" rather than published; they are now kept and required (#1848) 25.12.2 -------