diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f7abb9a..ec9c755 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,159 +2,232 @@ name: CI on: [push, pull_request] +# Automatically cancel previous runs of this workflow on the same branch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: + linux: + # Skip building pull requests from the same repository + if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} + runs-on: ubuntu-latest + strategy: + matrix: + target: [x86_64, aarch64] + fail-fast: false + steps: + - uses: actions/checkout@v5 + with: + submodules: 'true' + + - name: Update pyproject.toml version + if: ${{ startsWith(github.ref, 'refs/tags/') }} + shell: bash + run: | + # Extract version from tag (strip 'v' prefix if present) + VERSION=${GITHUB_REF#refs/tags/} + VERSION=${VERSION#v} + echo "Extracted version: $VERSION" + + # Update version in pyproject.toml (works on both GNU and BSD sed) + sed -i.bak "s/^version = .*/version = \"$VERSION\"/" pyproject.toml + rm pyproject.toml.bak + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.9.3" + + # NOTE: On Linux we need to manually export LD_LIBRARY_PATH + - name: Set up Python + run: | + uv python install --default + LIBDIR=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") + echo "LD_LIBRARY_PATH=${LIBDIR}:${LD_LIBRARY_PATH}" >> $GITHUB_ENV + + - name: Run Python tests + run: uv run pytest + + - name: Run Rust tests + run: cargo run + + - name: Clean Rust build cache + run: cargo clean + + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + manylinux: auto + + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-linux-${{ matrix.target }} + path: dist + windows: # Skip building pull requests from the same repository if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} runs-on: windows-latest - env: - # Disable output buffering in an attempt to get readable errors - PYTHONUNBUFFERED: '1' steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: 'true' - - - name: Python environment - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - with: - targets: x86_64-pc-windows-msvc - - - name: Build + - name: Update pyproject.toml version + if: ${{ startsWith(github.ref, 'refs/tags/') }} shell: bash run: | - pip install -r requirements.txt - python setup.py sdist - python setup.py bdist_wheel --py-limited-api=cp37 - pip install --force-reinstall dist/*.whl - python -c "import icicle" + # Extract version from tag (strip 'v' prefix if present) + VERSION=${GITHUB_REF#refs/tags/} + VERSION=${VERSION#v} + echo "Extracted version: $VERSION" + + # Update version in pyproject.toml (works on both GNU and BSD sed) + sed -i.bak "s/^version = .*/version = \"$VERSION\"/" pyproject.toml + rm pyproject.toml.bak + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + version: "0.9.3" + + - name: Set up Python + run: uv python install --default + + - name: Run Rust tests + run: cargo run + + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: x64 + args: --release --out dist --find-interpreter + + - name: Run Python tests + run: uv run pytest - - name: Test - run: | - pip install -r tests/requirements.txt - python tests/example.py - python tests/invalid.py - - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-windows + name: wheels-windows-x64 path: dist macos: # Skip building pull requests from the same repository if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} runs-on: macos-latest - env: - # Disable output buffering in an attempt to get readable errors - PYTHONUNBUFFERED: '1' + strategy: + matrix: + target: [x86_64, aarch64] + fail-fast: false steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: 'true' - - - name: Python environment - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - with: - targets: aarch64-apple-darwin, x86_64-apple-darwin - - - name: Build + - name: Update pyproject.toml version + if: ${{ startsWith(github.ref, 'refs/tags/') }} shell: bash - env: - DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer - MACOSX_DEPLOYMENT_TARGET: '10.9' - ARCHFLAGS: -arch x86_64 -arch arm64 - PYO3_CROSS_LIB_DIR: /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib run: | - pip install -r requirements.txt - python setup.py bdist_wheel --py-limited-api=cp37 - pip install --force-reinstall dist/*_universal2.whl - python -c "import icicle" - - - name: Test - run: | - pip install -r tests/requirements.txt - python tests/example.py - python tests/invalid.py - + # Extract version from tag (strip 'v' prefix if present) + VERSION=${GITHUB_REF#refs/tags/} + VERSION=${VERSION#v} + echo "Extracted version: $VERSION" + + # Update version in pyproject.toml (works on both GNU and BSD sed) + sed -i.bak "s/^version = .*/version = \"$VERSION\"/" pyproject.toml + rm pyproject.toml.bak + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + version: "0.9.3" + + - name: Set up Python + run: uv python install --default + + - name: Run Rust tests + if: matrix.target == 'aarch64' + run: cargo run --release + + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + + - name: Run Python tests + if: matrix.target == 'aarch64' + run: uv run pytest + - name: Upload wheels uses: actions/upload-artifact@v4 with: - name: wheels-macos + name: wheels-macos-${{ matrix.target }} path: dist - linux: + sdist: # Skip building pull requests from the same repository if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} - runs-on: ubuntu-24.04 - container: quay.io/pypa/manylinux_2_28_x86_64 - env: - # Disable output buffering in an attempt to get readable errors - PYTHONUNBUFFERED: '1' + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: submodules: 'true' - - - name: Build + + - name: Update pyproject.toml version + if: ${{ startsWith(github.ref, 'refs/tags/') }} shell: bash run: | - curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && yum install -y openssl-devel - export PATH="$PATH:$HOME/.cargo/bin" - export PATH="/opt/python/cp38-cp38/bin:$PATH" - pip install -r requirements.txt - python setup.py bdist_wheel --py-limited-api=cp37 --plat-name manylinux_2_28_x86_64 - auditwheel show dist/*.whl - pip install --force-reinstall dist/*.whl - python -c "import icicle" - - - name: Test - run: | - export PATH="/opt/python/cp38-cp38/bin:$PATH" - pip install -r tests/requirements.txt - python tests/example.py - python tests/invalid.py - - - name: Upload wheels + # Extract version from tag (strip 'v' prefix if present) + VERSION=${GITHUB_REF#refs/tags/} + VERSION=${VERSION#v} + echo "Extracted version: $VERSION" + + # Update version in pyproject.toml (works on both GNU and BSD sed) + sed -i.bak "s/^version = .*/version = \"$VERSION\"/" pyproject.toml + rm pyproject.toml.bak + + - name: Build sdist + uses: PyO3/maturin-action@v1 + with: + command: sdist + args: --out dist + + - name: Upload sdist uses: actions/upload-artifact@v4 with: - name: wheels-linux + name: wheels-sdist path: dist release: if: ${{ startsWith(github.ref, 'refs/tags/') }} - runs-on: ubuntu-24.04 - needs: [windows, macos, linux] + runs-on: ubuntu-latest + needs: [linux, windows, macos, sdist] permissions: contents: write discussions: write id-token: write steps: - name: Download wheels - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: pattern: wheels-* merge-multiple: true path: dist - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.13 + uses: PyO3/maturin-action@v1 + with: + command: upload + args: --non-interactive --skip-existing dist/* - name: Release - uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9 + uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 with: generate_release_notes: true files: dist/*