Add 'collect codereview' command: build dataset entries from real PRs#749
Merged
Conversation
Harvest a real PR diff as the patch and its inline comments as expected_comments; --reviewer keeps one author's findings, --reacted keeps positively-reacted ones (drops thumbs-down as FP guards by omission). Relax ReviewComment.file to allow spaces in paths. Serves ADO 643360 + 643361.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds collection of code-review dataset entries from real GitHub pull requests.
Changes:
- Adds reviewer and reaction-based comment harvesting.
- Adds GitHub APIs for merge bases, comments, and reactions.
- Supports spaces in reviewed file paths.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tests/test_collect_codereview.py |
Tests parsing and comment selection. |
src/bcbench/dataset/codereview.py |
Allows spaces in review paths. |
src/bcbench/commands/collect.py |
Registers the new CLI command. |
src/bcbench/collection/gh_client.py |
Adds required GitHub API operations. |
src/bcbench/collection/collect_codereview.py |
Builds and saves code-review entries. |
src/bcbench/collection/__init__.py |
Exports collection helpers. |
Real reviewer-bot comments escape the severity/domain header (Severity\ -\ Performance), so the header regex missed domain. Prefer the <!-- agent_domain: X --> marker the bot always appends; fall back to header parsing for human comments.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (3)
src/bcbench/collection/gh_client.py:89
gh api --paginateemits one JSON array per page, sojson.loads(result.stdout)raisesJSONDecodeError: Extra dataas soon as a PR has more than one page of review comments. Slurp the pages and flatten the outer array before parsing so this method actually returns all comments as documented.
"--paginate",
src/bcbench/collection/gh_client.py:105
- This has the same pagination parsing failure as the review-comments endpoint: comments with more than one page of reactions produce concatenated JSON arrays, which
json.loadscannot parse. Flatten the paginated output into one array.
"--paginate",
src/bcbench/collection/collect_codereview.py:90
- Falling back to
original_linere-admits exactly the outdated comments this function says it skips. GitHub keepsoriginal_linepopulated when the currentlinebecomes null, but that old location is relative to an earlier head and may no longer identify an issue in the collected final patch. Use only the current line fields so outdated findings cannot corrupt the gold set.
line = comment.get("line") or comment.get("original_line")
if not line:
return None # outdated / unanchored comment
start = comment.get("start_line") or comment.get("original_start_line")
…se-insensitive reviewer, remove unused global - gh_client: add --slurp so multi-page comment/reaction results parse (json.loads previously failed on concatenated page arrays). - _comment_line_span: use only current line/start_line; drop original_line fallback that re-admitted outdated comments at stale coordinates. - build_expected_comments: case-insensitive reviewer login match. - Remove unused module-level _config (CodeQL); clarify --reacted is any-author (combine with --reviewer for bot-only). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 74500e3e-0905-4f26-a2f4-3e6208c4fec2
build_expected_comments and parse_domain_severity are internal helpers (unit-tested directly via the submodule, no package-level consumer). Match the collect_gh convention of exporting only public entry-points. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 74500e3e-0905-4f26-a2f4-3e6208c4fec2
- parse_domain_severity: prefer an explicit (minor)/(major) tag or a '<sev> Severity' header over the first severity-like word in prose, so a word inside a title (e.g. 'high' in 'high-impact') no longer overrides the annotated severity. - collect_codereview_entry: in --reacted mode, pre-filter comments (reviewer, placeable line span, non-empty body) before calling the reactions API, so review-heavy PRs no longer spend a request per comment and risk rate limits. - collect codereview command: catch CollectionError and exit(1) with a clean message instead of a traceback, matching the screen command. - tests: cover collect_codereview_entry orchestration with a mocked GHClient (call sequence + reload) and the explicit-tag severity case.
- Return Severity (not str) from parse_domain_severity and annotate the local, resolving the ty mismatch against ReviewComment.severity. - Guard the reactions lookup against a None comment id. - Raise CollectionError instead of typer.Exit from collect_codereview_entry so the CLI command formats the error consistently; drop the now-unused typer import.
Comment on lines
+168
to
+172
| patch = gh_client.get_pr_diff(pr_number) | ||
| if not patch.strip(): | ||
| raise CollectionError("PR diff is empty") | ||
|
|
||
| comments = gh_client.get_pr_review_comments(pr_number) |
Collaborator
Author
There was a problem hiding this comment.
This is a good catch. I shall create another bug and then check with Wael how do we want to solve it
Jiawen-CS
approved these changes
Jul 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
New
bcbench collect codereview <pr>command that turns a real GitHub PR into aCodeReviewEntry: the PR diff becomes the reviewpatch, and the PR's inline comments become theexpected_comments.Why
Today code-review dataset entries are hand-authored synthetic JSONL. Two workflows need real PRs as entries:
microsoft/BCApps#9553).--reviewer <login>harvests exactly those.microsoft/BCApps#9315).--reactedkeeps the positively-reacted findings as gold; a 👎-only comment is dropped, which makes it a false-positive guard by omission (the construct stays in the patch but is absent fromexpected_comments, so flagging it costs precision).The two flags compose:
--reacted --reviewer "github-actions[bot]"= only the bot's positively-reacted findings.How
collection/collect_codereview.py— mirrors the existingcollect_gh(bug-fix) collector but builds aCodeReviewEntry.base_commitis the merge-base of base/head (via the compare API), i.e. exactly whatgh pr diff's three-dot diff is computed against, so the patch applies cleanly.(domain, severity)best-effort parsing are pure, unit-tested functions. Unplaceable / reply / LEFT-side comments are skipped.GHClientgainsget_merge_base,get_pr_review_comments,get_review_comment_reactions.ReviewComment.filepattern relaxed to allow spaces — real BC paths contain them (e.g..../1.Setup Data/...) and the judge matches on the full normalized path, so the exact path must be storable. Matches howproject_pathsalready allows spaces. No other model change; synthetic entries are unaffected (test_dataset_integritygreen).collect codereviewsubcommand.Tested
tests/test_collect_codereview.py(new, 11 cases): header parsing, reviewer/reacted/compose filtering, reply/side/unanchored skipping, multi-line spans, spaced paths.CodeReviewEntry.load:#9553 --reviewer WaelAbuSeada→ 16 expected comments,base_commit=e597a54….#9315 --reacted→ 2 positively-reacted findings, the 👎 Style comment correctly excluded.test_collect_codereview+test_codereview+test_collect_gh+test_dataset_integritygreen;ruff check/ruff formatclean.Depends on the same category as #748 (fetch
base_commiton demand) — that PR lets the fetched real-PR base be checked out at eval time. First helper for Accept real PRs as BC Bench code-review dataset entries (ADO 643360); the--reactedpath also serves Auto-feed online-eval reactions (ADO 643361).