name: CI on: push: branches: - main pull_request: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true env: CARGO_TERM_COLOR: always jobs: fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - run: pip install nox - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - name: Check python formatting (black) run: nox -s fmt-py - name: Check rust formatting (rustfmt) run: nox -s fmt-rust clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - run: pip install nox - uses: dtolnay/rust-toolchain@stable with: components: clippy - run: nox -s clippy check-target: needs: [fmt] runs-on: ubuntu-latest strategy: # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} matrix: target: [powerpc64le-unknown-linux-gnu, s390x-unknown-linux-gnu, wasm32-wasi] name: check-${{ matrix.target }} steps: - uses: actions/checkout@v3 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - name: Run cargo checks run: | set -x VERSIONS=("3.7" "3.8" "3.9" "3.10" "3.11") for VERSION in ${VERSIONS[@]}; do echo "version=$VERSION" > config.txt echo "suppress_build_script_link_lines=true" >> config.txt PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --no-default-features PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --no-default-features --features "abi3" PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --features "full multiple-pymethods" PYO3_BUILD_CONFIG=$(pwd)/config.txt cargo check --all-targets --features "abi3 full multiple-pymethods" done build: needs: [fmt] # don't wait for clippy as fails rarely and takes longer name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }} runs-on: ${{ matrix.platform.os }} strategy: # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} matrix: extra_features: ["multiple-pymethods"] # Because MSRV doesn't support this rust: [stable] python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.7", "pypy-3.8", "pypy-3.9" ] platform: [ { os: "macos-latest", python-architecture: "x64", rust-target: "x86_64-apple-darwin", }, { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu", }, { os: "windows-latest", python-architecture: "x64", rust-target: "x86_64-pc-windows-msvc", }, ] include: # Test minimal supported Rust version - rust: 1.48.0 python-version: "3.11" platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu", } msrv: "MSRV" extra_features: "" # Test the `nightly` feature - rust: nightly python-version: "3.11" platform: { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu", } extra_features: "nightly multiple-pymethods" # Test 32-bit Windows only with the latest Python version - rust: stable python-version: "3.11" platform: { os: "windows-latest", python-architecture: "x86", rust-target: "i686-pc-windows-msvc", } extra_features: "multiple-pymethods" steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.platform.python-architecture }} - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.platform.rust-target }} # needed to correctly format errors, see #1865 components: rust-src - uses: Swatinem/rust-cache@v2 with: key: cargo-${{ matrix.platform.python-architecture }}-${{ matrix.platform.os }}-${{ matrix.msrv }} continue-on-error: true - if: matrix.platform.os == 'ubuntu-latest' name: Prepare LD_LIBRARY_PATH (Ubuntu only) run: echo LD_LIBRARY_PATH=${pythonLocation}/lib >> $GITHUB_ENV - if: matrix.msrv == 'MSRV' name: Prepare minimal package versions (MSRV only) run: | set -x cargo update -p indexmap --precise 1.6.2 cargo update -p hashbrown:0.12.3 --precise 0.9.1 PROJECTS=("." "examples/decorator" "examples/maturin-starter" "examples/setuptools-rust-starter" "examples/word-count") for PROJ in ${PROJECTS[@]}; do cargo update --manifest-path "$PROJ/Cargo.toml" -p parking_lot --precise 0.11.0 cargo update --manifest-path "$PROJ/Cargo.toml" -p once_cell --precise 1.14.0 done cargo update -p plotters --precise 0.3.1 cargo update -p plotters-svg --precise 0.3.1 cargo update -p plotters-backend --precise 0.3.2 cargo update -p bumpalo --precise 3.10.0 cargo update -p once_cell --precise 1.14.0 - name: Build docs run: cargo doc --no-deps --no-default-features --features "full ${{ matrix.extra_features }}" - name: Build (no features) run: cargo build --lib --tests --no-default-features # --no-default-features when used with `cargo build/test -p` doesn't seem to work! - name: Build pyo3-build-config (no features) run: | cd pyo3-build-config cargo build --no-default-features # Run tests (except on PyPy, because no embedding API). - if: ${{ !startsWith(matrix.python-version, 'pypy') }} name: Test (no features) run: cargo test --no-default-features --lib --tests # --no-default-features when used with `cargo build/test -p` doesn't seem to work! - name: Test pyo3-build-config (no features) run: | cd pyo3-build-config cargo test --no-default-features - name: Build (all additive features) run: cargo build --lib --tests --no-default-features --features "full ${{ matrix.extra_features }}" - if: ${{ startsWith(matrix.python-version, 'pypy') }} name: Build PyPy (abi3-py37) run: cargo build --lib --tests --no-default-features --features "abi3-py37 full ${{ matrix.extra_features }}" # Run tests (except on PyPy, because no embedding API). - if: ${{ !startsWith(matrix.python-version, 'pypy') }} name: Test run: cargo test --no-default-features --features "full ${{ matrix.extra_features }}" # Run tests again, but in abi3 mode - if: ${{ !startsWith(matrix.python-version, 'pypy') }} name: Test (abi3) run: cargo test --no-default-features --features "abi3 full ${{ matrix.extra_features }}" # Run tests again, for abi3-py37 (the minimal Python version) - if: ${{ (!startsWith(matrix.python-version, 'pypy')) && (matrix.python-version != '3.7') }} name: Test (abi3-py37) run: cargo test --no-default-features --features "abi3-py37 full ${{ matrix.extra_features }}" - name: Test proc-macro code run: cargo test --manifest-path=pyo3-macros-backend/Cargo.toml - name: Test build config run: cargo test --manifest-path=pyo3-build-config/Cargo.toml - name: Test python examples and tests shell: bash run: | python -m pip install -U pip nox nox -s test-py env: CARGO_TARGET_DIR: ${{ github.workspace }}/target - name: Test cross compilation if: ${{ matrix.platform.os == 'ubuntu-latest' && matrix.python-version == '3.9' }} uses: PyO3/maturin-action@v1 env: PYO3_CROSS_LIB_DIR: /opt/python/cp39-cp39/lib with: target: aarch64-unknown-linux-gnu manylinux: auto args: --release -i python3.9 -m examples/maturin-starter/Cargo.toml - run: sudo rm -rf examples/maturin-starter/target if: ${{ matrix.platform.os == 'ubuntu-latest' && matrix.python-version == '3.9' }} - name: Test cross compile to same architecture if: ${{ matrix.platform.os == 'ubuntu-latest' && matrix.python-version == '3.9' }} uses: PyO3/maturin-action@v1 env: PYO3_CROSS_LIB_DIR: /opt/python/cp39-cp39/lib with: target: x86_64-unknown-linux-gnu manylinux: auto args: --release -i python3.9 -m examples/maturin-starter/Cargo.toml - name: Test cross compilation if: ${{ matrix.platform.os == 'macos-latest' && matrix.python-version == '3.9' }} uses: PyO3/maturin-action@v1 with: target: aarch64-apple-darwin args: --release -i python3.9 -m examples/maturin-starter/Cargo.toml - name: Test cross compile to Windows if: ${{ matrix.platform.os == 'ubuntu-latest' && matrix.python-version == '3.8' }} env: XWIN_ARCH: x86_64 run: | set -ex sudo apt-get install -y mingw-w64 llvm rustup target add x86_64-pc-windows-gnu x86_64-pc-windows-msvc python -m pip install cargo-xwin # abi3 cargo build --manifest-path examples/maturin-starter/Cargo.toml --features abi3 --target x86_64-pc-windows-gnu cargo xwin build --manifest-path examples/maturin-starter/Cargo.toml --features abi3 --target x86_64-pc-windows-msvc # non-abi3 export PYO3_CROSS_PYTHON_VERSION=3.9 cargo build --manifest-path examples/maturin-starter/Cargo.toml --features generate-import-lib --target x86_64-pc-windows-gnu cargo xwin build --manifest-path examples/maturin-starter/Cargo.toml --features generate-import-lib --target x86_64-pc-windows-msvc - name: Test cross compile to Windows with maturin if: ${{ matrix.platform.os == 'ubuntu-latest' && matrix.python-version == '3.8' }} uses: PyO3/maturin-action@v1 with: target: x86_64-pc-windows-gnu args: -i python3.8 -m examples/maturin-starter/Cargo.toml --features abi3 env: CARGO_TERM_VERBOSE: true CARGO_BUILD_TARGET: ${{ matrix.platform.rust-target }} RUST_BACKTRACE: 1 RUSTFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings" # TODO: this is a hack to workaround compile_error! warnings about auto-initialize on PyPy # Once cargo's `resolver = "2"` is stable (~ MSRV Rust 1.52), remove this. PYO3_CI: 1 # This is a hack to make CARGO_PRIMARY_PACKAGE always set even for the # msrv job. MSRV is currently 1.48, but CARGO_PRIMARY_PACKAGE only came in # 1.49. CARGO_PRIMARY_PACKAGE: 1 valgrind: needs: [fmt] runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.11" - uses: Swatinem/rust-cache@v2 with: key: cargo-valgrind continue-on-error: true # FIXME(adamreichold): Switch to stable when Valgrind understands DWARF5 as generated by LLVM 14, # c.f. https://bugs.kde.org/show_bug.cgi?id=452758#c35 - uses: dtolnay/rust-toolchain@1.61.0 - uses: taiki-e/install-action@valgrind - run: python -m pip install -U pip nox - run: nox -s test-rust -- release skip-full env: CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: valgrind --leak-check=no --error-exitcode=1 RUST_BACKTRACE: 1 TRYBUILD: overwrite careful: needs: [fmt] runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.11" - uses: Swatinem/rust-cache@v2 with: key: cargo-careful continue-on-error: true - uses: dtolnay/rust-toolchain@nightly with: components: rust-src - run: cargo install cargo-careful - run: python -m pip install -U pip nox - run: nox -s test-rust -- careful skip-full env: RUST_BACKTRACE: 1 TRYBUILD: overwrite coverage: needs: [fmt] name: coverage-${{ matrix.os }} strategy: matrix: os: ["windows", "macos", "ubuntu"] runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: "3.11" - uses: Swatinem/rust-cache@v2 with: key: coverage-cargo-${{ matrix.os }} continue-on-error: true - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov - run: python -m pip install -U pip nox - run: nox -s coverage - uses: codecov/codecov-action@v3 with: file: coverage.lcov name: ${{ matrix.os }} emscripten: name: emscripten runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 id: setup-python with: python-version: "3.11" - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable with: targets: wasm32-unknown-emscripten - uses: actions/setup-node@v3 with: node-version: 14 - run: pip install nox - uses: actions/cache@v3 id: cache with: path: | .nox/emscripten key: ${{ hashFiles('emscripten/*') }} - ${{ hashFiles('noxfile.py') }} - ${{ steps.setup-python.outputs.python-path }} - uses: Swatinem/rust-cache@v2 with: key: cargo-emscripten-wasm32 - name: Build if: steps.cache.outputs.cache-hit != 'true' run: nox -s build-emscripten - name: Test run: nox -s test-emscripten