Skip to content

ci: wire up Codecov uploads and update CODEOWNERS - #143

Merged
farhadrgh merged 4 commits into
mainfrom
farhadr/codecov-upload
Sep 16, 2026
Merged

farhadrgh merged 4 commits into
mainfrom
farhadr/codecov-upload

Conversation

@farhadrgh

@farhadrgh farhadrgh commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

The Codecov app is installed but receives nothing. pyproject's pytest addopts already run --cov=nvsubquadratic --cov-report=term, so coverage is computed on every gpu-tests run and then discarded to the log.

Two things made this non-obvious. pytest runs inside the CI container via docker run --rm, so a report written in the container disappears with it — the coverage directory has to be a bind mount. And the image runs as USER ubuntu (Dockerfile:218), whose uid need not match the runner's, so the mount point is chmod 777 rather than relying on a uid match.

Only --cov-report=xml is added on the command line; --cov and the term report stay in pyproject so local runs are unchanged and CI logs keep the summary.

The upload is deliberately incapable of failing the job: continue-on-error plus fail_ci_if_error: false. gpu-tests is a required status check that takes ~36 minutes on a single self-hosted runner, and a Codecov outage or a missing CODECOV_TOKEN is not worth blocking a merge over. If the token secret is absent the action falls back to tokenless upload, which works for public repos.

Also gitignores the coverage/ directory the job creates in the workspace; .gitignore already covered .coverage and a bare coverage.xml but not the directory.

Summary

Environment setup

Create the conda environment (required to run tests):

bash setup_conda_env.sh
conda activate nvsubquadratic

Test plan

  • pre-commit run --all-files passes (pre-commit install if not yet set up).
  • Existing tests pass (pytest tests/).
  • New tests added, or explain why not needed:

Documentation checklist

For every new or modified public symbol in nvsubquadratic/ or experiments/:

  • Every new module has a module-level docstring explaining what it contains and why.
  • Every new public class has a class docstring covering purpose, math/motivation, and key attributes.
  • Every new public method / function has Args: and Returns: blocks with tensor shapes where applicable.
  • Math notation is consistent with the paper (or a comment explains any deviation).
  • Docstrings containing backslashes use r"""...""" (required by ruff D301).
  • If a new file was added, a row has been added to docs-tracker.md with status [x].

See CONVENTIONS.md for the full style guide.

Summary by CodeRabbit

  • Tests

    • GPU test runs now generate XML coverage reports.
    • Coverage results are uploaded automatically when available, while reporting issues remain non-blocking and do not prevent test completion.
  • Chores

    • Generated coverage directories are now excluded from version control, keeping working trees and project changes cleaner.

The Codecov app is installed but receives nothing. pyproject's pytest addopts
already run --cov=nvsubquadratic --cov-report=term, so coverage is computed on
every gpu-tests run and then discarded to the log.

Two things made this non-obvious. pytest runs inside the CI container via
`docker run --rm`, so a report written in the container disappears with it — the
coverage directory has to be a bind mount. And the image runs as USER ubuntu
(Dockerfile:218), whose uid need not match the runner's, so the mount point is
chmod 777 rather than relying on a uid match.

Only --cov-report=xml is added on the command line; --cov and the term report
stay in pyproject so local runs are unchanged and CI logs keep the summary.

The upload is deliberately incapable of failing the job: `continue-on-error`
plus `fail_ci_if_error: false`. gpu-tests is a required status check that takes
~36 minutes on a single self-hosted runner, and a Codecov outage or a missing
CODECOV_TOKEN is not worth blocking a merge over. If the token secret is absent
the action falls back to tokenless upload, which works for public repos.

Also gitignores the `coverage/` directory the job creates in the workspace;
.gitignore already covered `.coverage` and a bare `coverage.xml` but not the
directory.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Farhad Ramezanghorbani <farhadr@nvidia.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Enterprise

Run ID: 7780fc62-6075-48c9-a539-544f5adec6cc

📥 Commits

Reviewing files that changed from the base of the PR and between c1884cb and 03e9ae3.

📒 Files selected for processing (1)
  • .github/CODEOWNERS

Included review availability: Your plan provides up to 12 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The GPU test workflow now generates an XML coverage report in a mounted directory and uploads it to Codecov without failing the workflow. Git ignores the coverage directory. CODEOWNERS now assigns owners to subquadratic-ops paths and tests.

Changes

GPU coverage reporting

Layer / File(s) Summary
Coverage generation and upload
.github/workflows/gpu-tests.yml, .gitignore
The GPU pytest step writes XML coverage output to a writable mounted directory. A non-blocking Codecov upload runs regardless of prior step status. The coverage/ directory is ignored by Git.

Subquadratic-ops ownership

Layer / File(s) Summary
Ownership rules
.github/CODEOWNERS
CODEOWNERS entries cover subquadratic-ops wrappers, lowering, modules, and related tests. The entries assign the default owners and an upstream maintainer.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to 03e9a

The PR adds non-blocking coverage reporting and ownership metadata without a supported merge-blocking behavior change.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
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.
Title check ✅ Passed The title clearly identifies the two main changes: Codecov uploads and CODEOWNERS updates. It is concise and specific.
Description check ✅ Passed The description provides a detailed summary, implementation rationale, environment setup, and relevant coverage behavior. The template remains partially incomplete: the Summary placeholder is unchange…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch farhadr/codecov-upload

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

@moradza maintains the upstream subquadratic-ops package, so a change to the
wrapper layer that binds to it — dtype/shape marshalling, the arch gating, the
torch.compile lowering he rewrote — should reach him automatically rather than
by someone remembering to add him.

He is listed alongside the default owners rather than instead of them. GitHub
requires an approving review from at least one codeowner per changed file, so
this auto-requests his review without making him a hard blocker when he is away,
and without preventing @farhadrgh from self-approving. Listing @moradza alone on
a line would make his approval mandatory for that path; the comment in the file
records that as the deliberate alternative.

Verified: @moradza has write access, and all 12 paths exist at this commit.

Bundled with the Codecov change because gpu-tests.yml has a bare `pull_request:`
trigger with no path filter, so every PR — including a CODEOWNERS-only one —
costs a ~36-minute run on the single self-hosted runner. Two config PRs would
pay that twice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Farhad Ramezanghorbani <farhadr@nvidia.com>
@farhadrgh farhadrgh changed the title ci: upload coverage to Codecov from the GPU test job ci: wire up Codecov uploads and route subq-ops changes to @moradza Sep 16, 2026
farhadrgh and others added 2 commits September 16, 2026 13:48
Adds ownership for the two experiment families:

- ImageNet / ViT5 (benchmarks/vit5_imagenet, examples/imagenet_classification,
  examples/vit5_imagenet, the profiling report, and the two imagenet
  datamodules) -> @Dafidofff and @moradza.
- Spatial recall (examples/spatial_recall_{1d,2d,3d,v2}, reports/spatial_recall,
  spatial_recall_dataset.py and its motion test) -> @dwromero and @Dafidofff.

All 13 paths verified to exist at this commit. As with the subq-ops rules, each
line lists the new owners ALONGSIDE the defaults, so their review is
auto-requested without making any one person a merge blocker.

Two things recorded in the file because both fail silently:

- @dwromero and @Dafidofff currently have `read` access. GitHub ignores a
  CODEOWNERS entry for a user without write access — no auto-request, no
  required review, and no hard error. These rules stay inert until someone
  grants them write. @moradza already has it.
- @Dafidofff is David Wessels. A separate @dwessels account exists and is not
  him; naming it would produce a rule that never fires.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Farhad Ramezanghorbani <farhadr@nvidia.com>
@farhadrgh farhadrgh changed the title ci: wire up Codecov uploads and route subq-ops changes to @moradza ci: wire up Codecov uploads and update CODEOWNERS Sep 16, 2026
farhadrgh added a commit that referenced this pull request Sep 16, 2026
gpu-tests has a bare `pull_request:` trigger, so a PR touching only docs or repo
config costs ~36 minutes on the single self-hosted runner. PR #142
(.coderabbit.yaml + a template) and #143 (CODEOWNERS + .gitignore) both paid it.

The obvious fix is wrong, and the file already says so at the top: `gpu-tests`
is a required status check, and a path-filtered required check never reports on
non-matching PRs, leaving them unmergeable forever. So the job still runs on
every PR and still reports; what it skips is the expensive work.

A scope step diffs against the PR base and gates the buildx/GHCR/build/pytest/CP
steps. Fail-safe by construction: the suite is skipped only when EVERY changed
file matches a known-inert pattern, so an unrecognised path — a new source
directory, say — always runs. This workflow itself, Dockerfile, pyproject.toml
and requirements* are deliberately not inert.

Implemented with shell `case` globs rather than a regex. The first version used
`grep -qvE` and appeared to misclassify mixed docs+source PRs as skippable. That
turned out to be a local artifact — `grep` on this workstation is a function
wrapping ugrep, which returns 1 from `-v` even when it matches — but the lesson
stands: logic guarding a required check should not depend on which grep the
runner provides.

Verified by extracting the step's actual script and running it against real
inputs: docs+source, PR #143's file list, Dockerfile, pyproject, requirements
and an unknown path all produce needed=true; PR #142's list, docs-only and
README-only produce needed=false.

Also requires fetch-depth: 0 on checkout so the base diff resolves.

Signed-off-by: Farhad Ramezanghorbani <farhadr@nvidia.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@farhadrgh
farhadrgh merged commit dcf169c into main Sep 16, 2026
8 checks passed
@farhadrgh
farhadrgh deleted the farhadr/codecov-upload branch September 16, 2026 20:34
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