Skip to content

feat(autofix): make FE changes to match github mentions#118261

Draft
joseph-sentry wants to merge 23 commits into
masterfrom
joey--github-mention-fe
Draft

feat(autofix): make FE changes to match github mentions#118261
joseph-sentry wants to merge 23 commits into
masterfrom
joey--github-mention-fe

Conversation

@joseph-sentry

Copy link
Copy Markdown
Contributor
  • update feedback section in code changes card to reflect feedback queueing status:
    • we made a change to queue feedback that's received while the autofix agent is already running to avoid concurrency issues, and we want to update the feedback section to reflect this change by showing feedback in 3 different statuses
      • processed
      • processing
      • queued
  • poll autofix state when autofix drawer is open, a PR has been created and PR iteration is enabled
    • Before, we polled for autofix state while the autofix run was processing
    • now, since we can receive feedback from github we need to poll while:
      • a PR is created for this run
      • PR iteration as a feature is enabled
      • the drawer is open
    • if we don't do this, then a user in the UI won't be able to see in real time that feedback has come in from Github

alexsohn1126 and others added 12 commits June 18, 2026 14:47
This is just adding some UI stuff and fleshing out @alexsohn1126's PR
to support ingesting PR iteration feedback through github webhooks

the approach is to add a legacy github webhook handler for issue comments
then parse it to make sure:
- the user is not requesting a review
- the user has github write access to the repo

then then handler queues up a taskworker task, that task triggers the
seer autofix agent with an iteration
this is a case that got brought up after the first iteration of this PR

we need to handle the case where we receive comments while an agent.run is
under way for a given autofix run

before this change we risked a state where we have 2 agent.run happening at the same time
writing to the same blocks, this wouldn't mess up the agent runs while they're happening, but
the resulting conversation would end up broken and any subsequent iteration would be looking at a
weird state of the conversation

we want to serialize PR iteration runs so we don't run into the above, we'll do this by queueing feedback
that we receive during runs into redis, then at the completion hook after the run is finished we'll
queue up another run with the feedback that was buffered

the implementation is:
- a task that checks whether a run is processing and queues up the feedback if not
- a queue of feedback items in redis
- writing feedback items when we receive a PR iteration request from the UI or github
  and running the task
- running the task from the completion hook after a PR iteration

we avoid:
- double work: by having the task be under a redis lock
- dropped work: by having the completion hook run the task

an important part of this change is the seer behaviour:
- seer sets the run state to processing in the endpoint that the task calls synchronously
  so as far as we can tell, it's being done under the lock
  so there's no chance of the next task run seeing status != processing when it enters the mutex zone
- seer also sets the completed status before calling the completion hook, this eliminates the possibility
  of dropping work, since we know that the completion hook will _always_ pick up any buffered work that
  was enqueued during its run
2 changes:
- updating feedback section in code changes card to reflect feedback queueing status
    we made a change to queue feedback that's received while the autofix agent is already
    running to avoid concurrency issues, and we want to update the feedback section to 
    reflect this change by showing feedback in 3 different statuses:
    - processed
    - processing
    - queued
- updating polling logic for autofix to catch updates to feedback
    in order to accomplish the above, we need to poll autofix state whenever more often
    since before we were only polling between the time the user had input something in the UI
    and the time seer had said the action associated with that input was completed

    now we also want to poll when we have an open PR since github feedback might come in whenever
    and we want to reflect the feedback coming in from github in a timely manner

    we also want to make sure we're showing that feedback that gets submitted during a run gets queued
    up instead of added to the current iteration
@github-actions github-actions Bot added Scope: Frontend Automatically applied to PRs that change frontend components Scope: Backend Automatically applied to PRs that change backend components labels Jun 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on 08624d9 in this run:

tests/sentry/seer/endpoints/test_group_ai_autofix.py::GroupAutofixEndpointTest::test_pr_iteration_requires_feature_flaglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/endpoints/test_group_ai_autofix.py:367: in test_pr_iteration_requires_feature_flag
    assert response.status_code == 403, response.data
E   AssertionError: {'detail': 'PR iteration is not enabled for this organization'}
E   assert 400 == 403
E    +  where 400 = <Response status_code=400, "application/json">.status_code
tests/sentry/seer/endpoints/test_group_ai_autofix.py::GroupAutofixEndpointTest::test_stopping_pointlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/endpoints/test_group_ai_autofix.py:232: in test_stopping_point
    mock_trigger_explorer.assert_called_once_with(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:989: in assert_called_once_with
    return self.assert_called_with(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:977: in assert_called_with
    raise AssertionError(_error_message()) from cause
E   AssertionError: expected call not found.
E   Expected: trigger_autofix_agent(group=<Group at 0x7f3be2105810: id=114, project_id=4558364180086816>, step=<AutofixStep.ROOT_CAUSE: 'root_cause'>, referrer=<AutofixReferrer.GROUP_AUTOFIX_ENDPOINT: 'api.group_ai_autofix'>, stopping_point=<AutofixStoppingPoint.CODE_CHANGES: 'code_changes'>, run_id=None, user_context=None, insert_index=None, feedback=None)
E     Actual: trigger_autofix_agent(group=<Group at 0x7f3be2977b10: id=114, project_id=4558364180086816>, step=<AutofixStep.ROOT_CAUSE: 'root_cause'>, referrer=<AutofixReferrer.GROUP_AUTOFIX_ENDPOINT: 'api.group_ai_autofix'>, stopping_point=<AutofixStoppingPoint.CODE_CHANGES: 'code_changes'>, run_id=None, user_context=None, insert_index=None)
tests/sentry/seer/endpoints/test_group_ai_autofix.py::GroupAutofixEndpointTest::test_insert_index_passed_throughlog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/endpoints/test_group_ai_autofix.py:257: in test_insert_index_passed_through
    mock_trigger_explorer.assert_called_once_with(
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:989: in assert_called_once_with
    return self.assert_called_with(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:977: in assert_called_with
    raise AssertionError(_error_message()) from cause
E   AssertionError: expected call not found.
E   Expected: trigger_autofix_agent(group=<Group at 0x7fe711fb1a90: id=445, project_id=4558364181266448>, step=<AutofixStep.SOLUTION: 'solution'>, referrer=<AutofixReferrer.GROUP_AUTOFIX_ENDPOINT: 'api.group_ai_autofix'>, stopping_point=None, run_id=42, user_context=None, insert_index=3, feedback=None)
E     Actual: trigger_autofix_agent(group=<Group at 0x7fe711213250: id=445, project_id=4558364181266448>, step=<AutofixStep.SOLUTION: 'solution'>, referrer=<AutofixReferrer.GROUP_AUTOFIX_ENDPOINT: 'api.group_ai_autofix'>, stopping_point=None, run_id=42, user_context=None, insert_index=3)
tests/sentry/seer/autofix/test_pr_iteration_webhook.py::HandleIssueCommentForAutofixIterationTest::test_schedules_task_for_valid_commandlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/autofix/test_pr_iteration_webhook.py:43: in test_schedules_task_for_valid_command
    self._call(self._event())
tests/sentry/seer/autofix/test_pr_iteration_webhook.py:33: in _call
    return handle_issue_comment_for_autofix_iteration(
src/sentry/seer/autofix/pr_iteration_webhook.py:149: in handle_issue_comment_for_autofix_iteration
    raise ValueError("GitHub PR comment is missing html_url")
E   ValueError: GitHub PR comment is missing html_url
tests/sentry/seer/endpoints/test_group_ai_autofix.py::GroupAutofixEndpointTest::test_pr_iteration_requires_existing_prlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/endpoints/test_group_ai_autofix.py:399: in test_pr_iteration_requires_existing_pr
    mock_trigger_explorer.assert_called_once()
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/unittest/mock.py:956: in assert_called_once
    raise AssertionError(msg)
E   AssertionError: Expected 'trigger_autofix_agent' to have been called once. Called 0 times.
tests/sentry/seer/endpoints/test_group_ai_autofix.py::GroupAutofixEndpointTest::test_pr_iterationlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/seer/endpoints/test_group_ai_autofix.py:335: in test_pr_iteration
    assert response.status_code == 202, response.data
E   AssertionError: {'detail': 'feedback is required for pr_iteration'}
E   assert 400 == 202
E    +  where 400 = <Response status_code=400, "application/json">.status_code

Comment thread src/sentry/integrations/github/webhook.py
Comment thread src/sentry/seer/endpoints/group_ai_autofix.py Outdated
Comment thread src/sentry/tasks/seer/autofix.py
Comment thread src/sentry/seer/endpoints/group_ai_autofix.py Outdated
joseph-sentry and others added 10 commits June 24, 2026 16:22
Route pr_iteration feedback through the match arm so the repo_pr_states
check runs before enqueuing, instead of an early return that bypassed it.
Update endpoint and webhook tests for the new flow.
When consuming queued feedback, skip github comments already processed
into the run's blocks and collapse duplicate comment ids within the
batch, so webhook redelivery or task retries can't double-deliver
feedback (Warden 2W4-L4C). Dedup keys on the seer run state, the source
of truth, so there's no dual-write crash window.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants