name: Python Wheel
on:
workflow_call:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
wheel-matrix:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
plat: manylinux_2_17_x86_64
cross: 1
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
plat: manylinux_2_17_aarch64
cross: 1
- os: macos-15-intel
target: x86_64-apple-darwin
plat: macosx_10_13_x86_64
cross: 0
- os: macos-latest
target: aarch64-apple-darwin
plat: macosx_11_0_arm64
cross: 0
- os: windows-latest
target: x86_64-pc-windows-msvc
plat: win_amd64
cross: 0
runs-on: ${{ matrix.os }}
timeout-minutes: 40
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with:
python-version: "3.12"
- name: Install Python build tooling
shell: bash
run: |
set -euo pipefail
python -m pip install --quiet --upgrade pip
python -m pip install --quiet build wheel setuptools
- name: Install Rust toolchain
if: ${{ !matrix.cross }}
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c with:
targets: ${{ matrix.target }}
- name: Install cross CLI
if: ${{ matrix.cross }}
run: cargo install cross --version 0.2.5 --locked
- name: Build and verify wheel
shell: bash
env:
TARGET: ${{ matrix.target }}
WHEEL_PLAT_TAG: ${{ matrix.plat }}
CROSS: ${{ matrix.cross }}
run: bash scripts/build-python-wheel.sh
- name: Fresh venv install + installed-wheel proof
if: ${{ matrix.target != 'aarch64-unknown-linux-gnu' }}
shell: bash
run: |
set -euo pipefail
python -m venv /tmp/wheel-venv
if [ -f /tmp/wheel-venv/Scripts/python.exe ]; then
VENV_PY=/tmp/wheel-venv/Scripts/python.exe
else
VENV_PY=/tmp/wheel-venv/bin/python
fi
"$VENV_PY" -m pip install --quiet --upgrade pip
"$VENV_PY" -m pip install --quiet dist/*.whl
"$VENV_PY" python/scripts/wheel_proof.py
- name: Upload wheel artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f with:
name: wheel-${{ matrix.target }}
path: dist/*.whl
if-no-files-found: error
retention-days: 7
python-version-matrix:
needs: wheel-matrix
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
python: ["3.10", "3.12", "3.14"]
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with:
python-version: ${{ matrix.python }}
- name: Download Linux x86_64 wheel
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 with:
name: wheel-x86_64-unknown-linux-gnu
path: dist
- name: Install SAME wheel into Python ${{ matrix.python }} and prove it
shell: bash
run: |
set -euo pipefail
python -m venv /tmp/wheel-venv
if [ -f /tmp/wheel-venv/Scripts/python.exe ]; then
VENV_PY=/tmp/wheel-venv/Scripts/python.exe
else
VENV_PY=/tmp/wheel-venv/bin/python
fi
"$VENV_PY" -m pip install --quiet --upgrade pip
"$VENV_PY" -m pip install --quiet dist/*.whl
"$VENV_PY" python/scripts/wheel_proof.py
datatrove-smoke:
needs: wheel-matrix
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with:
python-version: "3.12"
- name: Download Linux x86_64 wheel
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 with:
name: wheel-x86_64-unknown-linux-gnu
path: dist
- name: Install wheel with datatrove extra and run integration tests
shell: bash
run: |
set -euo pipefail
python -m venv /tmp/dt-venv
if [ -f /tmp/dt-venv/Scripts/python.exe ]; then
VENV_PY=/tmp/dt-venv/Scripts/python.exe
else
VENV_PY=/tmp/dt-venv/bin/python
fi
"$VENV_PY" -m pip install --quiet --upgrade pip
WHEEL=$(ls dist/*.whl | head -n1)
"$VENV_PY" -m pip install --quiet "${WHEEL}[datatrove]"
"$VENV_PY" -m pip install --quiet pytest
"$VENV_PY" -m pytest python/tests/test_datatrove_integration.py -q
sdist:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09
- name: Set up Python 3.12
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with:
python-version: "3.12"
- name: Install Python build tooling
shell: bash
run: |
set -euo pipefail
python -m pip install --quiet --upgrade pip
python -m pip install --quiet build wheel setuptools
- name: Build and verify sdist
shell: bash
run: |
set -euo pipefail
python -m build --sdist .
SDIST=$(ls dist/*.tar.gz | head -n 1)
test -n "$SDIST"
echo "sdist=$SDIST"
# Version provenance: sdist PKG-INFO must match Cargo.toml.
CARGO_VERSION=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
tar tzf "$SDIST" >/dev/null
PKG_INFO=$(tar xOf "$SDIST" --wildcards "mmap_chunker_core-$CARGO_VERSION/PKG-INFO")
printf '%s\n' "$PKG_INFO" | grep -F "Version: $CARGO_VERSION"
printf '%s\n' "$PKG_INFO" | grep -F 'Name: mmap-chunker-core'
# Required sources/metadata present; build outputs absent.
# NOTE: avoid `grep -q` on a `tar` pipe — early exit SIGPIPEs tar and
# pipefail turns it into a false failure.
for f in Cargo.toml mmap_chunker.h setup.py pyproject.toml \
src/lib.rs python/mmap_chunker/__init__.py \
python/mmap_chunker/_native.py python/mmap_chunker/planning.py \
python/mmap_chunker/py.typed; do
if ! tar tzf "$SDIST" | grep -E "(^|/)$f\$" >/dev/null; then
echo "ERROR: sdist is missing required file $f" >&2
exit 1
fi
done
if tar tzf "$SDIST" | grep -E '(^|/)(target|\.worktrees|\.git)(/|$)' >/dev/null \
|| tar tzf "$SDIST" | grep -E '(\.crate|\.whl|\.so$|\.dll$|\.dylib$)' >/dev/null; then
echo "ERROR: sdist contains build outputs or foreign artifacts" >&2
exit 1
fi
echo "PASS: sdist version, metadata, and content contract verified"
- name: Upload sdist artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f with:
name: python-sdist
path: dist/*.tar.gz
if-no-files-found: error
retention-days: 7