diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 8731a73..7129679 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -5,6 +5,14 @@ on: tags: - "v*" workflow_dispatch: + pull_request: + paths: + - ".github/workflows/publish-pypi.yml" + - "Cargo.toml" + - "Cargo.lock" + - "pyproject.toml" + - "src/**" + - "python/**" permissions: contents: read @@ -51,6 +59,7 @@ jobs: PY manylinux: + if: github.event_name != 'pull_request' name: manylinux ${{ matrix.target }} needs: validate runs-on: ubuntu-latest @@ -90,6 +99,7 @@ jobs: if-no-files-found: error musllinux: + if: github.event_name != 'pull_request' name: musllinux ${{ matrix.target }} needs: validate runs-on: ubuntu-latest @@ -124,7 +134,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15", "3.14t", "3.15t"] steps: - uses: actions/checkout@v7 @@ -132,6 +142,7 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 + allow-prereleases: true - name: Build wheel uses: PyO3/maturin-action@v1 @@ -142,11 +153,46 @@ jobs: args: >- --release --locked --compatibility pypi --interpreter python --out dist - - name: Test wheel + - name: Validate wheel tags and test in a clean interpreter + shell: bash + env: + EXPECTED_PYTHON: ${{ matrix.python-version }} run: | - python -m pip install pytest - python -m pip install --no-index --no-deps --force-reinstall --find-links dist fasttime-rs - python -m pytest python/tests + python -m venv wheel-test + wheel-test/Scripts/python -m pip install pytest packaging + wheel-test/Scripts/python - <<'PY' + import os + from pathlib import Path + import struct + import sys + import sysconfig + import zipfile + from packaging.tags import Tag + from packaging.utils import parse_wheel_filename + + version = os.environ["EXPECTED_PYTHON"] + free_threaded = version.endswith("t") + major, minor = map(int, version.removesuffix("t").split(".")) + assert sys.version_info[:2] == (major, minor), sys.version + assert struct.calcsize("P") == 8, "Expected a 64-bit interpreter" + assert bool(sysconfig.get_config_var("Py_GIL_DISABLED")) == free_threaded + python_tag = f"cp{major}{minor}" + abi_tag = python_tag + ("t" if free_threaded else "") + expected = Tag(python_tag, abi_tag, "win_amd64") + wheels = list(Path("dist").glob("*.whl")) + assert len(wheels) == 1, wheels + wheel = wheels[0] + assert parse_wheel_filename(wheel.name)[3] == {expected}, wheel.name + with zipfile.ZipFile(wheel) as archive: + metadata = [name for name in archive.namelist() if name.endswith(".dist-info/WHEEL")] + assert len(metadata) == 1, metadata + tags = [line[5:] for line in archive.read(metadata[0]).decode().splitlines() + if line.startswith("Tag: ")] + assert tags == [str(expected)], tags + print(f"Validated {wheel.name}: {expected}; interpreter={sys.version}") + PY + wheel-test/Scripts/python -m pip install --no-index --no-deps --find-links dist fasttime-rs + wheel-test/Scripts/python -m pytest python/tests - name: Upload wheel uses: actions/upload-artifact@v6 @@ -156,6 +202,7 @@ jobs: if-no-files-found: error macos: + if: github.event_name != 'pull_request' name: macOS ${{ matrix.platform.target }} CPython ${{ matrix.python-version }} needs: validate runs-on: ${{ matrix.platform.runner }} @@ -198,6 +245,7 @@ jobs: if-no-files-found: error sdist: + if: github.event_name != 'pull_request' name: Source distribution needs: validate runs-on: ubuntu-latest