Skip to content

Add upload_coverage_files for uploading coverage reports from disk - #37

Open
Aadhi-07 wants to merge 1 commit into
prooflinedev:mainfrom
Aadhi-07:upload-coverage-files
Open

Aadhi-07 wants to merge 1 commit into
prooflinedev:mainfrom
Aadhi-07:upload-coverage-files

Conversation

@Aadhi-07

@Aadhi-07 Aadhi-07 commented Nov 6, 2026

Copy link
Copy Markdown

Add upload_coverage_files for uploading coverage reports from disk

Who this helps

Anyone uploading coverage from CI. Today every caller has to read each report file, pick a unique relative name, build UploadedReport objects, and pass the commit SHA by hand (the README example uses TESTED_SHA). This adds one call that does that for them on both ProoflineClient and AsyncProoflineClient.

client.upload_coverage_files(org_id, repo_id, ["python/lcov.info", "web/lcov.info"])

What changed

  • proofline/coverage.py (new): coverage_request(paths, *, tested_sha=None, root=None) builds a CoverageUploadRequest from files.
  • proofline/client.py: upload_coverage_files on both clients. It builds the request, then calls the existing upload_coverage_reports, so transport, retries and error handling are unchanged.
  • README.md: short example under "Coverage uploads".
  • tests/test_coverage_files.py (new): 13 tests.

Decisions

  • tested_sha defaults to GITHUB_SHA. The API accepts a merge commit for a PR head, which is what GITHUB_SHA is on pull_request events, so the default works in GitHub Actions. An explicit tested_sha always wins.
  • Strict SHA check. A missing or non-40-char-lowercase-hex SHA raises ValueError before any request, instead of a server refusal after uploading up to 64 MiB.
  • Names are relative to root (default: cwd), with forward slashes. Matches the API's web/lcov.info example and gives the same names on Windows and Linux. Files outside root and duplicate names raise ValueError. I preferred failing loudly over guessing a name like the basename, which would collide in monorepos.
  • 1 to 50 reports checked client-side, matching the API's documented limit.
  • A single string path raises TypeError, since iterating it would silently treat each character as a path.
  • Async client reads files in a thread (asyncio.to_thread) so it doesn't block the event loop.
  • Left alone: generated code, upload_coverage_reports, and retry behavior.

How I verified it

  • New tests cover name resolution, the GITHUB_SHA default and override, each error case, and a request through the test server for both sync and async clients (checking path and exact JSON body). They also check that invalid input sends no request.
  • tests/test_http.py and tests/test_release_version.py pass (102 total with the new tests).
  • ruff check, ruff format --check and mypy are clean.
  • Not run: scripts/check.py and tests/test_generated_operation.py (they need the pinned generator toolchain), and no real upload against the live API since I had no token.

This branch has not been deployed

No deployments
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.

1 participant