ref(seer): Call project settings update helper in callsites that don't need to update the full Seer project preference#116356
Conversation
…tomationTuning Consolidate update_seer_project_settings and bulk_update_seer_project_settings into a single function that accepts project_ids. Remove row locks, use bulk_create with update_conflicts and _raw_delete for efficiency. - SeerProjectSettingsUpdate uses snake_case keys via CamelSnakeSerializer - Add auto_create_pr and automation_tuning fields - Simplify clear_preference_automation_handoff (3 keys, preserves auto_create_pr) - Endpoint returns autoCreatePr and automationTuning in response - Seat-based tuning validation (off/medium only) - Stopping point syncs auto_create_pr automatically - Callers (configure_seer_for_existing_org, set_default_project_seer_preferences) migrated to new unified function
Restore _write_preference_project_options, row lock in _write_preferences_to_sentry_db, and revert configure_seer_for_existing_org and set_default_project_seer_preferences to their master state. These callsite migrations will land in a follow-up PR.
| ) | ||
|
|
||
| if len(preferences_to_set) > 0: | ||
| bulk_write_preferences_to_sentry_db(projects, preferences_to_set) |
There was a problem hiding this comment.
We don't sacrifice performance here, because bulk_write_preferences_to_sentry_db used to call _write_preference_project_options which set project options individually even within the same project.
So even though we can't bulk operate across all projects since the updates could differ by project, we're now bulk updating each project which is an improvement.
681bd04 to
6b65685
Compare
| project.delete_option("sentry:seer_automation_handoff_point") | ||
| project.delete_option("sentry:seer_automation_handoff_target") | ||
| project.delete_option("sentry:seer_automation_handoff_integration_id") | ||
| project.delete_option("sentry:seer_automation_handoff_auto_create_pr") |
There was a problem hiding this comment.
We don't want to clear auto_create_pr here:
- We only read a handoff if the other three fields (point, target, integration id) are non-null.
- Legacy seer: if we reenable the agent we want to restore the toggle to its previous state
- Seat-based seer: generally this field should stay in sync with stopping point
…taking project_ids
…er with auto_create_pr sync
dc236fb to
f682313
Compare
…nd auto_create_pr fields (#116352) Consolidate `update_seer_project_settings` and `bulk_update_seer_project_settings` into a single function that bulk deletes/creates project options across 1+ project ids. Also, strip seat-based business logic (stopping point → auto_create_pr syncing, tuning validation) out of the update helper and add tuning and auto_create_pr as update fields, so it becomes a pure write layer and can be used by other callsites. Followups: #116356, #115962 #### Why: By moving business logic out, other callsites can do updates without hidden side effects. - Independent auto_create_pr and tuning updates are needed by legacy seer and will be used when we add legacy seer to the project settings endpoints: #115962 - #116356 reroutes existing callsites that modify seer project settings (`_write_preferences_to_sentry_db`, `configure_seer_for_existing_org`, `set_default_project_seer_preferences`) to the update helper to ensure that handoff options are either cleared or added atomically AND to skip unnecessary connected repo operations. It also removes `Project` row locks and simplifies `clear_preference_automation_handoff`. #### Other cleanups: - `SeerProjectSettingsUpdate` uses snake_case keys via `CamelSnakeSerializer`. - Add tuning to the project settings endpoints serializers (as opposed to consolidating tuning="off" into stopping_point="off"), again to make it easier to support legacy seer. - Endpoint returns `autoCreatePr` and `automationTuning` in response. - Stopping point syncs `auto_create_pr` automatically.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c875e14. Configure here.
…ndpoint (#115962) Depends on #116352 and #116356. Add legacy usage-based Seer support to the project settings endpoints by branching on `is_seer_seat_based_tier_enabled`. **Serializer split:** - Extract `_BaseProjectSettingsUpdateSerializer` with shared validation (agent, integration_id, cross-field checks) - `ProjectSettingsUpdateSerializer` (seat-based): restricted tuning choices (off/medium), stopping_point validation via `get_valid_automated_run_stopping_points`, auto_create_pr synced from stopping_point - `LegacyProjectSettingsUpdateSerializer` (usage-based): accepts all tuning values, direct `auto_create_pr` field, no stopping_point restrictions ### Example payloads **Set tuning to a granular value:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"automationTuning": "high"} ``` **Set stopping point (frontend sends agent=seer to clear any external handoff):** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"stoppingPoint": "code_changes", "agent": "seer"} ``` This clears handoff keys (target, point, integration_id) but preserves `auto_create_pr` so switching back to an external agent restores the previous toggle value. **Switch to external agent with auto_create_pr:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"agent": "cursor_background_agent", "integrationId": 1, "autoCreatePr": true} ``` **Toggle auto_create_pr on an existing external agent:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"autoCreatePr": false} ``` **Turn off automation:** ```json PUT /api/0/projects/{org}/{project}/seer/settings/ {"automationTuning": "off"} ``` GET response will show `stoppingPoint: "off"`, but the stored stopping point is unchanged — re-enabling restores it.
| """Atomically clear a project's automation handoff settings.""" | ||
| ProjectOption.objects.filter( | ||
| project=project, | ||
| key__in=[ | ||
| "sentry:seer_automation_handoff_point", | ||
| "sentry:seer_automation_handoff_target", | ||
| "sentry:seer_automation_handoff_integration_id", | ||
| ], | ||
| ).delete() |
There was a problem hiding this comment.
Bug: The clear_preference_automation_handoff function fails to clear the auto_create_pr project option, leaving a stale value that can be incorrectly reused in subsequent handoff configurations.
Severity: MEDIUM
Suggested Fix
Update the clear_preference_automation_handoff function to include SEER_AUTO_CREATE_PR_PROJECT_OPTION in the list of keys passed to ProjectOption.objects.filter(key__in=...).delete(). This will ensure the auto_create_pr setting is properly cleared along with other handoff-related options.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/seer/autofix/utils.py#L569-L577
Potential issue: The refactored `clear_preference_automation_handoff` function no longer
clears the `sentry:seer_automation_handoff_auto_create_pr` project option. The previous
implementation explicitly deleted this key, but the new implementation, which uses
`ProjectOption.objects.filter(key__in=[...]).delete()`, omits it from the list of keys
to be deleted. This leaves a stale `auto_create_pr=True` value in the database after a
handoff is cleared. If a user later re-enables a handoff without specifying the
`auto_create_pr` value, the stale `True` value will be read, causing the system to
incorrectly enable auto-PR creation when it was not requested for the new configuration.
Did we get this right? 👍 / 👎 to inform future reviews.

Followup to #116352.
Reroute existing callsites that modify seer project settings (
_write_preferences_to_sentry_db,configure_seer_for_existing_org,set_default_project_seer_preferences) to the unifiedupdate_seer_project_settingshelper. This ensures handoff options are cleared/added atomically and skips unnecessary connected repo operations.Also remove
Projectrow locks from_write_preferences_to_sentry_dbandclear_preference_automation_handoff— no longer needed since handoff options are all either cleared or added atomically, and the other update fields may be updated independently of each other.