chore(deps): bump actions/download-artifact from 7 to 8 #7
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
| name: Build wheels (cibuildwheel — Rust Phase 2) | |
| # Phase-2 gate for the Rust HDFE kernel spike. | |
| # | |
| # The Rust HDFE crate lives under `rust/statspai_hdfe/` and its | |
| # `Cargo.toml` IS present on `main`. But cibuildwheel can only emit a | |
| # platform wheel when the project's PEP 517 build-backend is maturin, | |
| # so the PyO3 extension gets compiled into the wheel. Today | |
| # `pyproject.toml` uses `setuptools.build_meta` (no `[tool.maturin]`), | |
| # which yields a pure-Python `py3-none-any` wheel that cibuildwheel | |
| # rejects with exit 5 (NonPlatformWheelError). The `check_rust_present` | |
| # guard below therefore gates on the maturin backend — NOT on Cargo.toml | |
| # presence — so this workflow stays INERT until the native wheel | |
| # pipeline is actually wired. When a PR switches the build-backend to | |
| # maturin, the guard opens and the cibuildwheel matrix runs. | |
| # | |
| # Matrix coverage mirrors the contract in `rust/README.md`: | |
| # - macOS arm64 (macos-14) + x86_64 (macos-13) | |
| # - manylinux_2_17 x86_64 + aarch64 | |
| # - musllinux_1_2 x86_64 | |
| # - Windows x86_64 | |
| # | |
| # Security note: this workflow only reads `matrix.*` and `inputs.*` | |
| # (both defined in this file, not user-controlled), and does not | |
| # interpolate any `github.event.*` strings into `run:` blocks — so | |
| # the GitHub Actions command-injection vectors do not apply. | |
| on: | |
| push: | |
| branches: | |
| - 'feat/rust-hdfe' | |
| - 'feat/rust-phase2' | |
| pull_request: | |
| paths: | |
| - 'rust/**' | |
| - '.github/workflows/build-wheels.yml' | |
| - 'pyproject.toml' | |
| workflow_dispatch: | |
| inputs: | |
| publish_testpypi: | |
| description: 'Upload wheels to TestPyPI after build' | |
| type: boolean | |
| default: false | |
| # Opt into Node 24 runtime for JavaScript actions. GitHub's documented | |
| # migration path (2025-09-19 changelog) ahead of the 2026-06-02 hard | |
| # cutover. Preserves current action versions. No user input interpolated. | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' | |
| jobs: | |
| check_rust_present: | |
| name: Detect Rust crate | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has_rust: ${{ steps.detect.outputs.has_rust }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - id: detect | |
| name: Detect a maturin (PyO3) build backend | |
| run: | | |
| # cibuildwheel can only build a platform wheel when the PEP 517 | |
| # backend is maturin (so the Rust extension is compiled in). | |
| # Gate on that — Cargo.toml presence alone is NOT sufficient: | |
| # with the setuptools backend a pure-Python wheel is produced | |
| # and cibuildwheel exits 5 (NonPlatformWheelError). This keeps | |
| # the workflow inert until the native build is really wired, | |
| # while still re-triggering (via the pyproject.toml path filter) | |
| # the moment a PR adopts the maturin backend. | |
| if grep -Eq '^[[:space:]]*build-backend[[:space:]]*=[[:space:]]*"maturin' pyproject.toml \ | |
| && [ -f rust/statspai_hdfe/Cargo.toml ]; then | |
| echo "has_rust=true" >> "$GITHUB_OUTPUT" | |
| echo "maturin backend + Rust crate present — cibuildwheel matrix will run." | |
| else | |
| echo "has_rust=false" >> "$GITHUB_OUTPUT" | |
| echo "No maturin build-backend on this ref — wheel jobs skip (pure-Python build)." | |
| fi | |
| build_wheels: | |
| name: Build wheels (${{ matrix.os }} / ${{ matrix.arch }}) | |
| needs: check_rust_present | |
| if: needs.check_rust_present.outputs.has_rust == 'true' | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Linux — manylinux_2_17 covers Python >=3.9 on most distros; | |
| # musllinux covers Alpine/containers where glibc is absent. | |
| - os: ubuntu-latest | |
| arch: x86_64 | |
| cibw_build: "cp39-manylinux_x86_64 cp310-manylinux_x86_64 cp311-manylinux_x86_64 cp312-manylinux_x86_64 cp313-manylinux_x86_64 cp39-musllinux_x86_64 cp310-musllinux_x86_64 cp311-musllinux_x86_64 cp312-musllinux_x86_64 cp313-musllinux_x86_64" | |
| - os: ubuntu-latest | |
| arch: aarch64 | |
| cibw_build: "cp39-manylinux_aarch64 cp310-manylinux_aarch64 cp311-manylinux_aarch64 cp312-manylinux_aarch64 cp313-manylinux_aarch64" | |
| # macOS split — macos-13 runs x86_64 natively; macos-14 is | |
| # Apple-silicon and only builds arm64 wheels. | |
| - os: macos-13 | |
| arch: x86_64 | |
| cibw_build: "cp39-macosx_x86_64 cp310-macosx_x86_64 cp311-macosx_x86_64 cp312-macosx_x86_64 cp313-macosx_x86_64" | |
| - os: macos-14 | |
| arch: arm64 | |
| cibw_build: "cp39-macosx_arm64 cp310-macosx_arm64 cp311-macosx_arm64 cp312-macosx_arm64 cp313-macosx_arm64" | |
| # Windows — x86_64 only. | |
| - os: windows-latest | |
| arch: AMD64 | |
| cibw_build: "cp39-win_amd64 cp310-win_amd64 cp311-win_amd64 cp312-win_amd64 cp313-win_amd64" | |
| env: | |
| CIBW_ARCHS: ${{ matrix.arch }} | |
| CIBW_BUILD: ${{ matrix.cibw_build }} | |
| CIBW_SKIP: "*-win32 *-manylinux_i686 pp*" | |
| CIBW_BEFORE_BUILD_LINUX: "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal && source $HOME/.cargo/env && pip install maturin" | |
| CIBW_BEFORE_BUILD_MACOS: "rustup target add aarch64-apple-darwin x86_64-apple-darwin && pip install maturin" | |
| CIBW_BEFORE_BUILD_WINDOWS: "pip install maturin" | |
| CIBW_TEST_REQUIRES: "pytest numpy pandas numba" | |
| CIBW_TEST_COMMAND: > | |
| python -c "import statspai; assert statspai.__version__" | |
| && pytest {project}/tests/test_fast_demean.py {project}/tests/test_hdfe_native.py -x -q | |
| CIBW_ARCHS_LINUX: ${{ matrix.arch }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Enable QEMU for aarch64 (linux only) | |
| if: matrix.os == 'ubuntu-latest' && matrix.arch == 'aarch64' | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: arm64 | |
| - name: Install cibuildwheel | |
| run: python -m pip install --upgrade pip cibuildwheel==2.21.3 | |
| - name: Build wheels | |
| run: python -m cibuildwheel --output-dir wheelhouse | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: wheels-${{ matrix.os }}-${{ matrix.arch }} | |
| path: ./wheelhouse/*.whl | |
| build_sdist: | |
| name: Build sdist | |
| needs: check_rust_present | |
| if: needs.check_rust_present.outputs.has_rust == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Build sdist | |
| run: | | |
| python -m pip install --upgrade pip build | |
| python -m build --sdist | |
| - uses: actions/upload-artifact@v6 | |
| with: | |
| name: sdist | |
| path: ./dist/*.tar.gz | |
| publish_testpypi: | |
| name: Upload to TestPyPI (opt-in) | |
| needs: [build_wheels, build_sdist] | |
| if: | | |
| github.event_name == 'workflow_dispatch' && | |
| inputs.publish_testpypi == true | |
| runs-on: ubuntu-latest | |
| environment: testpypi | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| packages-dir: dist/ | |
| skip-existing: true |