Skip to content

Comments

feat(cherry-pick): add PR author attribution and optional assignee for cherry-pick PRs#994

Open
rnetser wants to merge 12 commits intomainfrom
feat/issue-993-cherry-pick-author-attribution
Open

feat(cherry-pick): add PR author attribution and optional assignee for cherry-pick PRs#994
rnetser wants to merge 12 commits intomainfrom
feat/issue-993-cherry-pick-author-attribution

Conversation

@rnetser
Copy link
Collaborator

@rnetser rnetser commented Feb 19, 2026

Summary

  • When cherry-pick is triggered by label (on merge), the description now says requested-by by <user> with target-branch label instead of the anonymous requested-by by target-branch label
  • Added new config option cherry-pick-assign-to-pr-author (boolean, default: false) to assign cherry-pick PRs to the original PR author via hub's -a flag
  • Config available at both global and per-repository level

Test plan

  • 1280 tests pass (90.44% coverage)
  • 3 new tests for assignee flag and by_label format
  • Linting and formatting clean
  • All pre-commit hooks pass

Closes #993

Summary by CodeRabbit

  • New Features

    • New config option to assign cherry-picked pull requests to the original PR author (global and per-repo; default: off).
  • Improvements

    • Label-triggered cherry-picks show clearer "requested by" wording and can assign the original PR author when enabled.
    • Improved error reporting and PR comments when target branches are missing.
  • Tests

    • Expanded tests covering assignment behavior, label-trigger formatting, and cherry-pick scenarios.

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new global and per-repository config flag to optionally assign cherry-pick PRs to the original PR author, threads the original author through label-triggered cherry-pick flows, updates the cherry-pick implementation to support by-label formatting and optional assignee, and updates tests accordingly.

Changes

Cohort / File(s) Summary
Configuration Schema
webhook_server/config/schema.yaml
Added global and per-repo cherry-pick-assign-to-pr-author boolean (default: false).
Core Initialization
webhook_server/libs/github_api.py
Read per-repo config and expose cherry_pick_assign_to_pr_author attribute on GithubWebhook instances.
PR Handling Logic
webhook_server/libs/handlers/pull_request_handler.py
Filter cherry-pick labels early, extract PR author, and call cherry_pick(..., reviewed_user=pr_author, by_label=True) for label-triggered cherry-picks.
Cherry-Pick Implementation
webhook_server/libs/handlers/runner_handler.py
Added by_label: bool = False kw-only parameter; format requested_by to include original author when by-label; include -a {author} assignee flag when repo config enables assignment; log/comment on missing target branch; update hub command construction and failure handling.
Tests
webhook_server/tests/test_pull_request_handler.py, webhook_server/tests/test_runner_handler.py
Updated tests to pass reviewed_user/by_label; added tests for assignee flag behavior, requested-by formatting, disabled behavior, and extended mock fixture with cherry_pick_assign_to_pr_author.

Sequence Diagram(s)

sequenceDiagram
    participant PR as Pull Request
    participant PRH as PullRequestHandler
    participant RH as RunnerHandler
    participant GH as GitHub

    PR->>PRH: merged with `cherry-pick-<branch>` label(s)
    PRH->>PRH: filter labels\nextract original PR author
    PRH->>RH: cherry_pick(pr, target_branch,\nreviewed_user=pr_author, by_label=true)
    RH->>RH: build requested_by ("by {author} with target-branch label")
    alt repo config cherry_pick_assign_to_pr_author = true
        RH->>RH: set assignee_flag ("-a {author_login}")
    else
        RH->>RH: no assignee_flag
    end
    alt target branch exists
        RH->>GH: execute hub create pull-request\n(include assignee_flag & labels)
        GH-->>RH: success (cherry-pick PR created)
    else
        RH->>RH: log error
        RH->>GH: post comment on original PR about failure
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • myakove
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% 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 accurately describes the main changes: adding PR author attribution and optional assignee functionality for cherry-pick PRs, which aligns with the primary objectives.
Linked Issues check ✅ Passed All requirements from issue #993 are met: by_label flag and author attribution added [#993], cherry-pick-assign-to-pr-author config at global/repo levels [#993], assignee logic implemented [#993], cherry_pick() signature updated [#993], and comprehensive tests added [#993].
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #993 requirements: configuration schema additions, cherry_pick method enhancements, handler refactoring, and test coverage—no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/issue-993-cherry-pick-author-attribution

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 and usage tips.

@qodo-code-review
Copy link

Review Summary by Qodo

Add PR author attribution and optional assignee for cherry-pick PRs

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add PR author attribution to cherry-pick descriptions with new by_label parameter
• Implement optional assignee feature via cherry-pick-assign-to-pr-author config option
• Extract PR author login when cherry-pick triggered by label on merge
• Add comprehensive test coverage for assignee and attribution functionality

Grey Divider

File Changes

1. webhook_server/libs/github_api.py ⚙️ Configuration changes +3/-0

Load cherry-pick assignee configuration option

• Add new config property cherry_pick_assign_to_pr_author with default value False
• Load configuration from both global and per-repository levels

webhook_server/libs/github_api.py


2. webhook_server/libs/handlers/pull_request_handler.py ✨ Enhancement +8/-4

Extract PR author for label-triggered cherry-picks

• Filter labels to extract only cherry-pick labels before processing
• Retrieve PR author login when cherry-pick labels are present
• Pass reviewed_user (PR author) and by_label=True to cherry_pick method

webhook_server/libs/handlers/pull_request_handler.py


3. webhook_server/libs/handlers/runner_handler.py ✨ Enhancement +27/-3

Implement author attribution and assignee logic

• Add by_label parameter to cherry_pick method with comprehensive docstring
• Implement conditional requested_by format based on by_label flag
• Add logic to determine assignee based on cherry_pick_assign_to_pr_author config
• Construct -a flag with quoted assignee username for hub pull-request command

webhook_server/libs/handlers/runner_handler.py


View more (3)
4. webhook_server/tests/test_pull_request_handler.py 🧪 Tests +4/-1

Update cherry-pick test assertions

• Update test assertion to include reviewed_user="owner1" parameter
• Add by_label=True parameter to cherry_pick mock call verification

webhook_server/tests/test_pull_request_handler.py


5. webhook_server/tests/test_runner_handler.py 🧪 Tests +105/-0

Add comprehensive cherry-pick assignee tests

• Initialize cherry_pick_assign_to_pr_author mock property to False
• Add test for assignee assignment when reviewed_user is provided
• Add test for fallback to PR author login when reviewed_user is empty
• Add test for correct requested-by format when triggered by label

webhook_server/tests/test_runner_handler.py


6. webhook_server/config/schema.yaml ⚙️ Configuration changes +8/-0

Add cherry-pick assignee config schema

• Add cherry-pick-assign-to-pr-author boolean property to global configuration
• Add cherry-pick-assign-to-pr-author boolean property to per-repository configuration
• Include description and default value false for both levels

webhook_server/config/schema.yaml


Grey Divider

Qodo Logo

@myakove-bot
Copy link
Collaborator

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: Disabled for this repository
  • Pre-commit Checks: pre-commit runs automatically if .pre-commit-config.yaml exists
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: All label categories are enabled (default configuration)

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest python-module-install - Test Python package installation
  • /retest pre-commit - Run pre-commit hooks and checks
  • /retest conventional-title - Validate commit message format
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 1 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No WIP, hold, conflict labels
  5. Verified: PR must be marked as verified (if verification is enabled)

📊 Review Process

Approvers and Reviewers

Approvers:

  • myakove
  • rnetser

Reviewers:

  • myakove
  • rnetser
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is automatically removed on each new commit
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 19, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (2)

Grey Divider


Action required

✅ 1. -a uses reviewed_user 📎 Requirement gap ✓ Correctness
Description
When cherry_pick_assign_to_pr_author is enabled, cherry_pick() builds hub’s -a assignee from
reviewed_user when provided, but reviewed_user is the command requester in comment-triggered
flows rather than the original PR author. This can incorrectly assign cherry-pick PRs to the
requester instead of the PR author.
Code

webhook_server/libs/handlers/runner_handler.py[R558-565]

+        if self.github_webhook.cherry_pick_assign_to_pr_author:
+            if reviewed_user:
+                pr_author = reviewed_user
+            else:
+                pr_author = await asyncio.to_thread(lambda: pull_request.user.login)
+            assignee_flag = f" -a {shlex.quote(pr_author)}"
+        else:
+            assignee_flag = ""
Evidence
Compliance requires assigning the cherry-pick PR to the original PR author via hub -a, but the new
implementation assigns to reviewed_user when present, and reviewed_user is passed from the
comment command path as the requesting user (not the PR author).

Optional assignee logic assigns cherry-pick PR to original PR author via hub -a flag
webhook_server/libs/handlers/runner_handler.py[558-565]
webhook_server/libs/handlers/issue_comment_handler.py[420-434]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`cherry-pick-assign-to-pr-author` is intended to assign the created cherry-pick PR to the original PR author, but the current implementation assigns to `reviewed_user` when it is provided (which is the requester in the comment-command flow).
## Issue Context
`reviewed_user` is used for audit/attribution of who requested the cherry-pick. For comment-triggered cherry-picks, `reviewed_user` is the command requester, not the PR author, so using it for hub `-a` violates the requirement.
## Fix Focus Areas
- webhook_server/libs/handlers/runner_handler.py[539-565]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. Tests expect requester assignee 📎 Requirement gap ⛯ Reliability
Description
New tests assert the hub -a assignee is reviewed_user (the requester) rather than the original
PR author, so they validate the wrong behavior. They also don’t add a test that explicitly verifies
the default/disabled state excludes -a.
Code

webhook_server/tests/test_runner_handler.py[R922-952]

+    @pytest.mark.asyncio
+    async def test_cherry_pick_assigns_to_reviewed_user(
+        self, runner_handler: RunnerHandler, mock_pull_request: Mock
+    ) -> None:
+        """Test cherry_pick uses reviewed_user for assignee when cherry_pick_assign_to_pr_author is True."""
+        runner_handler.github_webhook.pypi = {"token": "dummy"}
+        runner_handler.github_webhook.cherry_pick_assign_to_pr_author = True
+        with patch.object(runner_handler, "is_branch_exists", new=AsyncMock(return_value=Mock())):
+            with patch.object(runner_handler.check_run_handler, "set_check_in_progress") as mock_set_progress:
+                with patch.object(runner_handler.check_run_handler, "set_check_success") as mock_set_success:
+                    with patch.object(runner_handler, "_checkout_worktree") as mock_checkout:
+                        mock_checkout.return_value = AsyncMock()
+                        mock_checkout.return_value.__aenter__ = AsyncMock(
+                            return_value=(True, "/tmp/worktree-path", "", "")
+                        )
+                        mock_checkout.return_value.__aexit__ = AsyncMock(return_value=None)
+                        with patch(
+                            "webhook_server.libs.handlers.runner_handler.run_command",
+                            new=AsyncMock(return_value=(True, "success", "")),
+                        ) as mock_run_cmd:
+                            with patch.object(mock_pull_request, "create_issue_comment", new=Mock()) as mock_comment:
+                                await runner_handler.cherry_pick(
+                                    mock_pull_request, "main", reviewed_user="cherry-requester"
+                                )
+                                mock_set_progress.assert_called_once()
+                                mock_set_success.assert_called_once()
+                                mock_comment.assert_called_once()
+                                # Verify the hub pull-request command includes -a with the reviewed_user
+                                last_cmd = mock_run_cmd.call_args_list[-1]
+                                hub_command = last_cmd.kwargs.get("command", last_cmd.args[0] if last_cmd.args else "")
+                                assert "-a 'cherry-requester'" in hub_command or "-a cherry-requester" in hub_command
Evidence
Compliance requires tests to validate assignee behavior controlled by config, specifically assigning
to the original PR author and toggling inclusion/exclusion of -a. The added test asserts -a uses
reviewed_user (requester), and no added test in this block validates the disabled state.

Update automated tests for author attribution and optional assignee behavior
webhook_server/tests/test_runner_handler.py[922-952]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new tests validate `-a` against `reviewed_user` (requester), but the requirement is to assign to the original PR author. Tests should also explicitly cover the disabled/default behavior where `-a` must not be present.
## Issue Context
After correcting the implementation to always use the PR author for `-a`, tests should set `mock_pull_request.user.login` and assert the hub command contains `-a &amp;lt;pr-author&amp;gt;`. Add a complementary test with `cherry_pick_assign_to_pr_author = False` to assert `-a` is absent.
## Fix Focus Areas
- webhook_server/tests/test_runner_handler.py[922-1025]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@webhook_server/libs/handlers/runner_handler.py`:
- Around line 539-555: In cherry_pick, avoid producing "by  with target-branch
label" when by_label is True but reviewed_user is empty: update the requested_by
assignment to check reviewed_user and use a sensible fallback (e.g. "by
target-branch label" or "by unknown") or format conditionally so you only
include "by {reviewed_user} with target-branch label" when reviewed_user is
non-empty; reference the cherry_pick method and the requested_by / reviewed_user
/ by_label variables when making the change.

In `@webhook_server/tests/test_runner_handler.py`:
- Around line 965-1003: Rename the test function
test_cherry_pick_assigns_to_pr_author_fallback to reflect actual behavior (e.g.,
test_cherry_pick_always_assigns_to_pr_author_when_flag_set) and update its
docstring to state that when
runner_handler.github_webhook.cherry_pick_assign_to_pr_author is True the
assignee is always pull_request.user.login regardless of reviewed_user; also
update the inline comment on Line 996 to match this invariant (referencing
runner_handler.cherry_pick, reviewed_user, and cherry_pick_assign_to_pr_author
to locate the code).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@webhook_server/tests/test_runner_handler.py`:
- Around line 1008-1046: Add a new async test that exercises
runner_handler.cherry_pick with by_label=True and reviewed_user="" to cover the
fallback branch that sets requested_by to "by target-branch label";
specifically, create a test named like
test_cherry_pick_by_label_empty_reviewed_user_requested_by_format that mirrors
test_cherry_pick_by_label_requested_by_format's setup (patch is_branch_exists,
check_run_handler methods, _checkout_worktree, run_command, and
PR.create_issue_comment) but calls runner_handler.cherry_pick(mock_pull_request,
"main", reviewed_user="", by_label=True) and asserts the last run_command
invocation's hub command contains "requested-by by target-branch label" and does
not contain the double-space pattern "by  with".
- Around line 999-1000: The test's assertion using mock_to_thread.call_count >=
1 is too weak; when cherry_pick_assign_to_pr_author=True the success path should
make exactly two asyncio.to_thread calls (one for accessing user.login and one
for create_issue_comment). Update the assertion in the test_runner_handler to
assert mock_to_thread.call_count == 2 (or otherwise verify the two specific
calls exist), and/or add an explicit check that one of the mock_to_thread calls
invoked user.login (e.g., by inspecting mock_to_thread.call_args_list) so the
test guarantees user.login was called via asyncio.to_thread.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 19, 2026
- Capture asyncio.to_thread mock in test_cherry_pick_by_label_requested_by_format
  and add call_count == 2 assertion for consistency with sibling tests
- Remove dead-code mock_pull_request.user setup in
  test_cherry_pick_by_label_empty_reviewed_user_requested_by_format since
  cherry_pick_assign_to_pr_author=False means user.login is never accessed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@webhook_server/config/schema.yaml`:
- Around line 82-85: Add the new schema key "cherry-pick-assign-to-pr-author" to
the config schema tests: update the valid_full_config fixture in
webhook_server/tests/test_config_schema.py to include
"cherry-pick-assign-to-pr-author" at both the global and per-repo levels, and
add "cherry-pick-assign-to-pr-author" to the boolean_fields lists in
webhook_server/tests/test_schema_validator.py (the global list near
"auto-verify-cherry-picked-prs" and the repo-level list near "verified-job") so
the schema validator tests cover this boolean option.

In `@webhook_server/libs/handlers/runner_handler.py`:
- Around line 561-565: The code is directly accessing pull_request.user.login;
replace that with a call through the unified API on the webhook to fetch the PR
author (e.g., use self.github_webhook.unified_api to get the pull request author
login) when cherry_pick_assign_to_pr_author is true, then build assignee_flag
from that value (keep the existing shlex.quote usage and flag format); update
the block that references cherry_pick_assign_to_pr_author, pull_request and
assignee_flag to use the unified_api helper instead of pull_request.user.login.
ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2556e41 and 9f51fd3.

📒 Files selected for processing (6)
  • webhook_server/config/schema.yaml
  • webhook_server/libs/github_api.py
  • webhook_server/libs/handlers/pull_request_handler.py
  • webhook_server/libs/handlers/runner_handler.py
  • webhook_server/tests/test_pull_request_handler.py
  • webhook_server/tests/test_runner_handler.py

…educe test nesting

- Reuse reviewed_user as pr_author when by_label=True to avoid redundant
  asyncio.to_thread call for pull_request.user.login
- Fix misleading fallback message: use "unknown requester" instead of
  "by target-branch label" for comment-triggered cherry-picks
- Extract CherryPickMocks dataclass and cherry_pick_setup async context
  manager to reduce 7-8 levels of nesting to 1 in cherry-pick tests
coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 23, 2026
…feat/issue-993-cherry-pick-author-attribution
Always use pull_request.user.login as the cherry-pick PR assignee
rather than the user who requested the cherry-pick. Wrap the
user.login access with asyncio.to_thread to avoid blocking.
Collapse redundant conditional in by_label branch.
Update tests to assert PR author as assignee and correct
to_thread call counts.
…ering

Combine list comprehension assignment and truthiness check into a
single walrus operator expression.
@rnetser
Copy link
Collaborator Author

rnetser commented Feb 24, 2026

/build-and-push-container

@myakove-bot
Copy link
Collaborator

New container for ghcr.io/myk-org/github-webhook-server:pr-994 published

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Cherry-pick PR author attribution and optional assignee

2 participants