Skip to content

Add code coverage measurement for unit and integration tests - #967

Open
roydahan wants to merge 2 commits into
scylladb:masterfrom
roydahan:claude/code-coverage-tool-plan-474b86
Open

Add code coverage measurement for unit and integration tests#967
roydahan wants to merge 2 commits into
scylladb:masterfrom
roydahan:claude/code-coverage-tool-plan-474b86

Conversation

@roydahan

@roydahan roydahan commented Aug 5, 2026

Copy link
Copy Markdown

What

Adds coverage.py-based code coverage measurement, runnable both locally and in CI, across the unit suite (all event-loop reactors) and the integration suite.

  • scripts/coverage.sh: single source of truth that wraps each existing pytest invocation (main unit run, plus one per reactor: gevent/asyncio/eventlet, plus the integration suite when SCYLLA_VERSION/CASSANDRA_VERSION is set) with coverage run, then combines and reports.
  • pyproject.toml: adds coverage[toml] as a dev dependency and [tool.coverage.*] config (branch coverage on, source=["cassandra"], HTML report to htmlcov/).
  • .github/workflows/coverage.yml: new CI job (Ubuntu, Python 3.13) that runs scripts/coverage.sh against a live Scylla, posts the text report to the job summary, and uploads htmlcov/ + coverage.xml as a build artifact. No fail_under gate yet — this establishes a baseline first.
  • CONTRIBUTING.rst / .gitignore: docs and ignores for the new script/artifacts.

Why this approach

Several core modules (cluster.py, connection.py, protocol.py, pool.py, query.py, cqltypes.py, metadata.py, util.py, concurrent.py, shard_info.py) are optionally Cython-compiled whenever Cython is importable (it's already a dev dependency). Once compiled, coverage.py can't trace into them, so scripts/coverage.sh sets CASS_DRIVER_NO_CYTHON=1 to force those specific modules to build as plain Python — the same state already exercised by the Windows/PyPy legs of cibuildwheel, with existing cythontest/notcython skip decorators degrading cleanly.

One gotcha found while validating this locally: a prior normal (Cython-enabled) build leaves .so files in place, and Python's import system prefers those over the .py source even after CASS_DRIVER_NO_CYTHON=1 is set — silently producing a false 0% report for every affected file. scripts/coverage.sh now explicitly removes stale compiled extensions and does a clean uv sync --reinstall-package before running, which was confirmed necessary and sufficient by an end-to-end local run (core modules showed real, non-trivial coverage after the fix, 0% before it).

Cython-only modules with no pure-Python fallback (obj_parser, numpy_parser, row_parser, bytesio, etc.) aren't built at all in CASS_DRIVER_NO_CYTHON=1 mode, so they remain unmeasured by this method — documented as a known limitation. Closing that gap would need Cython's own line-tracing (linetrace=True + CYTHON_TRACE=1), which adds real build complexity and is deliberately out of scope here.

Coverage results are surfaced via a GitHub Actions job summary + artifact rather than Codecov/another third-party service, to avoid needing an external account or token for this first pass.

Testing

Verified end-to-end locally (unit suite only, since no local Scylla/ccm setup): ran scripts/coverage.sh, confirmed the stale-extension issue, fixed it, and confirmed core modules report real coverage (protocol.py 69%, cqltypes.py 80%, metadata.py 55%, etc.) with htmlcov/index.html and coverage.xml generated correctly by the combined report.

Pre-review checklist

  • I have split my patch into logically separate commits.
  • All commit messages clearly explain what they change and why.
  • I added relevant tests for new features and bug fixes. (tooling change, not driver behavior)
  • All commits compile, pass static checks and pass test.
  • PR description sums up the changes and reasons why they should be introduced.
  • I have provided docstrings for the public items that I want to introduce. (no public API changes)
  • I have adjusted the documentation in ./docs/source/. (contributor-facing doc lives in CONTRIBUTING.rst instead)
  • I added appropriate Fixes: annotations to PR description. (not fixing a tracked issue)

Copilot AI balanced review requested due to automatic review settings August 5, 2026 16:26
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds coverage configuration, a local coverage script, contributor documentation, and a GitHub Actions workflow. The script runs unit and reactor-specific tests, optionally runs integration tests, and generates text, HTML, and XML reports. The workflow provisions Python, JDK, system dependencies, and Scylla before running the script. It publishes the coverage summary and report artifacts.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant uv
  participant Scylla
  participant coverage.sh
  participant CoverageReports
  GitHubActions->>uv: install tooling and sync the driver
  GitHubActions->>Scylla: provision Scylla
  GitHubActions->>coverage.sh: run coverage tests
  coverage.sh->>CoverageReports: generate coverage reports
  GitHubActions->>CoverageReports: publish summary and artifacts
Loading

Suggested reviewers: copilot, dkropachev

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding code coverage measurement for unit and integration tests.
Description check ✅ Passed The description explains the changes, rationale, testing, limitations, and checklist status in sufficient detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds coverage.py-based measurement for unit and integration tests, with local tooling, configuration, CI reporting, and contributor documentation.

Changes:

  • Adds a coverage runner that rebuilds without optional Cython modules and combines parallel test results.
  • Configures coverage reporting and CI artifact generation.
  • Documents usage and ignores generated artifacts.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/coverage.sh Runs unit/reactor and optional integration suites under coverage.
pyproject.toml Adds coverage dependency and reporting configuration.
CONTRIBUTING.rst Documents local coverage usage and limitations.
.gitignore Ignores generated coverage data and reports.
.github/workflows/coverage.yml Adds the coverage CI workflow and report artifacts.
Suppressed comments (1)

.github/workflows/coverage.yml:24

  • This filter prevents a pull request that changes only scripts/coverage.sh from validating the coverage command in CI. Since the script is the single source of truth invoked below, it must not be excluded from this workflow's PR triggers.
     - scripts/*

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/coverage.yml
Copilot AI review requested due to automatic review settings August 5, 2026 16:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
CONTRIBUTING.rst-124-125 (1)

124-125: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a supported Scylla release.

release:2025.2 has been unsupported since December 2025. Use release:2026.1, which is the CI target. (docs.scylladb.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.rst` around lines 124 - 125, Update the SCYLLA_VERSION value in
the coverage command to use the supported CI target release:2026.1 instead of
the unsupported release:2025.2, while preserving the existing integration-suite
invocation.
scripts/coverage.sh-27-47 (1)

27-47: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Generate reports after test failures.

A failing test exits under set -e before coverage combine, coverage html, and coverage xml. Record the test failure, generate reports, then exit with the recorded status.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/coverage.sh` around lines 27 - 47, The test commands in the coverage
script currently terminate execution before report generation when any test
fails. Update the test execution flow to capture the failing status without
immediate exit, always run coverage combine, report, html, and xml generation,
then exit with the recorded test status.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/coverage.yml:
- Around line 8-19: Remove the scripts/* exclusion from both paths-ignore
trigger blocks in the coverage workflow so changes to scripts/coverage.sh
trigger the workflow, while preserving all other path exclusions.

---

Other comments:
In `@CONTRIBUTING.rst`:
- Around line 124-125: Update the SCYLLA_VERSION value in the coverage command
to use the supported CI target release:2026.1 instead of the unsupported
release:2025.2, while preserving the existing integration-suite invocation.

In `@scripts/coverage.sh`:
- Around line 27-47: The test commands in the coverage script currently
terminate execution before report generation when any test fails. Update the
test execution flow to capture the failing status without immediate exit, always
run coverage combine, report, html, and xml generation, then exit with the
recorded test status.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: c29a0d89-9b07-409e-aa47-d29da8bd209d

📥 Commits

Reviewing files that changed from the base of the PR and between 1d7e601 and c0bec59.

📒 Files selected for processing (5)
  • .github/workflows/coverage.yml
  • .gitignore
  • CONTRIBUTING.rst
  • pyproject.toml
  • scripts/coverage.sh

Comment thread .github/workflows/coverage.yml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (3)

.github/workflows/coverage.yml:23

  • Ignoring scripts/* on pull requests means a PR that only changes scripts/coverage.sh will skip the only workflow that exercises that script, so broken coverage tooling can merge without pre-merge validation. Keep script changes in this workflow's path filter; the integration workflow's similar filter is not sufficient because it does not invoke this coverage wrapper.
     - scripts/*

scripts/coverage.sh:32

  • The script claims to cover all unit-test reactors, but it permanently ignores the asyncore reactor and never runs that file separately. On supported Python versions where asyncore is still available (for example 3.9–3.11), this drops all asyncore reactor coverage; on newer Python versions the file can remain in the main run and will skip itself because ASYNCCORE_AVAILABLE is false. Remove this ignore so the documented coverage scope is accurate.
    --ignore=tests/unit/io/test_asyncorereactor.py

.github/workflows/coverage.yml:85

  • always() does not preserve a report when any pytest invocation fails: set -e stops coverage.sh before coverage combine/html/xml, leaving only parallel .coverage.* files. This step then runs coverage report against the missing .coverage file, and the artifact step has no HTML/XML outputs to upload. Combine partial data and generate the outputs here so failed test runs still publish the diagnostic coverage results.
      if: always()

Copilot AI review requested due to automatic review settings August 5, 2026 21:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated no new comments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
CONTRIBUTING.rst (1)

131-137: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the stale Building the Driver reference.

The supplied CONTRIBUTING.rst has no Building the Driver section. Point this text to Dev setup or add the referenced section.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.rst` around lines 131 - 137, Update the documentation reference
in the coverage explanation to point to the existing ``Dev setup`` section
instead of the missing ``Building the Driver`` section, without changing the
surrounding guidance.
🟡 Other comments (1)
scripts/coverage.sh-39-44 (1)

39-44: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reset EVENT_LOOP_MANAGER for the default unit run.

tests/__init__.py:51 reads this variable. The first command inherits the caller's value, so EVENT_LOOP_MANAGER=gevent bash scripts/coverage.sh replaces the default run with gevent coverage. Set the variable to an empty value for the default invocation.

Proposed fix
-uv run coverage run -m pytest tests/unit -v \
+EVENT_LOOP_MANAGER= uv run coverage run -m pytest tests/unit -v \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/coverage.sh` around lines 39 - 44, Update the default unit-test
invocation in the coverage script to explicitly set EVENT_LOOP_MANAGER to an
empty value before running coverage, ensuring tests/__init__.py uses the default
event-loop manager regardless of the caller’s environment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/coverage.sh`:
- Around line 12-18: Update the coverage script’s setup and cleanup flow to fail
immediately when commands such as cd, rm, or find fail, while preserving
non-fatal handling for test and report-generation commands so the recorded test
status still reaches the final exit. Check each setup/cleanup command explicitly
or scope error suppression only to the test/report invocations, ensuring cleanup
cannot continue in an unintended directory or use stale data.

---

Outside diff comments:
In `@CONTRIBUTING.rst`:
- Around line 131-137: Update the documentation reference in the coverage
explanation to point to the existing ``Dev setup`` section instead of the
missing ``Building the Driver`` section, without changing the surrounding
guidance.

---

Other comments:
In `@scripts/coverage.sh`:
- Around line 39-44: Update the default unit-test invocation in the coverage
script to explicitly set EVENT_LOOP_MANAGER to an empty value before running
coverage, ensuring tests/__init__.py uses the default event-loop manager
regardless of the caller’s environment.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: d5cc1f82-ddf0-4502-be0f-7f7de5a22577

📥 Commits

Reviewing files that changed from the base of the PR and between 652d681 and a061057.

📒 Files selected for processing (3)
  • .github/workflows/coverage.yml
  • CONTRIBUTING.rst
  • scripts/coverage.sh
💤 Files with no reviewable changes (1)
  • .github/workflows/coverage.yml

Comment thread scripts/coverage.sh Outdated
Copilot AI review requested due to automatic review settings August 5, 2026 22:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated no new comments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
scripts/coverage.sh (3)

37-49: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the asyncore test comment.

Lines 37-39 name test_asyncorereactor.py and say it is not ignored. Lines 44 and 48 use tests/unit/io/test_asyncioreactor.py, ignore it in the main run, and execute it separately. Update the comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/coverage.sh` around lines 37 - 49, Correct the comment above the main
pytest command to reference test_asyncioreactor.py and accurately state that it
is ignored there and executed separately with the asyncio event-loop
configuration. Keep the existing test commands unchanged.

12-17: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add regression tests for the failure policy.

Cover setup and cleanup failures, test failures that still generate reports, and report failures that produce a non-zero exit status.

As per coding guidelines: “Add relevant tests for new features and bug fixes.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/coverage.sh` around lines 12 - 17, Add regression coverage for the
scripts/coverage.sh failure policy, including setup and cleanup failures, test
failures that still execute combine/report/html/xml generation, and
report-generation failures returning a non-zero status. Use isolated fixtures or
mocks around the script’s existing status handling so each scenario verifies
both report execution and the final exit status.

Source: Coding guidelines


40-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the canonical pytest options.

Add CASS_DRIVER_NO_SKIP=1 and --import-mode=append to each unit and reactor invocation. Otherwise, skipped tests remain hidden and imports may differ from the configured test commands.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/coverage.sh` around lines 40 - 49, Update every pytest invocation in
the coverage script, including the main unit run and each EVENT_LOOP_MANAGER
reactor run, to set CASS_DRIVER_NO_SKIP=1 and pass --import-mode=append while
preserving the existing test paths, ignores, and failure-status handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/coverage.sh`:
- Around line 37-49: Correct the comment above the main pytest command to
reference test_asyncioreactor.py and accurately state that it is ignored there
and executed separately with the asyncio event-loop configuration. Keep the
existing test commands unchanged.
- Around line 12-17: Add regression coverage for the scripts/coverage.sh failure
policy, including setup and cleanup failures, test failures that still execute
combine/report/html/xml generation, and report-generation failures returning a
non-zero status. Use isolated fixtures or mocks around the script’s existing
status handling so each scenario verifies both report execution and the final
exit status.
- Around line 40-49: Update every pytest invocation in the coverage script,
including the main unit run and each EVENT_LOOP_MANAGER reactor run, to set
CASS_DRIVER_NO_SKIP=1 and pass --import-mode=append while preserving the
existing test paths, ignores, and failure-status handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 161a69e4-f94c-448e-ba15-7db88e29ea0c

📥 Commits

Reviewing files that changed from the base of the PR and between a061057 and 4e595d7.

📒 Files selected for processing (1)
  • scripts/coverage.sh

Copilot AI review requested due to automatic review settings August 5, 2026 23:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 6, 2026 00:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 5 changed files in this pull request and generated no new comments.

Introduces coverage.py as the coverage tool, wrapping each existing
pytest invocation (main unit run plus one per event-loop reactor, plus
the integration suite) with `coverage run` and combining the results.

Several core modules (cluster.py, connection.py, protocol.py, etc.) are
optionally Cython-compiled by default, which coverage.py cannot trace
into, so scripts/coverage.sh forces CASS_DRIVER_NO_CYTHON=1 and cleans
any stale compiled extensions first (Python's import system otherwise
prefers a leftover .so over the .py source, silently producing a false
0% report). Cython-only modules with no .py fallback are a documented,
known gap for this method.

scripts/coverage.sh tracks test failures in $status rather than using
`set -e`, so a failing test still lets coverage combine/report/html/xml
run -- otherwise there would be no coverage output at all to diagnose
the failure with. Setup/cleanup steps before that point still fail
fast. tests/unit/io/test_asyncorereactor.py is included rather than
ignored, since it already self-skips via ASYNCCORE_AVAILABLE on Python
3.12+, where asyncore was removed from the stdlib.

The GitHub Actions workflow (.github/workflows/coverage.yml) runs this
against a live Scylla on every push/PR, posts the text report to the
job summary, and uploads the HTML/XML report as a build artifact --
surfaced this way instead of through a third-party service like
Codecov, to avoid needing an external account or token for this first
pass.

Fixes: https://scylladb.atlassian.net/browse/DRIVER-889

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@dkropachev dkropachev left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage works, but please address these issues:

  1. Add explicit coverage concurrency modes for gevent/eventlet; the default mode can produce incorrect results:

    coverage run --concurrency=gevent,thread ...
    coverage run --concurrency=eventlet,thread ...
  2. Update and commit uv.lock. uv lock --check currently fails.

  3. Avoid deleting every .so/.pyd under cassandra/; this destroys local builds for all Python versions.

  4. Set CASS_DRIVER_NO_CYTHON=1 at workflow job level. Currently the summary step rebuilds Cython extensions, wasting about two minutes.

Optional follow-up: add a coverage threshold or regression gate; the current workflow only reports coverage.

…on cleanup, job-level env

- scripts/coverage.sh: pass --concurrency=gevent,thread /
  --concurrency=eventlet,thread to the gevent/eventlet coverage runs.
  gevent/eventlet monkey-patch threading/sockets, which can confuse
  coverage.py's default sys.settrace-based collector without an explicit
  hint about the greenlet scheduler.
- scripts/coverage.sh: replace the blanket `find cassandra -name "*.so"
  -delete` with a targeted cleanup scoped to the current interpreter's
  own EXTENSION_SUFFIXES (excluding only cmurmur3/libevwrapper, which
  CASS_DRIVER_NO_CYTHON doesn't affect). The previous version also
  deleted every other local Python version's compiled extensions,
  destroying their builds unnecessarily. It also missed the Cython-only
  modules with no .py fallback (row_parser, obj_parser, ...) when an
  earlier, narrower fix only targeted the ten cythonizable .py modules
  by name -- left in place, those keep HAVE_CYTHON true off a stale .so
  and silently defeat CASS_DRIVER_NO_CYTHON entirely. Verified locally:
  the full script still produces the same ~56% baseline it did before,
  and cmurmur3/libevwrapper survive while HAVE_CYTHON correctly reads
  False during the run.
- .github/workflows/coverage.yml: set CASS_DRIVER_NO_CYTHON=1 at job
  level instead of only inside coverage.sh, so every step -- including
  "Build driver" and the summary step, both separate `uv run`
  invocations -- sees the same value instead of flipping the uv
  cache-key and triggering a full Cython rebuild between steps.
- uv.lock: commit it (was gitignored) and bring it in sync with the
  coverage[toml] dependency added earlier; `uv lock --check` now passes
  from a clean checkout.

Not doing (tracked as a deliberate follow-up, not a defect): a coverage
threshold/regression gate. This first pass establishes a baseline;
picking a threshold blind isn't useful yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@roydahan

roydahan commented Aug 6, 2026

Copy link
Copy Markdown
Author

Addressed all four required points in 5aeabcc:

  1. Concurrency modes: scripts/coverage.sh now passes --concurrency=gevent,thread / --concurrency=eventlet,thread to the respective reactor runs.
  2. uv.lock: un-gitignored and committed, brought in sync with coverage[toml]uv lock --check now passes from a clean checkout.
  3. Targeted .so cleanup: replaced the blanket find cassandra -name "*.so" -delete with a cleanup scoped to only the current interpreter's own EXTENSION_SUFFIXES (via the same mechanism tests/conftest.py already uses to detect staleness), excluding only cmurmur3/libevwrapper (unaffected by CASS_DRIVER_NO_CYTHON). Other local Python versions'/venvs' builds are no longer touched. While verifying this locally I found the initial narrower version of this fix (scoped only to the ten cythonizable .py modules by name) missed the Cython-only modules with no .py fallback (row_parser, obj_parser, ...) — left in place, those keep HAVE_CYTHON True off a stale .so and silently defeat CASS_DRIVER_NO_CYTHON entirely, so the fix now scans the whole cassandra/ tree by suffix instead of a hardcoded module list.
  4. Job-level env: CASS_DRIVER_NO_CYTHON=1 is now set once at the workflow job level rather than only inside coverage.sh, so "Build driver" and the summary step (separate uv run invocations) don't flip the uv cache-key and trigger a rebuild between them.

Verified locally end-to-end after the fixes: same ~56% baseline as before, cmurmur3/libevwrapper survive the cleanup, and HAVE_CYTHON correctly reads False during the coverage run.

On the optional follow-up (threshold/regression gate): leaving this out for now, as noted in the original PR description — this first pass establishes a baseline, and picking a threshold blind isn't useful yet. Happy to add one in a follow-up once we have a few runs of data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants