1919 MSRV :
2020 required : true
2121 type : string
22+ verbose :
23+ type : boolean
24+ default : false
25+
26+ env :
27+ NOX_DEFAULT_VENV_BACKEND : uv
2228
2329jobs :
2430 build :
2531 continue-on-error : ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.7", "3.8"]'), inputs.python-version) || contains(fromJSON('["beta", "nightly"]'), inputs.rust) }}
2632 runs-on : ${{ inputs.os }}
2733 if : ${{ !(startsWith(inputs.python-version, 'graalpy') && startsWith(inputs.os, 'windows')) }}
2834 steps :
29- - uses : actions/checkout@v4
30-
31- - name : Set up Python ${{ inputs.python-version }}
32- uses : actions/setup-python@v5
35+ - uses : actions/checkout@v5
36+ with :
37+ # For PRs, we need to run on the real PR head, not the resultant merge of the PR into the target branch.
38+ #
39+ # This is necessary for coverage reporting to make sense; we then get exactly the coverage change
40+ # between the base branch and the real PR head.
41+ #
42+ # If it were run on the merge commit the problem is that the coverage potentially does not align
43+ # with the commit diff, because the merge may affect line numbers.
44+ ref : ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
45+
46+ # installs using setup-python do not work for arm macOS 3.9 and below
47+ - if : ${{ !(inputs.os == 'macos-latest' && contains(fromJSON('["3.7", "3.8", "3.9"]'), inputs.python-version) && inputs.python-architecture == 'x64') }}
48+ name : Set up Python ${{ inputs.python-version }}
49+ uses : actions/setup-python@v6
3350 with :
3451 python-version : ${{ inputs.python-version }}
3552 architecture : ${{ inputs.python-architecture }}
36- check-latest : ${{ startsWith(inputs.python-version, 'pypy') }} # PyPy can have FFI changes within Python versions, which creates pain in CI
53+ # PyPy can have FFI changes within Python versions, which creates pain in CI
54+ check-latest : ${{ startsWith(inputs.python-version, 'pypy') }}
3755
38- - name : Install nox
39- run : python -m pip install --upgrade pip && pip install nox
56+ # workaround for the above, only available for 3.9
57+ - if : ${{ inputs.os == 'macos-latest' && contains(fromJSON('["3.9"]'), inputs.python-version) && inputs.python-architecture == 'x64' }}
58+ name : Set up Python ${{ inputs.python-version }}
59+ uses : astral-sh/setup-uv@v7
60+ with :
61+ python-version : cpython-${{ inputs.python-version }}-macos-x86-64
4062
41- - if : inputs.python-version == 'graalpy24.1'
42- name : Install GraalPy virtualenv (only GraalPy 24.1)
43- run : python -m pip install 'git+https://github.com/oracle/graalpython#egg=graalpy_virtualenv_seeder&subdirectory=graalpy_virtualenv_seeder'
63+ - name : Install nox
64+ run : python -m pip install --upgrade pip && pip install nox[uv]
4465
4566 - name : Install Rust toolchain
4667 uses : dtolnay/rust-toolchain@master
4768 with :
4869 toolchain : ${{ inputs.rust }}
4970 targets : ${{ inputs.rust-target }}
50- # needed to correctly format errors, see #1865
51- components : rust-src
71+ # rust-src needed to correctly format errors, see #1865
72+ components : rust-src,llvm-tools-preview
73+
74+ # On windows 32 bit, we are running on an x64 host, so we need to specifically set the target
75+ # NB we don't do this for *all* jobs because it breaks coverage of proc macros to have an
76+ # explicit target set.
77+ - name : Set Rust target for Windows 32-bit
78+ if : inputs.os == 'windows-latest' && inputs.python-architecture == 'x86'
79+ shell : bash
80+ run : |
81+ echo "CARGO_BUILD_TARGET=i686-pc-windows-msvc" >> $GITHUB_ENV
82+
83+ # windows on arm image contains x86-64 libclang
84+ - name : Install LLVM and Clang
85+ if : inputs.os == 'windows-11-arm'
86+ uses : KyleMayes/install-llvm-action@v2
87+ with :
88+ # to match windows-2022 images
89+ version : " 18"
90+
91+ - name : Install zoneinfo backport for Python 3.7 / 3.8
92+ if : contains(fromJSON('["3.7", "3.8"]'), inputs.python-version)
93+ run : python -m pip install backports.zoneinfo
5294
5395 - uses : Swatinem/rust-cache@v2
5496 with :
55- save-if : ${{ github.event_name != 'merge_group' }}
97+ save-if : ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}
5698
5799 - if : inputs.os == 'ubuntu-latest'
58100 name : Prepare LD_LIBRARY_PATH (Ubuntu only)
@@ -66,95 +108,66 @@ jobs:
66108 name : Ignore changed error messages when using trybuild
67109 run : echo "TRYBUILD=overwrite" >> "$GITHUB_ENV"
68110
69- - if : inputs.rust == 'nightly'
70- name : Prepare to test on nightly rust
71- run : echo "MAYBE_NIGHTLY=nightly" >> "$GITHUB_ENV"
72-
73- - name : Build docs
74- run : nox -s docs
75-
76- - name : Build (no features)
77- if : ${{ !startsWith(inputs.python-version, 'graalpy') }}
78- run : cargo build --lib --tests --no-default-features
111+ - uses : dorny/paths-filter@v3
112+ if : ${{ inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') }}
113+ id : ffi-changes
114+ with :
115+ base : ${{ github.event.merge_group.base_ref }}
116+ ref : ${{ github.event.merge_group.head_ref }}
117+ filters : |
118+ changed:
119+ - 'pyo3-ffi/**'
120+ - 'pyo3-ffi-check/**'
121+ - '.github/workflows/ci.yml'
122+ - '.github/workflows/build.yml'
79123
80- # --no-default-features when used with `cargo build/test -p` doesn't seem to work!
81- - name : Build pyo3-build-config (no features)
82- run : |
83- cd pyo3-build-config
84- cargo build --no-default-features
124+ - name : Run pyo3-ffi-check
125+ # TODO: investigate graalpy failures
126+ if : ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy')) }}
127+ run : nox -s ffi-check
85128
86- # Run tests (except on PyPy, because no embedding API).
87- - if : ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }}
88- name : Test (no features)
89- run : cargo test --no-default-features --lib --tests
129+ - name : Install cargo-llvm-cov
130+ uses : taiki-e/install-action@cargo-llvm-cov
90131
91- # --no-default-features when used with `cargo build/test -p` doesn't seem to work!
92- - name : Test pyo3-build-config (no features)
132+ - name : Prepare coverage environment
93133 run : |
94- cd pyo3-build-config
95- cargo test --no-default-features
96-
97- - name : Build (all additive features)
98- if : ${{ !startsWith(inputs.python-version, 'graalpy') }}
99- run : cargo build --lib --tests --no-default-features --features "multiple-pymethods full $MAYBE_NIGHTLY"
100-
101- - if : ${{ startsWith(inputs.python-version, 'pypy') }}
102- name : Build PyPy (abi3-py39)
103- run : cargo build --lib --tests --no-default-features --features "multiple-pymethods abi3-py39 full $MAYBE_NIGHTLY"
134+ cargo llvm-cov clean --workspace --profraw-only
135+ nox -s set-coverage-env
104136
105- # Run tests (except on PyPy, because no embedding API).
106- - if : ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }}
107- name : Test
108- run : cargo test --no-default-features --features "full $MAYBE_NIGHTLY"
109-
110- # Repeat, with multiple-pymethods feature enabled (it's not entirely additive)
111- - if : ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }}
112- name : Test
113- run : cargo test --no-default-features --features "multiple-pymethods full $MAYBE_NIGHTLY"
114-
115- # Run tests again, but in abi3 mode
116- - if : ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }}
117- name : Test (abi3)
118- run : cargo test --no-default-features --features "multiple-pymethods abi3 full $MAYBE_NIGHTLY"
119-
120- # Run tests again, for abi3-py37 (the minimal Python version)
121- - if : ${{ (!startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy')) && (inputs.python-version != '3.7') }}
122- name : Test (abi3-py37)
123- run : cargo test --no-default-features --features "multiple-pymethods abi3-py37 full $MAYBE_NIGHTLY"
124-
125- - name : Test proc-macro code
126- run : cargo test --manifest-path=pyo3-macros-backend/Cargo.toml
137+ - name : Build docs
138+ run : nox -s docs
127139
128- - name : Test build config
129- run : cargo test --manifest-path=pyo3-build-config/Cargo.toml
140+ - name : Run Rust tests
141+ run : nox -s test-rust
130142
131143 - name : Test python examples and tests
132144 shell : bash
133145 run : nox -s test-py
134146 env :
135147 CARGO_TARGET_DIR : ${{ github.workspace }}/target
136148
137- - uses : dorny/paths-filter@v3
138- if : ${{ inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') }}
139- id : ffi-changes
149+ - name : Generate coverage report
150+ # needs investigation why llvm-cov fails on windows-11-arm
151+ continue-on-error : ${{ inputs.os == 'windows-11-arm' }}
152+ run : cargo llvm-cov
153+ --package=pyo3
154+ --package=pyo3-build-config
155+ --package=pyo3-macros-backend
156+ --package=pyo3-macros
157+ --package=pyo3-ffi
158+ report --codecov --output-path coverage.json
159+
160+ - name : Upload coverage report
161+ uses : codecov/codecov-action@v5
162+ # needs investigation why llvm-cov fails on windows-11-arm
163+ continue-on-error : ${{ inputs.os == 'windows-11-arm' }}
140164 with :
141- base : ${{ github.event.pull_request.base.ref || github.event.merge_group.base_ref }}
142- ref : ${{ github.event.pull_request.head.ref || github.event.merge_group.head_ref }}
143- filters : |
144- changed:
145- - 'pyo3-ffi/**'
146- - 'pyo3-ffi-check/**'
147- - '.github/workflows/ci.yml'
148- - '.github/workflows/build.yml'
149-
150- - name : Run pyo3-ffi-check
151- # pypy 3.9 on windows is not PEP 3123 compliant, nor is graalpy
152- if : ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') && !(inputs.python-version == 'pypy3.9' && contains(inputs.os, 'windows'))) }}
153- run : nox -s ffi-check
165+ files : coverage.json
166+ name : ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }}
167+ token : ${{ secrets.CODECOV_TOKEN }}
154168
155169 env :
156- CARGO_TERM_VERBOSE : true
157- CARGO_BUILD_TARGET : ${{ inputs.rust-target }}
170+ CARGO_TERM_VERBOSE : ${{ inputs.verbose }}
158171 RUST_BACKTRACE : 1
159172 RUSTFLAGS : " -D warnings"
160173 RUSTDOCFLAGS : " -D warnings"
0 commit comments