Skip to content

Add CI: strict clippy, live-Postgres test suite, mypy - #16

Merged
magi8101 merged 4 commits into
masterfrom
ci/rust-lint-python-mypy
Sep 2, 2026
Merged

magi8101 merged 4 commits into
masterfrom
ci/rust-lint-python-mypy

Conversation

@magi8101

@magi8101 magi8101 commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Rust warning cleanup (prerequisite for a real -D warnings gate): deleted 2 confirmed-dead error.rs functions, slimmed RuntimeManager to just what's used, fixed a one-line lifetime-elision hint, added an explicit #![allow(non_snake_case)] for the PostPyro module name (deliberate - has to match the Python import name).
  • .github/workflows/ci.yml: on push/PR to master. cargo check → cargo clippy --all-targets -D warnings → cargo test --lib → build via maturin develop --release against a postgres:16 service container → mypy on tests//benchmarks/ → the 3 integration test files → the concurrency correctness harness (real assertions, blocking) → the driver comparison benchmark (informational only, continue-on-error: true - timing on shared runners is too noisy to gate merges on).
  • mypy: added [tool.mypy] to pyproject.toml, scoped to tests/+benchmarks/ (the only real Python application code here - __init__.py is a pure re-export, checked via mypy_path against the .pyi stub). Fixed 3 real findings it surfaced in bench_vs_alternatives.py along the way (an untyped list, two optional-import fallback assignments).

Test plan

  • Every CI step run locally first, exactly as CI executes it: cargo check/clippy -D warnings/test --lib all clean, maturin build + wheel contents unchanged, mypy clean (5 files, 0 errors), all 3 integration tests pass live, both benchmark scripts exit 0

Cleaned up the codebase's 8 pre-existing clippy warnings first, so CI
can start with a genuine -D warnings gate instead of a lenient one:
- Deleted error.rs's type_conversion_error/invalid_connection_string_error -
  confirmed zero callers anywhere, dead since Task 2's rewrite.
- Slimmed RuntimeManager to just shared() - its runtime field and
  new()/block_on()/spawn() methods were confirmed unused everywhere
  outside their own definitions.
- Fixed the one-line lifetime-elision hint in pool.rs's connect().
- Added an explicit #![allow(non_snake_case)] at the crate root for
  the PostPyro module name - deliberate, has to match the Python
  import name (`import PostPyro`), not something to actually rename.

New .github/workflows/ci.yml, one job on push/PR to master:
cargo check -> cargo clippy --all-targets -D warnings -> cargo test
--lib -> maturin develop --release against a postgres:16 service
container -> mypy against tests/ and benchmarks/ (the only real
Python application code in this repo; __init__.py is a pure
re-export) -> the three integration test files -> the concurrency
correctness harness (real pass/fail assertions) -> the driver
comparison benchmark as an informational, non-blocking step (timing
on shared CI runners is too noisy to gate merges on).

Added a [tool.mypy] section to pyproject.toml (ignore-missing-imports
scoped to asyncpg only, which ships no stubs - psycopg's own types
resolve fine). Fixed 3 real mypy findings in bench_vs_alternatives.py
along the way: an untyped results list, and two try/except-import
fallback assignments that needed narrow type: ignore comments (a
well-known false positive for this exact optional-dependency pattern).

Every step verified locally first, exactly as CI runs it: cargo
check/clippy/test all clean, maturin build + wheel contents unchanged,
mypy clean (5 files, 0 errors), all 3 integration tests pass, both
benchmark scripts exit 0 with real numbers.

Co-Authored-By: mj7841@srmist.edu.in
Copilot AI lite review requested due to automatic review settings September 2, 2026 15:40

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 9 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 0904ed41-d062-4cdc-acdb-a2ede4a32eb3

📥 Commits

Reviewing files that changed from the base of the PR and between 6a09ee4 and bd7a1e2.

📒 Files selected for processing (8)
  • .gitguardian.yaml
  • .github/workflows/ci.yml
  • benchmarks/bench_vs_alternatives.py
  • pyproject.toml
  • src/error.rs
  • src/lib.rs
  • src/pool.rs
  • src/runtime.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gitguardian

gitguardian Bot commented Sep 2, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
19212429 Triggered Generic Password 22ed201 .github/workflows/ci.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

actions/setup-python installs Python directly, it doesn't create a
virtualenv - and maturin develop requires one (VIRTUAL_ENV set, or a
.venv it can discover) to know where to install the built extension.
The first CI run failed with exactly this: "Couldn't find a virtualenv
or conda environment". Fixed by creating one explicitly and adding its
bin/ to GITHUB_PATH plus setting VIRTUAL_ENV via GITHUB_ENV, so every
later step (pip installs, maturin develop, the test/benchmark scripts)
uses it automatically without re-sourcing activate per step.

Verified by fully simulating the fixed sequence from a genuinely clean
environment (fresh venv, env -i with only PATH/HOME/VIRTUAL_ENV set,
no inherited .venv or shell state): maturin develop --release
succeeds, and `import PostPyro` from that venv's own python3 works and
reports the right version.

Also added .gitguardian.yaml: GitGuardian flagged .github/workflows/ci.yml's
POSTGRES_PASSWORD as a secret - it's the ephemeral CI-only Postgres
service container's password (same postgres/postgres test credential
already hardcoded in every tests/*.py and benchmarks/*.py file in this
repo), not a real secret with anything to rotate. Path-scoped ignore
rather than a match-hash ignore, since generating the exact secret_sha
ggshield's match-based ignoring needs requires GitGuardian API access
this session doesn't have.

Also added continue-on-error to the benchmark-comparison-drivers pip
install step (asyncpg/psycopg) - it only feeds the one step already
marked informational/non-blocking, so a transient install hiccup
shouldn't fail the whole CI run (review finding from PR #16).

Co-Authored-By: mj7841@srmist.edu.in
The correctness-harness step just aborted on the first real CI run
(exit 134, SIGABRT) after all of its own PASS assertions already
printed - the panic happens during process exit, on a tokio-rt-worker
thread, not during the test logic itself. Hasn't reproduced locally
across 14 runs (including under taskset -c 0,1 to match a 2-core
runner), so getting a real backtrace from the environment where it
actually happens is the fastest path to a root cause. Diagnostic only,
not a fix - investigating before touching anything else.

Co-Authored-By: mj7841@srmist.edu.in
…utdown

Discovered on the first real CI run (not locally - didn't reproduce
across 44 local attempts including CPU-constrained and artificially
contended runs, but recurred on ~1 in 5 GitHub Actions runs): the
correctness harness's own logic always completed successfully (every
PASS line printed, including "pool closed cleanly"), then a Tokio
worker thread panicked during process exit and aborted (SIGABRT,
exit 134).

Root cause: the earlier Critical fix (Transaction's Drop impl,
PR #10) correctly lets an abandoned transaction's cleanup succeed
instead of panicking immediately - but the actual rollback-and-
return-connection work happens inside sqlx's own internal
`rt::spawn`, a detached fire-and-forget task nothing in this codebase
tracks or awaits. Pool.close() only waits for connections already
checked out through the normal path, not ones returning via one of
these detached background tasks. On a slower/more contended machine
(a 2-4 core CI runner vs. a fast, idle dev machine), the process can
begin exiting - and the static Tokio runtime can begin tearing down -
while one of these tasks is still mid-flight, which is what aborts.

Fix: a short bounded drain (block_on a 200ms sleep on the same
runtime) in two places - directly in Pool.close() (the exact call
site involved in the reproduction, giving lingering background
cleanup a scheduling window before close() returns), and as an
atexit-registered safety net at module init (covers the case where
close() is never called at all). This can't offer an absolute
guarantee - there's no Tokio API to wait for tasks this codebase
doesn't hold a handle to - but it converts a near-certain-under-
contention race into one that needs a cleanup task to still be
running after a 200ms grace period, which is far outside what a
single rollback-and-return-connection round trip should ever take.

Verified locally: cargo check/clippy -D warnings/test --lib all clean,
all 3 integration tests + the correctness harness pass. Verifying
against repeated CI runs next, since this doesn't reproduce locally at
all - only CI's failure rate can meaningfully confirm this actually
helps.

Co-Authored-By: mj7841@srmist.edu.in
@magi8101
magi8101 merged commit 6ae29f9 into master Sep 2, 2026
9 of 10 checks passed
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.

2 participants