-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
ref: Create a prevent config model, no longer use organization options #101831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #101831 +/- ##
===========================================
+ Coverage 76.91% 80.96% +4.05%
===========================================
Files 8728 8718 -10
Lines 388272 387495 -777
Branches 24611 24477 -134
===========================================
+ Hits 298646 313754 +15108
+ Misses 89268 73393 -15875
+ Partials 358 348 -10 |
|
This PR has a migration; here is the generated SQL for for --
-- Create model PreventAIConfiguration
--
CREATE TABLE "sentry_preventaiconfiguration" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "date_updated" timestamp with time zone NOT NULL, "date_added" timestamp with time zone NOT NULL, "organization_id" bigint NOT NULL, "provider" varchar(64) NOT NULL, "git_organization_id" varchar(255) NOT NULL, "data" jsonb NOT NULL);
CREATE UNIQUE INDEX CONCURRENTLY "sentry_preventaiconfigur_organization_id_provider_eb547f9a_uniq" ON "sentry_preventaiconfiguration" ("organization_id", "provider", "git_organization_id");
ALTER TABLE "sentry_preventaiconfiguration" ADD CONSTRAINT "sentry_preventaiconfigur_organization_id_provider_eb547f9a_uniq" UNIQUE USING INDEX "sentry_preventaiconfigur_organization_id_provider_eb547f9a_uniq";
CREATE INDEX CONCURRENTLY "sentry_preventaiconfiguration_organization_id_a95756f3" ON "sentry_preventaiconfiguration" ("organization_id"); |
src/sentry/prevent/migrations/0001_initial_prevent_ai_configuration.py
Outdated
Show resolved
Hide resolved
suejung-sentry
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice stuff!
I'm not sure the protocols but we may want to have the migration PR more isolated and do the deletion off the old stuff in a separate PR? Maybe doesn't matter much
Our old implementation haven't been live yet minus the few testing orgs, we can probably manually migrate it over and delete the old ones. |
| ) | ||
| from sentry.models.organization import Organization | ||
| from sentry.models.repository import Repository | ||
| from sentry.prevent.types.config import PREVENT_AI_CONFIG_GITHUB_DEFAULT | ||
| from sentry.silo.base import SiloMode | ||
| from sentry.types.prevent_config import PREVENT_AI_CONFIG_GITHUB_DEFAULT | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The RPC endpoint reads config from the old organization_options, while the new UI endpoint writes to the new PreventAIConfiguration model, with no data migration.
(Severity: Critical 0.85 | Confidence: 1.00)
🔍 Detailed Analysis
The PreventPrReviewResolvedConfigsEndpoint in overwatch_rpc.py reads configuration from the old organization.get_option storage. However, the new OrganizationPreventGitHubConfigEndpoint writes settings to the new PreventAIConfiguration model. There is no data migration to move existing settings from the old storage to the new model, nor is there any fallback logic for the read endpoint to check the new model. As a result, any configuration changes made through the new UI will be saved to the new model but will be completely ignored by the Overwatch service, which will continue to use old or default settings from the previous storage location.
💡 Suggested Fix
Update the PreventPrReviewResolvedConfigsEndpoint to read from the new PreventAIConfiguration model. Additionally, create a data migration to transfer existing configurations from organization_options to the PreventAIConfiguration table to ensure continuity for existing users.
🤖 Prompt for AI Agent
Fix this bug. In src/sentry/overwatch/endpoints/overwatch_rpc.py at lines 21-28: The
`PreventPrReviewResolvedConfigsEndpoint` in `overwatch_rpc.py` reads configuration from
the old `organization.get_option` storage. However, the new
`OrganizationPreventGitHubConfigEndpoint` writes settings to the new
`PreventAIConfiguration` model. There is no data migration to move existing settings
from the old storage to the new model, nor is there any fallback logic for the read
endpoint to check the new model. As a result, any configuration changes made through the
new UI will be saved to the new model but will be completely ignored by the Overwatch
service, which will continue to use old or default settings from the previous storage
location.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feature is not live, don't need to make migration.
| response_data: dict[str, Any] = deepcopy(PREVENT_AI_CONFIG_GITHUB_DEFAULT) | ||
| response_data["github_organization"][git_organization_id] = request.data | ||
|
|
||
| return Response(response_data, status=200) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: A key in the default config object was renamed from github_organizations to github_organization, but the frontend code was not updated to match.
(Severity: High 0.75 | Confidence: 1.00)
🔍 Detailed Analysis
The default configuration object, PREVENT_AI_CONFIG_GITHUB_DEFAULT, has been modified, renaming the key github_organizations to github_organization. However, multiple frontend components, such as useUpdatePreventAIFeature.tsx and manageReposPanel.tsx, were not updated and still reference the old plural key github_organizations. When the frontend receives a configuration object from the backend using the new singular key, attempts to access config.github_organizations will result in undefined, breaking the UI for managing Prevent AI configurations.
💡 Suggested Fix
Update all frontend references from github_organizations to github_organization to match the new schema defined in the PREVENT_AI_CONFIG_GITHUB_DEFAULT constant. This includes updating type definitions in .tsx files and accessors in hooks and components.
🤖 Prompt for AI Agent
Fix this bug. In src/sentry/prevent/endpoints/pr_review_config.py at lines 87-90: The
default configuration object, `PREVENT_AI_CONFIG_GITHUB_DEFAULT`, has been modified,
renaming the key `github_organizations` to `github_organization`. However, multiple
frontend components, such as `useUpdatePreventAIFeature.tsx` and `manageReposPanel.tsx`,
were not updated and still reference the old plural key `github_organizations`. When the
frontend receives a configuration object from the backend using the new singular key,
attempts to access `config.github_organizations` will result in `undefined`, breaking
the UI for managing Prevent AI configurations.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frontend code is not live yet, it will be updated next.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: AI Config Endpoint Bypasses New Model
The PreventPrReviewResolvedConfigsEndpoint still reads prevent AI configuration from organization.get_option("sentry:prevent_ai_config_github"). This bypasses the new PreventAIConfiguration model, causing the endpoint to return default or stale configurations instead of the actual values, impacting external services.
src/sentry/overwatch/endpoints/overwatch_rpc.py#L75-L88
sentry/src/sentry/overwatch/endpoints/overwatch_rpc.py
Lines 75 to 88 in d9ce127
| return auth[0].lower() == self.token_name | |
| def authenticate_token(self, request: Request, token: str) -> tuple[Any, Any]: | |
| compare_signature(request, token) | |
| sentry_sdk.get_isolation_scope().set_tag("overwatch_rpc_auth", True) | |
| return (AnonymousUser(), token) | |
| def _can_use_prevent_ai_features(org: Organization) -> bool: | |
| """Check if organization has opted in to Prevent AI features.""" | |
| hide_ai_features = org.get_option("sentry:hide_ai_features", HIDE_AI_FEATURES_DEFAULT) | |
| pr_review_test_generation_enabled = bool( |
src/sentry/overwatch/endpoints/overwatch_rpc.py#L103-L107
sentry/src/sentry/overwatch/endpoints/overwatch_rpc.py
Lines 103 to 107 in d9ce127
| """ | |
| publish_status = { | |
| "GET": ApiPublishStatus.EXPERIMENTAL, | |
| } |
wedamija
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably suggest splitting out the new migration into a separate pr so that we can get it through more easily
|
|
||
| class Meta: | ||
| app_label = "prevent" | ||
| db_table = "sentry_preventaiconfiguration" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is in your own app, you can feel free to call this prevent_*
|
|
||
| __relocation_scope__ = RelocationScope.Excluded | ||
|
|
||
| organization_id = BoundedBigIntegerField(db_index=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use a proper foreign key here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a similar note, should we consider which silo this data should live in? I could see a case being made for either region or control, depending on where this is used the most.
|
|
||
| organization_id = BoundedBigIntegerField(db_index=True) | ||
| provider = models.CharField(max_length=64) | ||
| git_organization_id = models.CharField(max_length=255) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we link to the integration instead?
| organization_id = BoundedBigIntegerField(db_index=True) | ||
| provider = models.CharField(max_length=64) | ||
| git_organization_id = models.CharField(max_length=255) | ||
| data = models.JSONField(default=dict) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use more explicit fields here, instead of a json blob? What kind of data are we putting here?
Thanks for looking! I will move the table to a separate PR and make those schema changes. On using explicit fields instead of a json, it would make the table(s) a lot more confusing and inflexible. The current json object structure is defined like this, and being at very early stages of this product our configs change all the time so I feel its better to not lock it in with DB tables. |
The structure there looks pretty regular to me. Should the config have a link to a 1 -> M table that is defined like My experience with unstructured json blobs is that we always end up regretting it |
Yeah I hear you, thing is the configs for this product is so fluid right now, in a week I can see us use a whole different structure. So I'd rather get this config object more matured and when it comes to migrating to a DB schema later we will have to take that pill. While we are still building this pre-GA product I would prefer to be more flexible and not make DB migrations if possible. Also the structure would almost work except there's a nested "Repos" object in there that overrides the existing configs for the main "Org" object. 😿 |
|
This issue has gone three weeks without activity. In another week, I will close it. But! If you comment or otherwise update it, I will reset the clock, and if you remove the label "A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀 |
Creating a new table to manage prevent ai configurations, no longer use the previous method of managing it in organization_options. This will give more flexibility to storing configs across multiple git orgs and sentry orgs. Also we got feedback that we want members to be allowed to update config for the PR Review in order to change the type and frequency of reviews. Since this is in beta, there are no billing implications (where a member can create much higher usage that would then get billed). This is aligned with like Seer project settings and Github Integrations settings which allows members to edit.