From 14c28e2764f2e7176e54813488da3cb084a5701c Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 30 Apr 2026 14:07:24 +0100 Subject: [PATCH 01/23] ci: include coverage from running build scripts --- .github/actions/prepare-coverage/action.yml | 12 +++++++ .github/actions/report-coverage/action.yml | 19 +++++++++++ .github/workflows/build.yml | 36 ++++--------------- .github/workflows/ci.yml | 30 ++++++++++++---- noxfile.py | 38 ++++++++++++++------- 5 files changed, 87 insertions(+), 48 deletions(-) create mode 100644 .github/actions/prepare-coverage/action.yml create mode 100644 .github/actions/report-coverage/action.yml diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml new file mode 100644 index 00000000000..cc7ac419149 --- /dev/null +++ b/.github/actions/prepare-coverage/action.yml @@ -0,0 +1,12 @@ +name: 'Prepare coverage' +description: 'Installs cargo-llvm-cov and prepares the environment for coverage collection' +runs: + using: "composite" + steps: + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + - name: Prepare coverage environment + shell: bash + run: | + cargo llvm-cov clean --workspace --profraw-only + uvx nox -s set-coverage-env diff --git a/.github/actions/report-coverage/action.yml b/.github/actions/report-coverage/action.yml new file mode 100644 index 00000000000..ce17fa3060c --- /dev/null +++ b/.github/actions/report-coverage/action.yml @@ -0,0 +1,19 @@ +name: 'Report coverage' +description: 'Generate coverage report using cargo-llvm-cov and upload it to Codecov' +inputs: + name: + description: 'The name of the coverage report' + required: true +runs: + using: "composite" + steps: + - name: Generate coverage report + shell: bash + run: uvx nox -s generate-coverage-report + + - name: Upload coverage report + uses: codecov/codecov-action@v6 + with: + files: coverage.json + name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3e14d7f3ed..dade1e31fe1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,9 @@ on: workflow_call: inputs: + sha: + required: true + type: string os: required: true type: string @@ -34,14 +37,7 @@ jobs: steps: - uses: actions/checkout@v6.0.2 with: - # For PRs, we need to run on the real PR head, not the resultant merge of the PR into the target branch. - # - # This is necessary for coverage reporting to make sense; we then get exactly the coverage change - # between the base branch and the real PR head. - # - # If it were run on the merge commit the problem is that the coverage potentially does not align - # with the commit diff, because the merge may affect line numbers. - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + ref: ${{ inputs.sha }} # installs using setup-python do not work for arm macOS 3.9 and below - if: ${{ !(inputs.os == 'macos-latest' && contains(fromJSON('["3.8", "3.9"]'), inputs.python-version) && inputs.python-architecture == 'x64') }} @@ -119,13 +115,7 @@ jobs: if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy')) }} run: nox -s ffi-check - - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov - - - name: Prepare coverage environment - run: | - cargo llvm-cov clean --workspace --profraw-only - nox -s set-coverage-env + - uses: ./.github/actions/prepare-coverage - name: Build docs run: nox -s docs @@ -139,25 +129,11 @@ jobs: env: CARGO_TARGET_DIR: ${{ github.workspace }}/target - - name: Generate coverage report - # needs investigation why llvm-cov fails on windows-11-arm - continue-on-error: ${{ inputs.os == 'windows-11-arm' }} - run: cargo llvm-cov - --package=pyo3 - --package=pyo3-build-config - --package=pyo3-macros-backend - --package=pyo3-macros - --package=pyo3-ffi - report --codecov --output-path coverage.json - - - name: Upload coverage report - uses: codecov/codecov-action@v6 + - uses: ./.github/actions/report-coverage # needs investigation why llvm-cov fails on windows-11-arm continue-on-error: ${{ inputs.os == 'windows-11-arm' }} with: - files: coverage.json name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} - token: ${{ secrets.CODECOV_TOKEN }} env: CARGO_TERM_VERBOSE: ${{ inputs.verbose }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a8e2bddee..7704e9bd8e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ concurrency: env: CARGO_TERM_COLOR: always + NOX_DEFAULT_VENV_BACKEND: uv jobs: fmt: @@ -37,6 +38,15 @@ jobs: outputs: MSRV: ${{ steps.resolve-msrv.outputs.MSRV }} verbose: ${{ runner.debug == '1' }} + save-cache: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }} + # For PRs, we need to run on the real PR head, not the resultant merge of the PR into the target branch. + # + # This is necessary for coverage reporting to make sense; we then get exactly the coverage change + # between the base branch and the real PR head. + # + # If it were run on the merge commit the problem is that the coverage potentially does not align + # with the commit diff, because the merge may affect line numbers. + coverage-sha: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} steps: - uses: actions/checkout@v6.0.2 - uses: actions/setup-python@v6 @@ -136,6 +146,7 @@ jobs: needs: [fmt, resolve] uses: ./.github/workflows/build.yml with: + sha: ${{ needs.resolve.outputs.coverage-sha }} os: ${{ matrix.platform.os }} python-version: ${{ matrix.python-version }} python-architecture: ${{ matrix.platform.python-architecture }} @@ -211,6 +222,7 @@ jobs: needs: [fmt, resolve] uses: ./.github/workflows/build.yml with: + sha: ${{ needs.resolve.outputs.coverage-sha }} os: ${{ matrix.platform.os }} python-version: ${{ matrix.python-version }} python-architecture: ${{ matrix.platform.python-architecture }} @@ -581,20 +593,26 @@ jobs: - run: python3 -m nox -s test test-version-limits: - needs: [fmt] + needs: [fmt, resolve] if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v6.0.2 - - uses: actions/setup-python@v6 with: - python-version: "3.14" + ref: ${{ needs.resolve.outputs.coverage-sha }} + - uses: astral-sh/setup-uv@v7 + with: + save-cache: ${{ needs.resolve.outputs.save-cache }} + - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 with: - save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }} + save-if: ${{ needs.resolve.outputs.save-cache }} - uses: dtolnay/rust-toolchain@stable - - run: python3 -m pip install --upgrade pip && pip install nox[uv] - - run: python3 -m nox -s test-version-limits + - uses: ./.github/actions/prepare-coverage + - run: uvx nox -s test-version-limits + - uses: ./.github/actions/report-coverage + with: + name: test-version-limits check-feature-powerset: needs: [fmt, resolve] diff --git a/noxfile.py b/noxfile.py index b7130b30d4c..9a444efbcd5 100644 --- a/noxfile.py +++ b/noxfile.py @@ -51,8 +51,16 @@ FREE_THREADED_BUILD = bool(sysconfig.get_config_var("Py_GIL_DISABLED")) -def _get_output(*args: str) -> str: - return subprocess.run(args, capture_output=True, text=True, check=True).stdout +def _get_output(*args: str, env: Optional[Dict[str, str]] = None) -> str: + try: + return subprocess.run( + args, capture_output=True, text=True, check=True, stdin=None, env=env + ).stdout + except subprocess.CalledProcessError as e: + print(f"Command {args} failed with exit code {e.returncode}") + print(f"stdout:\n{e.stdout}") + print(f"stderr:\n{e.stderr}") + raise nox.command.CommandFailed() from e def _parse_supported_interpreter_version( @@ -174,12 +182,16 @@ def set_coverage_env(session: nox.Session) -> None: @nox.session(name="generate-coverage-report", venv_backend="none") def generate_coverage_report(session: nox.Session) -> None: - cov_format = "codecov" - output_file = "coverage.json" - if "lcov" in session.posargs: - cov_format = "lcov" - output_file = "lcov.info" + args = ("--lcov", "--output-path=lcov.info") + + elif "html" in session.posargs: + args = ("--html",) + else: + args = ( + "--codecov", + "--output-path=coverage.json", + ) _run_cargo( session, @@ -189,10 +201,9 @@ def generate_coverage_report(session: nox.Session) -> None: "--package=pyo3-macros-backend", "--package=pyo3-macros", "--package=pyo3-ffi", + "--include-build-script", "report", - f"--{cov_format}", - "--output-path", - output_file, + *args, ) @@ -1509,9 +1520,12 @@ def _get_feature_sets() -> Tuple[Optional[str], ...]: def _get_coverage_env() -> Dict[str, str]: - env = {} - output = _get_output("cargo", "llvm-cov", "show-env") + llvm_cov_execution_env = os.environ.copy() + # prevent llvm-cov from hanging asking to install llvm-tools-preview + llvm_cov_execution_env["CARGO_LLVM_COV_SETUP"] = "no" + output = _get_output("cargo", "llvm-cov", "show-env", env=llvm_cov_execution_env) + env = {} for line in output.strip().splitlines(): (key, value) = line.split("=", maxsplit=1) # Strip single or double quotes from the variable value From 490c1bf922c42f504a254b8a8cbd5a8068711b0c Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 30 Apr 2026 14:32:13 +0100 Subject: [PATCH 02/23] fix passing codecov token to report-coverage action --- .github/actions/report-coverage/action.yml | 7 +++++-- .github/workflows/build.yml | 1 + .github/workflows/ci.yml | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/report-coverage/action.yml b/.github/actions/report-coverage/action.yml index ce17fa3060c..3c9a1e2d5dc 100644 --- a/.github/actions/report-coverage/action.yml +++ b/.github/actions/report-coverage/action.yml @@ -4,6 +4,9 @@ inputs: name: description: 'The name of the coverage report' required: true + token: + description: 'Codecov upload token' + required: true runs: using: "composite" steps: @@ -15,5 +18,5 @@ runs: uses: codecov/codecov-action@v6 with: files: coverage.json - name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} - token: ${{ secrets.CODECOV_TOKEN }} + name: ${{ inputs.name }} + token: ${{ inputs.token }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dade1e31fe1..b99e30b03e1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -134,6 +134,7 @@ jobs: continue-on-error: ${{ inputs.os == 'windows-11-arm' }} with: name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} + token: ${{ secrets.CODECOV_TOKEN }} env: CARGO_TERM_VERBOSE: ${{ inputs.verbose }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7704e9bd8e3..3cd54328794 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -613,6 +613,7 @@ jobs: - uses: ./.github/actions/report-coverage with: name: test-version-limits + token: ${{ secrets.GITHUB_TOKEN }} check-feature-powerset: needs: [fmt, resolve] From 67199cb90c2f858ad45c3b1d2db9af73c81eb5ee Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 30 Apr 2026 15:05:17 +0100 Subject: [PATCH 03/23] completely skip coverage on windows-11-arm for now --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b99e30b03e1..a004d74e91d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,6 +116,7 @@ jobs: run: nox -s ffi-check - uses: ./.github/actions/prepare-coverage + if: ${{ inputs.os == 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 - name: Build docs run: nox -s docs @@ -130,8 +131,7 @@ jobs: CARGO_TARGET_DIR: ${{ github.workspace }}/target - uses: ./.github/actions/report-coverage - # needs investigation why llvm-cov fails on windows-11-arm - continue-on-error: ${{ inputs.os == 'windows-11-arm' }} + if: ${{ inputs.os == 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 with: name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} token: ${{ secrets.CODECOV_TOKEN }} From e9702f09671dea2609b34f5050bdf0bb1afc6e88 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 30 Apr 2026 15:49:55 +0100 Subject: [PATCH 04/23] correct condition --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a004d74e91d..82ee7b8335d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,7 +116,7 @@ jobs: run: nox -s ffi-check - uses: ./.github/actions/prepare-coverage - if: ${{ inputs.os == 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 + if: ${{ inputs.os != 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 - name: Build docs run: nox -s docs @@ -131,7 +131,7 @@ jobs: CARGO_TARGET_DIR: ${{ github.workspace }}/target - uses: ./.github/actions/report-coverage - if: ${{ inputs.os == 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 + if: ${{ inputs.os != 'windows-11-arm' }} # https://github.com/rust-lang/rust/issues/150123 with: name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }} token: ${{ secrets.CODECOV_TOKEN }} From 3adeaad605e1f645e178b8ce8155c4fd3ed309a6 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 2 May 2026 10:46:16 +0100 Subject: [PATCH 05/23] fixups, add coverage to cross-compilation jobs --- .github/workflows/ci.yml | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cd54328794..a091ac066dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ concurrency: env: CARGO_TERM_COLOR: always NOX_DEFAULT_VENV_BACKEND: uv + UV_PYTHON: 3.14 jobs: fmt: @@ -604,6 +605,8 @@ jobs: with: save-cache: ${{ needs.resolve.outputs.save-cache }} - uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview - uses: Swatinem/rust-cache@v2 with: save-if: ${{ needs.resolve.outputs.save-cache }} @@ -612,7 +615,7 @@ jobs: - run: uvx nox -s test-version-limits - uses: ./.github/actions/report-coverage with: - name: test-version-limits + name: ${{ github.job }} token: ${{ secrets.GITHUB_TOKEN }} check-feature-powerset: @@ -686,6 +689,7 @@ jobs: - name: Setup cross-compiler if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }} run: sudo apt-get install -y mingw-w64 llvm + - uses: ./.github/actions/prepare-coverage - name: Compile version-specific library uses: PyO3/maturin-action@v1 with: @@ -698,31 +702,38 @@ jobs: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux }} args: --release -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }} + - uses: ./.github/actions/report-coverage + with: + name: ${{ github.job }} + token: ${{ secrets.GITHUB_TOKEN }} test-cross-compilation-windows: - needs: [fmt] + needs: [fmt, resolve] if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v6.0.2 - - uses: actions/setup-python@v6 + - uses: astral-sh/setup-uv@v7 with: - python-version: "3.14" + save-cache: ${{ needs.resolve.outputs.save-cache }} - uses: dtolnay/rust-toolchain@stable with: targets: x86_64-pc-windows-gnu,x86_64-pc-windows-msvc - components: rust-src + components: rust-src,llvm-tools-preview # load cache (prepared in ci-cache-warmup.yml) - uses: actions/cache/restore@v5 with: path: ~/.cache/cargo-xwin key: cargo-xwin-cache + - name: Setup cross-compiler + run: sudo apt-get install -y mingw-w64 llvm + - uses: ./.github/actions/prepare-coverage - name: Test cross compile to Windows - run: | - set -ex - sudo apt-get install -y mingw-w64 llvm - pip install nox - nox -s test-cross-compilation-windows + run: uvx nox -s test-cross-compilation-windows + - uses: ./.github/actions/report-coverage + with: + name: ${{ github.job }} + token: ${{ secrets.GITHUB_TOKEN }} test-introspection: needs: [fmt] From 23e26e59543fcaba15f0f8149404390cf09a63e0 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 2 May 2026 12:20:48 +0100 Subject: [PATCH 06/23] install uv in cross compilation job --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a091ac066dc..9d3f6bfff0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -678,9 +678,11 @@ jobs: flags: "-i python3.13 --features pyo3/generate-import-lib" steps: - uses: actions/checkout@v6.0.2 - - uses: actions/setup-python@v6 + - uses: astral-sh/setup-uv@v7 with: - python-version: "3.14" + save-cache: ${{ needs.resolve.outputs.save-cache }} + # so that maturin-action will pick up the installed Python from uv + activate-environment: true - uses: Swatinem/rust-cache@v2 with: workspaces: examples/maturin-starter From b41d039ae6d7fbb42851922cd8a68f73ba4d5f06 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 9 May 2026 19:25:46 +0100 Subject: [PATCH 07/23] cleanups, try cargo-llvm-cov branch --- .github/actions/prepare-coverage/action.yml | 15 +++++++++++++-- .github/workflows/build.yml | 2 +- .github/workflows/ci.yml | 4 +--- noxfile.py | 11 +++++++---- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index cc7ac419149..b70628863bd 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -1,12 +1,23 @@ name: 'Prepare coverage' description: 'Installs cargo-llvm-cov and prepares the environment for coverage collection' +inputs: + host_only: + description: 'Whether to prepare the environment for host-only coverage collection' + required: false + default: "false" runs: using: "composite" steps: - name: Install cargo-llvm-cov - uses: taiki-e/install-action@cargo-llvm-cov + # FIXME: install test branch, should revert to install-action before merge + # uses: taiki-e/install-action@cargo-llvm-cov + run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only + shell: bash + - name: Prepare coverage environment shell: bash run: | cargo llvm-cov clean --workspace --profraw-only - uvx nox -s set-coverage-env + uvx nox -s set-coverage-env -- ${{ inputs.host_only && --coverage-host-only || "" }} + env: + CARGO_LLVM_COV_SETUP: "yes" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 82ee7b8335d..040f1db18b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,7 +66,7 @@ jobs: toolchain: ${{ inputs.rust }} targets: ${{ inputs.rust-target }} # rust-src needed to correctly format errors, see #1865 - components: rust-src,llvm-tools-preview + components: rust-src # On windows 32 bit, we are running on an x64 host, so we need to specifically set the target # NB we don't do this for *all* jobs because it breaks coverage of proc macros to have an diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d3f6bfff0d..3d0fb1365d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -605,8 +605,6 @@ jobs: with: save-cache: ${{ needs.resolve.outputs.save-cache }} - uses: dtolnay/rust-toolchain@stable - with: - components: llvm-tools-preview - uses: Swatinem/rust-cache@v2 with: save-if: ${{ needs.resolve.outputs.save-cache }} @@ -721,7 +719,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable with: targets: x86_64-pc-windows-gnu,x86_64-pc-windows-msvc - components: rust-src,llvm-tools-preview + components: rust-src # load cache (prepared in ci-cache-warmup.yml) - uses: actions/cache/restore@v5 with: diff --git a/noxfile.py b/noxfile.py index 9a444efbcd5..b62a5972a23 100644 --- a/noxfile.py +++ b/noxfile.py @@ -176,7 +176,7 @@ def coverage(session: nox.Session) -> None: def set_coverage_env(session: nox.Session) -> None: """For use in GitHub Actions to set coverage environment variables.""" with open(os.environ["GITHUB_ENV"], "a") as env_file: - for k, v in _get_coverage_env().items(): + for k, v in _get_coverage_env(*session.posargs).items(): print(f"{k}={v}", file=env_file) @@ -1519,11 +1519,14 @@ def _get_feature_sets() -> Tuple[Optional[str], ...]: _HOST_LINE_START = "host: " -def _get_coverage_env() -> Dict[str, str]: +def _get_coverage_env(*flags: str) -> Dict[str, str]: llvm_cov_execution_env = os.environ.copy() # prevent llvm-cov from hanging asking to install llvm-tools-preview - llvm_cov_execution_env["CARGO_LLVM_COV_SETUP"] = "no" - output = _get_output("cargo", "llvm-cov", "show-env", env=llvm_cov_execution_env) + # (allow user to override this, if they wish, e.g. in CI) + llvm_cov_execution_env.setdefault("CARGO_LLVM_COV_SETUP", "no") + output = _get_output( + "cargo", "llvm-cov", "show-env", *flags, env=llvm_cov_execution_env + ) env = {} for line in output.strip().splitlines(): From 6227adb0c2a868c2a8ae19c065c50ded8e8c0c92 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sun, 10 May 2026 11:35:00 +0100 Subject: [PATCH 08/23] fix typo --- .github/actions/prepare-coverage/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index b70628863bd..0aee98120ca 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -18,6 +18,6 @@ runs: shell: bash run: | cargo llvm-cov clean --workspace --profraw-only - uvx nox -s set-coverage-env -- ${{ inputs.host_only && --coverage-host-only || "" }} + uvx nox -s set-coverage-env -- ${{ inputs.host_only && '--coverage-host-only' || '' }} env: CARGO_LLVM_COV_SETUP: "yes" From 86254cfa95eb5a54700894257ab02b0f8376b5a8 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sun, 10 May 2026 20:17:46 +0100 Subject: [PATCH 09/23] specify package to install for testing --- .github/actions/prepare-coverage/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index 0aee98120ca..da0468e7a84 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -11,7 +11,7 @@ runs: - name: Install cargo-llvm-cov # FIXME: install test branch, should revert to install-action before merge # uses: taiki-e/install-action@cargo-llvm-cov - run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only + run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only cargo--llvm-cov shell: bash - name: Prepare coverage environment From 818ee2c5ba6c6842cd4f7b129104c7fe20091ca4 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Mon, 11 May 2026 07:38:13 +0100 Subject: [PATCH 10/23] typo --- .github/actions/prepare-coverage/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index da0468e7a84..3f742322444 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -11,7 +11,7 @@ runs: - name: Install cargo-llvm-cov # FIXME: install test branch, should revert to install-action before merge # uses: taiki-e/install-action@cargo-llvm-cov - run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only cargo--llvm-cov + run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only cargo-llvm-cov shell: bash - name: Prepare coverage environment From 676f93bd94bf84b9fe5902cece7de221a3065819 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Mon, 11 May 2026 08:56:37 +0100 Subject: [PATCH 11/23] fixup cross compile step --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d0fb1365d8..390cae0cf5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -679,8 +679,9 @@ jobs: - uses: astral-sh/setup-uv@v7 with: save-cache: ${{ needs.resolve.outputs.save-cache }} - # so that maturin-action will pick up the installed Python from uv - activate-environment: true + - uses: actions/setup-python@v6 + with: + python-version: ${{ env.UV_PYTHON }} - uses: Swatinem/rust-cache@v2 with: workspaces: examples/maturin-starter From d2506ce575211d5242f3b153fd27e9ae7aff8014 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Mon, 11 May 2026 09:58:48 +0100 Subject: [PATCH 12/23] switch cross-compilation jobs to debug --- .github/actions/report-coverage/action.yml | 2 +- .github/workflows/ci.yml | 4 ++-- noxfile.py | 14 +++----------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/actions/report-coverage/action.yml b/.github/actions/report-coverage/action.yml index 3c9a1e2d5dc..257edd782c3 100644 --- a/.github/actions/report-coverage/action.yml +++ b/.github/actions/report-coverage/action.yml @@ -12,7 +12,7 @@ runs: steps: - name: Generate coverage report shell: bash - run: uvx nox -s generate-coverage-report + run: uvx nox -s generate-coverage-report -- --codecov --output-path=coverage.json - name: Upload coverage report uses: codecov/codecov-action@v6 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 390cae0cf5f..2c68445f888 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -696,13 +696,13 @@ jobs: with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux }} - args: --release -m examples/maturin-starter/Cargo.toml ${{ matrix.flags }} + args: --profile=dev -m examples/maturin-starter/Cargo.toml ${{ matrix.flags }} - name: Compile abi3 library uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux }} - args: --release -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }} + args: --profile=dev -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }} - uses: ./.github/actions/report-coverage with: name: ${{ github.job }} diff --git a/noxfile.py b/noxfile.py index b62a5972a23..c1e14b56b2a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -182,16 +182,8 @@ def set_coverage_env(session: nox.Session) -> None: @nox.session(name="generate-coverage-report", venv_backend="none") def generate_coverage_report(session: nox.Session) -> None: - if "lcov" in session.posargs: - args = ("--lcov", "--output-path=lcov.info") - - elif "html" in session.posargs: - args = ("--html",) - else: - args = ( - "--codecov", - "--output-path=coverage.json", - ) + # default to `--html` report if no additional arguments provided (convenient for local use) + posargs = ("--html",) if not session.posargs else tuple(session.posargs) _run_cargo( session, @@ -203,7 +195,7 @@ def generate_coverage_report(session: nox.Session) -> None: "--package=pyo3-ffi", "--include-build-script", "report", - *args, + *posargs, ) From 70a2e433356816e65a033d5c3592df0511a9f921 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Mon, 11 May 2026 10:54:19 +0100 Subject: [PATCH 13/23] skip containers for cross compile tests --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c68445f888..4d2b5430999 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -659,12 +659,10 @@ jobs: - os: "ubuntu-latest" target: "x86_64-unknown-linux-gnu" flags: "-i python3.13" - manylinux: auto # ubuntu x86_64 -> aarch64 - os: "ubuntu-latest" target: "aarch64-unknown-linux-gnu" flags: "-i python3.13" - manylinux: auto # ubuntu x86_64 -> windows x86_64 - os: "ubuntu-latest" target: "x86_64-pc-windows-gnu" @@ -695,14 +693,14 @@ jobs: uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} - manylinux: ${{ matrix.manylinux }} args: --profile=dev -m examples/maturin-starter/Cargo.toml ${{ matrix.flags }} + container: off - name: Compile abi3 library uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} - manylinux: ${{ matrix.manylinux }} args: --profile=dev -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }} + container: off - uses: ./.github/actions/report-coverage with: name: ${{ github.job }} From dcdf44da5629da88fca38a997691fc6f0ba12c0a Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 12 May 2026 11:18:25 +0100 Subject: [PATCH 14/23] fixups --- .github/actions/prepare-coverage/action.yml | 2 +- .github/workflows/ci.yml | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index 3f742322444..e03a04cdecc 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -17,7 +17,7 @@ runs: - name: Prepare coverage environment shell: bash run: | - cargo llvm-cov clean --workspace --profraw-only + cargo llvm-cov clean --workspace uvx nox -s set-coverage-env -- ${{ inputs.host_only && '--coverage-host-only' || '' }} env: CARGO_LLVM_COV_SETUP: "yes" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e654efbb559..baeab0e91a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -699,11 +699,13 @@ jobs: - os: "ubuntu-latest" target: "aarch64-unknown-linux-gnu" flags: "-i python3.13" + apt-packages: gcc-aarch64-linux-gnu # ubuntu x86_64 -> windows x86_64 - os: "ubuntu-latest" target: "x86_64-pc-windows-gnu" # TODO: remove pyo3/generate-import-lib feature when maturin supports cross compiling to Windows without it flags: "-i python3.13 --features pyo3/generate-import-lib" + apt-packages: mingw-w64 llvm # windows x86_64 -> aarch64 - os: "windows-latest" target: "aarch64-pc-windows-msvc" @@ -721,9 +723,9 @@ jobs: workspaces: examples/maturin-starter save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }} key: ${{ matrix.target }} - - name: Setup cross-compiler - if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }} - run: sudo apt-get install -y mingw-w64 llvm + - name: Setup cross-compiler packages + if: ${{ matrix.apt-packages }} + run: sudo apt-get install -y ${{ matrix.apt-packages }} - uses: ./.github/actions/prepare-coverage - name: Compile version-specific library uses: PyO3/maturin-action@v1 @@ -740,7 +742,7 @@ jobs: - uses: ./.github/actions/report-coverage with: name: ${{ github.job }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} test-cross-compilation-windows: needs: [fmt, resolve] @@ -768,7 +770,7 @@ jobs: - uses: ./.github/actions/report-coverage with: name: ${{ github.job }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} test-introspection: needs: [fmt] From 3a5f4d41654f9b39216d3726991a1acde4bda988 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 12 May 2026 11:38:38 +0100 Subject: [PATCH 15/23] set linker for cross-compilation job --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index baeab0e91a1..a53944f2fd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -686,6 +686,8 @@ jobs: if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} runs-on: ${{ matrix.os }} name: test-cross-compilation ${{ matrix.os }} -> ${{ matrix.target }} + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc 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') }} From d8948a4a427acee2a028e61d52991f5cf34789ab Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 12 May 2026 12:08:25 +0100 Subject: [PATCH 16/23] correct secret --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a53944f2fd9..a1fd78fba02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -650,7 +650,7 @@ jobs: - uses: ./.github/actions/report-coverage with: name: ${{ github.job }} - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} check-feature-powerset: needs: [fmt, resolve] From f8d0550f2840daa59d6985187c64448820cbc7d8 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Tue, 12 May 2026 12:09:52 +0100 Subject: [PATCH 17/23] fixup report names --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1fd78fba02..7b7f639ad8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -743,7 +743,7 @@ jobs: container: off - uses: ./.github/actions/report-coverage with: - name: ${{ github.job }} + name: ${{ github.job }}/${{ matrix.os }}/${{ matrix.target }} token: ${{ secrets.CODECOV_TOKEN }} test-cross-compilation-windows: From 27a1bc4f164836068601fedb1d212f619a7f9373 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Wed, 13 May 2026 09:10:55 +0100 Subject: [PATCH 18/23] use released cargo-llvm-cov --- .github/actions/prepare-coverage/action.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index e03a04cdecc..493a0c83a03 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -9,10 +9,7 @@ runs: using: "composite" steps: - name: Install cargo-llvm-cov - # FIXME: install test branch, should revert to install-action before merge - # uses: taiki-e/install-action@cargo-llvm-cov - run: cargo install --git https://github.com/davidhewitt/cargo-llvm-cov --branch coverage-host-only cargo-llvm-cov - shell: bash + uses: taiki-e/install-action@cargo-llvm-cov - name: Prepare coverage environment shell: bash From 2e2f8497f785869edcdec7cc265f0cccab358f57 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 16 May 2026 14:36:13 +0100 Subject: [PATCH 19/23] Apply suggestions from code review Co-authored-by: Nathan Goldbaum Co-authored-by: David Hewitt --- .github/actions/prepare-coverage/action.yml | 2 +- .github/workflows/ci.yml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/actions/prepare-coverage/action.yml b/.github/actions/prepare-coverage/action.yml index 493a0c83a03..78333d7bdbf 100644 --- a/.github/actions/prepare-coverage/action.yml +++ b/.github/actions/prepare-coverage/action.yml @@ -15,6 +15,6 @@ runs: shell: bash run: | cargo llvm-cov clean --workspace - uvx nox -s set-coverage-env -- ${{ inputs.host_only && '--coverage-host-only' || '' }} + uvx nox -s set-coverage-env -- ${{ inputs.host_only == 'true' && '--coverage-host-only' || '' }} env: CARGO_LLVM_COV_SETUP: "yes" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b7f639ad8b..feebdbe6505 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -644,7 +644,6 @@ jobs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ needs.resolve.outputs.save-cache }} - - uses: dtolnay/rust-toolchain@stable - uses: ./.github/actions/prepare-coverage - run: uvx nox -s test-version-limits - uses: ./.github/actions/report-coverage @@ -682,7 +681,7 @@ jobs: - run: python3 -m nox -s check-feature-powerset -- ${{ matrix.rust != 'stable' && 'minimal-versions' || '' }} test-cross-compilation: - needs: [fmt] + needs: [fmt, resolve] if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} runs-on: ${{ matrix.os }} name: test-cross-compilation ${{ matrix.os }} -> ${{ matrix.target }} From 45145411aae12487e572ee611ff44562b3cabe0e Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 16 May 2026 15:02:43 +0100 Subject: [PATCH 20/23] try running in container --- .github/workflows/ci.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index feebdbe6505..8dc7a443f5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -696,6 +696,7 @@ jobs: - os: "ubuntu-latest" target: "x86_64-unknown-linux-gnu" flags: "-i python3.13" + manylinux: auto # ubuntu x86_64 -> aarch64 - os: "ubuntu-latest" target: "aarch64-unknown-linux-gnu" @@ -733,13 +734,25 @@ jobs: with: target: ${{ matrix.target }} args: --profile=dev -m examples/maturin-starter/Cargo.toml ${{ matrix.flags }} - container: off + manylinux: ${{ matrix.manylinux }} + docker-options: >- + -e LLVM_PROFILE_FILE + -e __CARGO_LLVM_COV_RUSTC_WRAPPER + -e __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS + -e __CARGO_LLVM_COV_RUSTC_WRAPPER_CRATE_NAMES + -v /home/runner/.cargo/bin/cargo-llvm-cov:/home/runner/.cargo/bin/cargo-llvm-cov - name: Compile abi3 library uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} args: --profile=dev -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }} - container: off + manylinux: ${{ matrix.manylinux }} + docker-options: >- + -e LLVM_PROFILE_FILE + -e __CARGO_LLVM_COV_RUSTC_WRAPPER + -e __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS + -e __CARGO_LLVM_COV_RUSTC_WRAPPER_CRATE_NAMES + -v /home/runner/.cargo/bin/cargo-llvm-cov:/home/runner/.cargo/bin/cargo-llvm-cov - uses: ./.github/actions/report-coverage with: name: ${{ github.job }}/${{ matrix.os }}/${{ matrix.target }} From 64136c164781183d7470fc3ce2cd1067f01d6197 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 16 May 2026 18:12:25 +0100 Subject: [PATCH 21/23] fixup cross-compilation --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8dc7a443f5e..f709c05b25a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -685,8 +685,6 @@ jobs: if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }} runs-on: ${{ matrix.os }} name: test-cross-compilation ${{ matrix.os }} -> ${{ matrix.target }} - env: - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc 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') }} @@ -701,7 +699,7 @@ jobs: - os: "ubuntu-latest" target: "aarch64-unknown-linux-gnu" flags: "-i python3.13" - apt-packages: gcc-aarch64-linux-gnu + manylinux: auto # ubuntu x86_64 -> windows x86_64 - os: "ubuntu-latest" target: "x86_64-pc-windows-gnu" From 4a2cc4cc03320d35397d62e1b605dfa432adcbb9 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 16 May 2026 19:02:26 +0100 Subject: [PATCH 22/23] cross compilation host coverage only --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f709c05b25a..ff967e0caff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -727,6 +727,8 @@ jobs: if: ${{ matrix.apt-packages }} run: sudo apt-get install -y ${{ matrix.apt-packages }} - uses: ./.github/actions/prepare-coverage + with: + host_only: true - name: Compile version-specific library uses: PyO3/maturin-action@v1 with: From 1bb798477113d9eddc3b528f1cff119d74972f69 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 16 May 2026 20:15:35 +0100 Subject: [PATCH 23/23] final tidy ups --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff967e0caff..ccb9ce3ec28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -712,6 +712,8 @@ jobs: flags: "-i python3.13 --features pyo3/generate-import-lib" steps: - uses: actions/checkout@v6.0.2 + with: + ref: ${{ needs.resolve.outputs.coverage-sha }} - uses: astral-sh/setup-uv@v7 with: save-cache: ${{ needs.resolve.outputs.save-cache }} @@ -764,6 +766,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6.0.2 + with: + ref: ${{ needs.resolve.outputs.coverage-sha }} - uses: astral-sh/setup-uv@v7 with: save-cache: ${{ needs.resolve.outputs.save-cache }} @@ -779,6 +783,8 @@ jobs: - name: Setup cross-compiler run: sudo apt-get install -y mingw-w64 llvm - uses: ./.github/actions/prepare-coverage + with: + host_only: true - name: Test cross compile to Windows run: uvx nox -s test-cross-compilation-windows - uses: ./.github/actions/report-coverage