From 30a6fcacdafb2f91ce0c05bb1d5b92775d147d88 Mon Sep 17 00:00:00 2001 From: Jericho Tolentino <68654047+jericht@users.noreply.github.com> Date: Sat, 20 Jun 2026 01:40:29 +0000 Subject: [PATCH] chore(build): build wheels for multiple platforms Replace the single-platform hatch build with a GitHub Actions matrix that builds native wheels for linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (x86_64, arm64) using maturin-action. Add --version-only flag to scripts/maturin_build.py so CI can inject the VCS version into pyproject.toml before maturin-action runs. Signed-off-by: Jericho Tolentino <68654047+jericht@users.noreply.github.com> --- .github/workflows/release_publish.yml | 55 +++++++++------------------ _build_backend.py | 7 ++++ scripts/maturin_build.py | 11 ++++++ 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/.github/workflows/release_publish.yml b/.github/workflows/release_publish.yml index 36027dab..b343341d 100644 --- a/.github/workflows/release_publish.yml +++ b/.github/workflows/release_publish.yml @@ -35,57 +35,36 @@ jobs: tag: ${{ needs.TagRelease.outputs.tag }} PreRelease: - needs: [TagRelease, UnitTests] - uses: OpenJobDescription/.github/.github/workflows/reusable_prerelease.yml@mainline - permissions: - id-token: write - contents: write - secrets: inherit - with: - tag: ${{ needs.TagRelease.outputs.tag }} + needs: [TagRelease, UnitTests] + uses: OpenJobDescription/.github/.github/workflows/reusable_maturin_prerelease.yml@mainline + secrets: inherit + with: + tag: ${{ needs.TagRelease.outputs.tag }} Release: - needs: [TagRelease, PreRelease] - uses: OpenJobDescription/.github/.github/workflows/reusable_release.yml@mainline - secrets: inherit - permissions: - id-token: write - contents: write - with: - tag: ${{ needs.TagRelease.outputs.tag }} - - Publish: - needs: [TagRelease, Release] - uses: OpenJobDescription/.github/.github/workflows/reusable_publish_python.yml@mainline + needs: [TagRelease, PreRelease] + uses: OpenJobDescription/.github/.github/workflows/reusable_release.yml@mainline + secrets: inherit permissions: id-token: write - secrets: inherit + contents: write with: - tag: ${{ needs.TagRelease.outputs.tag }} + tag: ${{ needs.TagRelease.outputs.tag }} # PyPI does not support reusable workflows yet - # # See https://github.com/pypi/warehouse/issues/11096 + # See https://github.com/pypi/warehouse/issues/11096 PublishToPyPI: - needs: [TagRelease, Publish] + needs: [TagRelease, Release, PreRelease] runs-on: ubuntu-latest environment: release permissions: id-token: write steps: - - name: Checkout - uses: actions/checkout@v6 + - uses: actions/download-artifact@v4 with: - ref: ${{ needs.TagRelease.outputs.tag }} - fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: '3.9' - - name: Install dependencies - run: | - pip install --upgrade hatch "virtualenv<21" - - name: Build - run: hatch -v build - # # See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-pypi + name: build-artifact + path: dist - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist diff --git a/_build_backend.py b/_build_backend.py index a0e0f26c..7b276861 100644 --- a/_build_backend.py +++ b/_build_backend.py @@ -32,10 +32,17 @@ from __future__ import annotations import contextlib +import os import shutil import sys from pathlib import Path +# Windows MSVC linker fails with LNK1104 when paths exceed MAX_PATH (260 chars). +# Building from an extracted sdist produces deeply nested target directories. +# Redirect Cargo's output to a short path to avoid this. +if sys.platform == "win32" and "CARGO_TARGET_DIR" not in os.environ: + os.environ["CARGO_TARGET_DIR"] = "C:\\cargo-target" + import maturin REPO_ROOT = Path(__file__).resolve().parent diff --git a/scripts/maturin_build.py b/scripts/maturin_build.py index 3812770a..e7f83d7a 100644 --- a/scripts/maturin_build.py +++ b/scripts/maturin_build.py @@ -67,6 +67,17 @@ def main(argv: list[str]) -> int: ) shutil.move(str(PYPROJECT_BAK), str(PYPROJECT)) + # --version-only: inject the VCS version into pyproject.toml and + # _version.py without running maturin. Used in CI when maturin-action + # handles the actual build but needs the version patched beforehand. + if "--version-only" in argv: + version = compute_version() + write_version_file(version) + print(f"Wrote src/openjd/model/_version.py (version {version})") + _patch_pyproject(version) + print(f"Patched pyproject.toml: project.version = {version!r}") + return 0 + maturin_args = argv or ["develop"] version = compute_version()