Skip to content

Fix changed-file code quality checks - #2178

Merged
j-rausch merged 2 commits into
feature/puzzletron_v2from
jrausch/modelopt-diff-gate-correction
Aug 12, 2026
Merged

Fix changed-file code quality checks#2178
j-rausch merged 2 commits into
feature/puzzletron_v2from
jrausch/modelopt-diff-gate-correction

Conversation

@j-rausch

@j-rausch j-rausch commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: Bug fix

The changed-file code-quality job currently reads the pull request base SHA from the event payload. That value can lag the synthetic merge checked out for a run, causing target-only files and inherited mypy diagnostics to be attributed to an unrelated pull request.

This change binds the comparison to the checked-out merge's first parent, pins the mypy hook dependencies used by the diff session, and compares normalized base and head diagnostics so only newly introduced errors fail the gate. Renames and copies are handled explicitly, and repository-controlled paths are separated from mypy options.

Testing

The code-quality workflow gains focused coverage for merge-parent selection, changed-file status handling, rename-aware diagnostic comparison, multiplicity, dependency pinning, and option-safe paths.

Summary by CodeRabbit

  • Bug Fixes

    • Improved pull request type-checking to compare the correct merge snapshots.
    • Added support for detecting changes across added, modified, renamed, and copied Python files.
    • Type-check results now highlight only newly introduced diagnostics while preserving existing issues.
  • Chores

    • Improved pre-commit type-checking setup with required type stubs and dependencies.
    • Added comprehensive automated coverage for pull request quality checks.
    • Updated test configuration for more reliable project-wide test discovery.

Use the checked-out synthetic merge parent and compare base/head mypy diagnostics so stale payload bases and inherited errors cannot fail unrelated pull requests.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch
j-rausch requested a review from a team as a code owner August 12, 2026 17:03
@j-rausch
j-rausch requested review from kevalmorabia97 and removed request for a team August 12, 2026 17:03
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cb7289b6-8542-4a76-a7b6-455a839e06ec

📥 Commits

Reviewing files that changed from the base of the PR and between 29f89db and ecf3791.

📒 Files selected for processing (3)
  • noxfile.py
  • pyproject.toml
  • tests/unit/tools/ci/test_mypy_diff.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/tools/ci/test_mypy_diff.py
  • noxfile.py

📝 Walkthrough

Walkthrough

The PR replaces payload-based mypy diffing with merge-parent comparison. It adds Git-aware changed-file tracking, isolated base and head mypy runs, rename-aware diagnostic filtering, and CI and pre-commit validation.

Changes

Mypy quality ratchet

Layer / File(s) Summary
CI and pre-commit entry points
.github/workflows/code_quality.yml, .pre-commit-config.yaml, noxfile.py, pyproject.toml
CI compares HEAD^1 with HEAD. The mypy hook disables automatic type-package installation and pins required typing dependencies. pre_commit_diff invokes the changed-file ratchet. Pytest includes the project root in its Python path.
Changed-file and diagnostic comparison
noxfile.py, tests/unit/tools/ci/test_mypy_diff.py
The implementation parses Git status and mypy output, tracks modified, added, renamed, and copied Python files, and filters inherited diagnostics by occurrence. Tests cover status parsing, diagnostic filtering, and path separation.
Isolated base and head checks
noxfile.py, tests/unit/tools/ci/test_mypy_diff.py
The check resolves commits, runs mypy in temporary base and head checkouts with isolated caches, maps renamed paths, and reports new diagnostics. Tests cover merge-parent selection and CI and pre-commit configuration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Mergeability Score: ⚪ Minimal · up to ecf37

This PR corrects changed-file code-quality comparisons and adds focused coverage; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant CodeQualityWorkflow
  participant pre_commit_diff
  participant GitRepository
  participant mypy
  CodeQualityWorkflow->>pre_commit_diff: invoke changed-file mypy check
  pre_commit_diff->>GitRepository: resolve HEAD^1 and HEAD
  pre_commit_diff->>GitRepository: create base and head checkouts
  pre_commit_diff->>mypy: run checks for changed Python files
  mypy-->>pre_commit_diff: return diagnostics
  pre_commit_diff-->>CodeQualityWorkflow: fail when new diagnostics exist
Loading

Possibly related PRs

Suggested reviewers: kevalmorabia97

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change to changed-file code-quality checks.
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.
Security Anti-Patterns ✅ Passed The complete PR range changes no modelopt or examples Python files, adds no pyproject.toml/requirements dependencies, and adds no listed security bypass patterns.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jrausch/modelopt-diff-gate-correction

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

🧹 Nitpick comments (4)
tests/unit/tools/ci/test_mypy_diff.py (3)

45-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the rejection branch.

_parse_changed_python_files raises ValueError for unsupported git name-status lines at noxfile.py line 292. No test covers that branch. A malformed status line would then fail the whole CI lane with an unclear error.

A single negative case documents the contract.

🧪 Suggested additional test
import pytest


def test_parse_changed_python_files_rejects_unsupported_status():
    with pytest.raises(ValueError, match="Unsupported git name-status line"):
        _parse_changed_python_files("D\tdeleted.py")
🤖 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 `@tests/unit/tools/ci/test_mypy_diff.py` around lines 45 - 62, Add a negative
test for _parse_changed_python_files that passes an unsupported status line such
as “D\tdeleted.py” and asserts pytest.raises(ValueError, match="Unsupported git
name-status line").

137-158: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Bind the assertion to the literal HEAD^1 expression.

The test computes current_base by recording the target-branch SHA before the merge. The workflow instead passes HEAD^1 at .github/workflows/code_quality.yml line 41. The test therefore validates the premise but not the expression the workflow uses.

Resolving merge_head^1 in the test ties the two together. A future change to first-parent selection then fails this test.

🧪 Suggested assertion
     _git(tmp_path, "merge", "--no-ff", "topic", "-m", "synthetic pull request merge")
     merge_head = _git(tmp_path, "rev-parse", "HEAD")
+
+    # The workflow passes HEAD^1; confirm it resolves to the recorded target snapshot.
+    assert _git(tmp_path, "rev-parse", f"{merge_head}^1") == current_base
🤖 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 `@tests/unit/tools/ci/test_mypy_diff.py` around lines 137 - 158, Update the
test around current_base and merge_head to derive the exact-base comparison from
merge_head^1 (HEAD^1) after the synthetic merge, rather than capturing the
pre-merge SHA separately. Keep the stale_base comparison unchanged and use the
resolved first-parent SHA when constructing exact_output so the test remains
bound to the workflow expression.

166-179: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert configuration structure instead of exact substrings and pinned versions.

Both tests match raw file text. Two problems follow.

First, the assertions break on formatting changes that do not change behavior. A reflowed args list or a re-quoted run line fails the test.

Second, test_mypy_hook_pins_stubs_and_disables_automatic_installation asserts exact versions of nox, types-docutils, and types-PyYAML. Every routine dependency bump then fails this test. The useful invariant is that each dependency carries a == pin, not that it carries one specific version. As written the test blocks upgrades rather than protecting against a regression.

Parse the YAML and assert on the resolved structure.

🧪 Suggested structural assertions
import yaml


def test_mypy_hook_pins_stubs_and_disables_automatic_installation():
    config = yaml.safe_load(
        (REPOSITORY_ROOT / ".pre-commit-config.yaml").read_text(encoding="utf-8")
    )
    hook = next(
        hook
        for repo in config["repos"]
        for hook in repo["hooks"]
        if hook["id"] == "mypy"
    )

    assert "--no-install-types" in hook["args"]
    dependencies = hook["additional_dependencies"]
    assert {name.split("==")[0] for name in dependencies} == {
        "nox",
        "types-docutils",
        "types-PyYAML",
    }
    # Every stub dependency must be pinned so hook runs stay reproducible.
    assert all("==" in name for name in dependencies)

As per path instructions, "checked-in tests should be lean and document expected behavior, protect against regressions, or flag backward-incompatible changes".

🤖 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 `@tests/unit/tools/ci/test_mypy_diff.py` around lines 166 - 179, Update the
configuration tests to parse YAML with yaml.safe_load and assert resolved
structure rather than raw text. In
test_code_quality_uses_checked_out_pull_request_merge_parent, inspect the parsed
workflow command while preserving the HEAD^1/HEAD behavior and rejecting
github.event.pull_request.base.sha. In
test_mypy_hook_pins_stubs_and_disables_automatic_installation, locate the hook
by id "mypy", verify --no-install-types, require the expected dependency names,
and assert every dependency uses a == pin without hard-coding versions.

Source: Path instructions

noxfile.py (1)

366-367: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Document the base-versus-head contract of _run_changed_file_mypy.

Add a short docstring stating that the helper runs mypy on both snapshots and reports only new diagnostics. Keep --follow-imports=skip; the previous pre_commit_diff implementation already used this option, so this change preserves the existing behavior.

🤖 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 `@noxfile.py` around lines 366 - 367, Add a concise docstring to the
_run_changed_file_mypy helper documenting that it runs mypy against both base
and head snapshots and reports only newly introduced diagnostics. Preserve the
existing --follow-imports=skip option and related behavior unchanged.
🤖 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 `@tests/unit/tools/ci/test_mypy_diff.py`:
- Around line 24-31: Update the pytest configuration in pyproject.toml to
include the repository root alongside tests/ in pythonpath, so direct collection
of test_mypy_diff.py can resolve imports from noxfile.

---

Nitpick comments:
In `@noxfile.py`:
- Around line 366-367: Add a concise docstring to the _run_changed_file_mypy
helper documenting that it runs mypy against both base and head snapshots and
reports only newly introduced diagnostics. Preserve the existing
--follow-imports=skip option and related behavior unchanged.

In `@tests/unit/tools/ci/test_mypy_diff.py`:
- Around line 45-62: Add a negative test for _parse_changed_python_files that
passes an unsupported status line such as “D\tdeleted.py” and asserts
pytest.raises(ValueError, match="Unsupported git name-status line").
- Around line 137-158: Update the test around current_base and merge_head to
derive the exact-base comparison from merge_head^1 (HEAD^1) after the synthetic
merge, rather than capturing the pre-merge SHA separately. Keep the stale_base
comparison unchanged and use the resolved first-parent SHA when constructing
exact_output so the test remains bound to the workflow expression.
- Around line 166-179: Update the configuration tests to parse YAML with
yaml.safe_load and assert resolved structure rather than raw text. In
test_code_quality_uses_checked_out_pull_request_merge_parent, inspect the parsed
workflow command while preserving the HEAD^1/HEAD behavior and rejecting
github.event.pull_request.base.sha. In
test_mypy_hook_pins_stubs_and_disables_automatic_installation, locate the hook
by id "mypy", verify --no-install-types, require the expected dependency names,
and assert every dependency uses a == pin without hard-coding versions.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c1275020-d00b-4b3e-bd35-fc5bc9809b8c

📥 Commits

Reviewing files that changed from the base of the PR and between 2d8d307 and 29f89db.

📒 Files selected for processing (4)
  • .github/workflows/code_quality.yml
  • .pre-commit-config.yaml
  • noxfile.py
  • tests/unit/tools/ci/test_mypy_diff.py

Comment thread tests/unit/tools/ci/test_mypy_diff.py
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.38%. Comparing base (2d8d307) to head (ecf3791).
⚠️ Report is 1 commits behind head on feature/puzzletron_v2.

Additional details and impacted files
@@                    Coverage Diff                    @@
##           feature/puzzletron_v2    #2178      +/-   ##
=========================================================
+ Coverage                  53.15%   62.38%   +9.22%     
=========================================================
  Files                        704      705       +1     
  Lines                      91506    91574      +68     
=========================================================
+ Hits                       48640    57126    +8486     
+ Misses                     42866    34448    -8418     
Flag Coverage Δ
examples 29.63% <ø> (?)
gpu 23.32% <ø> (?)
puzzletron 31.42% <ø> (ø)
regression 8.97% <ø> (?)
unit 29.54% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Keep direct pytest collection aligned with the documented invocation and preserve the mypy hook arguments while allowing routine pinned dependency updates.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch
j-rausch merged commit 5da9a05 into feature/puzzletron_v2 Aug 12, 2026
51 of 52 checks passed
@j-rausch
j-rausch deleted the jrausch/modelopt-diff-gate-correction branch August 12, 2026 22:28
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-12 22:28 UTC

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