Skip to content

fix(pr-bot): classify renames of core paths as core#506

Open
galuis116 wants to merge 3 commits into
vouchdev:testfrom
galuis116:fix/pr-bot-rename-classification-bypass
Open

fix(pr-bot): classify renames of core paths as core#506
galuis116 wants to merge 3 commits into
vouchdev:testfrom
galuis116:fix/pr-bot-rename-classification-bypass

Conversation

@galuis116

@galuis116 galuis116 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What changed

trust-gate.yml, auto-merge.yml, and comment-command.yml now build the
changed-file list from the REST pulls/{n}/files endpoint
(gh api repos/{o}/{r}/pulls/{n}/files --paginate) instead of
gh pr view --json files, and feed both the new and pre-rename filename
into pr_bot's classification. A new pr_bot changed-files subcommand
flattens that REST payload (filename + previous_filename when present)
into the plain one-path-per-line format the rest of pr_bot already
consumes.

Why

gh pr view --json files is backed by the GraphQL PullRequestFile type,
which carries only path/additions/deletions — no previous-filename
field. When GitHub detects a rename, only the new path appears in that
list. pr_bot._match() matches CORE_GLOBS entries by exact path, so
git mv src/vouch/http_server.py src/vouch/web_server.py (plus any edit
inside it) made the changed core file invisible to classification:
trust-gate.yml reported "untrusted author, no core paths touched — ok",
and the renamed PR was eligible for auto-merge arming as klass=code
instead of being permanently blocked as klass=core — a bypass of the
one detection mechanism that's supposed to guarantee "a PR touching [a
core path] needs the owner's review and is never merged by automation"
(pr_bot.py's own docstring).

The REST files endpoint does populate previous_filename on renamed
entries, so switching the source and folding both filenames into the
classified list closes the gap without changing pr_bot's classification
logic itself.

Fixes #505

What might break

Nothing for users with an existing .vouch/ directory — this only touches
CI workflow files and pr_bot.py's CLI surface (classify,
core-touched, should-arm all behave identically for non-renamed file
lists; the new changed-files subcommand is additive). No kb.* method,
object model, or on-disk shape changes.

VEP

Not applicable — no object model, kb.* method, on-disk layout, bundle
format, or audit-log shape change. This is CI-workflow and pr_bot.py
CLI-surface logic only, and this PR itself touches .github/** /
pr_bot.py (both CORE_GLOBS paths), so per the trust-gate's own rule it
needs owner review and cannot self-auto-merge.

Tests

  • make check locally: ruff clean; mypy clean on pr_bot.py; all 25
    tests/test_pr_bot.py cases pass (21 pre-existing + 4 new)
  • New / changed behaviour has a test — test_extract_changed_paths_plain_file,
    test_extract_changed_paths_includes_previous_filename_on_rename,
    test_rename_of_core_path_still_classifies_core,
    test_cli_changed_files_emits_previous_filename
  • CHANGELOG.md updated under ## [Unreleased]
  • the three edited workflow YAML files parse cleanly (yaml.safe_load)

Summary by CodeRabbit

  • New Features

    • Added a deterministic changed-files mode to output newline-delimited changed paths for a pull request from a provided file-list payload.
  • Bug Fixes

    • Improved changed-file detection for renamed files by using the GitHub REST file list (with pagination).
    • Core-path validation now recognizes both the original and updated names, preventing renamed core files from bypassing checks.
    • Trust-gate and auto-merge classification now rely on the more complete changed-file list.
  • Documentation

    • Updated the changelog to reflect the renamed-file core-path fix.

trust-gate.yml, auto-merge.yml, and comment-command.yml built the
changed-file list from `gh pr view --json files`, which is backed by
the GraphQL PullRequestFile type and carries no previous-filename
field. When GitHub detects a rename, only the new path appears there,
so `git mv src/vouch/http_server.py src/vouch/web_server.py` (plus any
edit inside it) made the changed core file invisible to pr_bot's exact-
match CORE_GLOBS check: trust-gate reported no core paths touched for
an untrusted author, and the PR was eligible for auto-merge arming as
klass=code instead of being permanently blocked as klass=core.

switch all three workflows to the REST pulls/{n}/files endpoint, which
does populate previous_filename on renamed entries, and add a
`changed-files` pr_bot subcommand that flattens that payload into both
the new and previous filename so a rename can no longer drop a core
path off the radar.

Fixes vouchdev#505
@galuis116
galuis116 requested a review from plind-junior as a code owner July 16, 2026 04:21
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changed-file extraction now uses GitHub’s paginated REST pull-request files endpoint and preserves both current and previous filenames for renames. Three workflows invoke the new CLI command before existing classification and gating logic.

Changes

Rename-aware classification

Layer / File(s) Summary
Path extraction and CLI validation
src/vouch/pr_bot.py, tests/test_pr_bot.py
Adds changed-files, emits renamed and previous paths, and tests extraction, core classification, and CLI output.
Workflow REST integration
.github/workflows/*.yml, CHANGELOG.md
Updates auto-merge, comment-command, and trust-gate workflows to consume paginated REST file data and documents the rename fix.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • vouchdev/vouch#487: Updates related changed-file classification logic in the auto-merge workflow.

Suggested labels: cli

Suggested reviewers: plind-junior

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving core classification for renamed paths.
Linked Issues check ✅ Passed The workflows and CLI now use REST file data plus previous_filename, so renamed core paths stay classified as core as required by #505.
Out of Scope Changes check ✅ Passed Changes stay focused on the rename-classification fix, related tests, workflow wiring, and changelog notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions github-actions Bot added docs documentation, specs, examples, and repo guidance ci github actions and automation tests tests and fixtures size: S 50-199 changed non-doc lines labels Jul 16, 2026
@plind-junior
plind-junior enabled auto-merge July 16, 2026 07:04
@plind-junior plind-junior added the auto-merge owner-authorized: arm native auto-merge for non-core PRs label Jul 16, 2026
…lassification-bypass

# Conflicts:
#	.github/workflows/comment-command.yml
auto-merge was automatically disabled July 16, 2026 14:23

Head branch was pushed to by a user without write access

@github-actions github-actions Bot removed the auto-merge owner-authorized: arm native auto-merge for non-core PRs label Jul 16, 2026
@github-actions

Copy link
Copy Markdown

new commits were pushed after authorization, so the prior verification no longer matches the head. auto-merge is disarmed and the label removed — re-authorize (add the auto-merge label or comment /auto-merge) to re-verify the new commits.

@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

🤖 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 `@src/vouch/pr_bot.py`:
- Around line 171-178: Update the docstring near the REST files payload
flattening logic to use lowercase prose throughout, including its descriptive
sentences and references to callers. Preserve the existing technical terms,
command examples, and behavior documentation unchanged.
🪄 Autofix (Beta)

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: Pro Plus

Run ID: 161634fc-2a41-4137-9ae7-5988e842fcfd

📥 Commits

Reviewing files that changed from the base of the PR and between bfb6b0a and 24f8e4f.

📒 Files selected for processing (6)
  • .github/workflows/auto-merge.yml
  • .github/workflows/comment-command.yml
  • .github/workflows/trust-gate.yml
  • CHANGELOG.md
  • src/vouch/pr_bot.py
  • tests/test_pr_bot.py

Comment thread src/vouch/pr_bot.py Outdated
Comment on lines +171 to +178
"""Flatten a REST ``/pulls/{n}/files`` payload into a path list.

Emits both ``filename`` and, for a renamed entry, ``previous_filename`` —
a rename that lands a core path under a new name must still classify as
core. ``gh pr view --json files`` (the GraphQL-backed shortcut) carries no
previous-filename field and silently drops this; callers must use the
REST files endpoint (``gh api repos/{o}/{r}/pulls/{n}/files``) instead.
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use lowercase prose in the docstring.

The docstring uses standard capitalization, which violates the repository's convention. As per path instructions for src/vouch/**, use lowercase prose in comments and review notes.

♻️ Proposed fix
-    """Flatten a REST ``/pulls/{n}/files`` payload into a path list.
-
-    Emits both ``filename`` and, for a renamed entry, ``previous_filename`` —
-    a rename that lands a core path under a new name must still classify as
-    core. ``gh pr view --json files`` (the GraphQL-backed shortcut) carries no
-    previous-filename field and silently drops this; callers must use the
-    REST files endpoint (``gh api repos/{o}/{r}/pulls/{n}/files``) instead.
-    """
+    """flatten a rest ``/pulls/{n}/files`` payload into a path list.
+
+    emits both ``filename`` and, for a renamed entry, ``previous_filename`` —
+    a rename that lands a core path under a new name must still classify as
+    core. ``gh pr view --json files`` (the graphql-backed shortcut) carries no
+    previous-filename field and silently drops this; callers must use the
+    rest files endpoint (``gh api repos/{o}/{r}/pulls/{n}/files``) instead.
+    """
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"""Flatten a REST ``/pulls/{n}/files`` payload into a path list.
Emits both ``filename`` and, for a renamed entry, ``previous_filename``
a rename that lands a core path under a new name must still classify as
core. ``gh pr view --json files`` (the GraphQL-backed shortcut) carries no
previous-filename field and silently drops this; callers must use the
REST files endpoint (``gh api repos/{o}/{r}/pulls/{n}/files``) instead.
"""
"""flatten a rest ``/pulls/{n}/files`` payload into a path list.
emits both ``filename`` and, for a renamed entry, ``previous_filename``
a rename that lands a core path under a new name must still classify as
core. ``gh pr view --json files`` (the graphql-backed shortcut) carries no
previous-filename field and silently drops this; callers must use the
rest files endpoint (``gh api repos/{o}/{r}/pulls/{n}/files``) instead.
"""
🤖 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 `@src/vouch/pr_bot.py` around lines 171 - 178, Update the docstring near the
REST files payload flattening logic to use lowercase prose throughout, including
its descriptive sentences and references to callers. Preserve the existing
technical terms, command examples, and behavior documentation unchanged.

Source: Path instructions

@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 (1)
src/vouch/pr_bot.py (1)

170-189: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

handle paginated files payloads consistently.

the workflows write gh api ... --paginate output straight to files.json, so multi-page prs produce multiple json arrays here. json.loads() will fail on that shape, and changed-file classification will break for larger prs. add --slurp at the call sites or flatten page arrays in extract_changed_paths() before parsing.

🤖 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 `@src/vouch/pr_bot.py` around lines 170 - 189, Update extract_changed_paths to
accept paginated REST output containing multiple JSON arrays, flattening all
page entries before collecting filename and previous_filename values. Preserve
handling of the existing single-array payload and the rename path behavior, or
alternatively add --slurp consistently at every workflow call site that writes
files.json.

Source: MCP tools

🤖 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 `@src/vouch/pr_bot.py`:
- Around line 170-189: Update extract_changed_paths to accept paginated REST
output containing multiple JSON arrays, flattening all page entries before
collecting filename and previous_filename values. Preserve handling of the
existing single-array payload and the rename path behavior, or alternatively add
--slurp consistently at every workflow call site that writes files.json.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 764c3541-bc67-4147-8b6a-929edecfb885

📥 Commits

Reviewing files that changed from the base of the PR and between 24f8e4f and 0ab0e14.

📒 Files selected for processing (1)
  • src/vouch/pr_bot.py

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

Labels

ci github actions and automation docs documentation, specs, examples, and repo guidance size: S 50-199 changed non-doc lines tests tests and fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants