feat(seer): Seer Autofix Settings Overview page#110758
Conversation
141f1d5 to
8f598e9
Compare
4549dff to
5d35c75
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for all 4 issues found in the latest run.
- ✅ Fixed: Feature flag bypass hardcoded to
true- Removed the hardcoded
truevalue and restored the proper feature flag checkorganization.features.includes('seer-overview').
- Removed the hardcoded
- ✅ Fixed: Wrong count passed to
tnfor button pluralization- Changed the count parameter in both
tncalls from the count of matching projects toprojects.lengthto correctly reflect total project count.
- Changed the count parameter in both
- ✅ Fixed: Unused duplicate utility file added
- Deleted the unused duplicate utility file at
static/app/views/settings/seer/overview/utils/organizationIntegrationsQueryOptions.ts.
- Deleted the unused duplicate utility file at
- ✅ Fixed: Bulk update silently applies wrong agent during loading
- Added
isIntegrationsPendingcheck to disable the bulk update button while integrations are loading, preventing incorrect agent selection.
- Added
Or push these changes by commenting:
@cursor push 3da9b8084f
Preview (3da9b8084f)
diff --git a/static/app/views/settings/seer/overview/autofixOverviewSection.tsx b/static/app/views/settings/seer/overview/autofixOverviewSection.tsx
--- a/static/app/views/settings/seer/overview/autofixOverviewSection.tsx
+++ b/static/app/views/settings/seer/overview/autofixOverviewSection.tsx
@@ -218,7 +218,7 @@
projects: Project[];
projectsWithPreferredAgent: AutofixAutomationSettings[];
}) {
- const {data: integrations} = useQuery(
+ const {data: integrations, isPending: isIntegrationsPending} = useQuery(
organizationIntegrationsCodingAgents(organization)
);
const rawAgentOptions = useAgentOptions({
@@ -310,6 +310,7 @@
disabled={
!canWrite ||
isBulkMutatingAgent ||
+ isIntegrationsPending ||
projectsWithPreferredAgent.length === projects.length
}
onClick={async () => {
@@ -321,7 +322,7 @@
{tn(
'Set for the existing project',
'Set for all existing projects',
- projectsWithPreferredAgent.length
+ projects.length
)}
</Button>
<Text variant="secondary" size="sm">
@@ -428,12 +429,12 @@
? tn(
'Enable for the existing project',
'Enable for all existing projects',
- projectsWithCreatePr.length
+ projects.length
)
: tn(
'Disable for the existing project',
'Disable for all existing projects',
- projectsWithCreatePr.length
+ projects.length
)}
</Button>
<Text variant="secondary" size="sm">
diff --git a/static/app/views/settings/seer/overview/utils/organizationIntegrationsQueryOptions.ts b/static/app/views/settings/seer/overview/utils/organizationIntegrationsQueryOptions.ts
deleted file mode 100644
--- a/static/app/views/settings/seer/overview/utils/organizationIntegrationsQueryOptions.ts
+++ /dev/null
@@ -1,22 +1,0 @@
-import type {OrganizationIntegration} from 'sentry/types/integrations';
-import type {Organization} from 'sentry/types/organization';
-import {apiOptions} from 'sentry/utils/api/apiOptions';
-
-export function organizationIntegrationsQueryOptions({
- organization,
- staleTime = 60_000,
- includeConfig = 0,
-}: {
- organization: Organization;
- includeConfig?: number;
- staleTime?: number;
-}) {
- return apiOptions.as<OrganizationIntegration[]>()(
- '/organizations/$organizationIdOrSlug/integrations/',
- {
- path: {organizationIdOrSlug: organization.slug},
- query: {includeConfig},
- staleTime,
- }
- );
-}
\ No newline at end of file
diff --git a/static/gsApp/views/seerAutomation/settings.tsx b/static/gsApp/views/seerAutomation/settings.tsx
--- a/static/gsApp/views/seerAutomation/settings.tsx
+++ b/static/gsApp/views/seerAutomation/settings.tsx
@@ -46,7 +46,7 @@
const organization = useOrganization();
const canWrite = useCanWriteSettings();
- const showSeerOverview = true; // organization.features.includes('seer-overview');
+ const showSeerOverview = organization.features.includes('seer-overview');
const scmOverviewData = useSCMOverviewSection();
const autofixOverviewData = useAutofixOverviewData();This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| const canWrite = useCanWriteSettings(); | ||
|
|
||
| const showSeerOverview = organization.features.includes('seer-overview'); | ||
| const showSeerOverview = true; // organization.features.includes('seer-overview'); |
There was a problem hiding this comment.
Feature flag bypass hardcoded to true
High Severity
The showSeerOverview variable is hardcoded to true with the original feature flag check (organization.features.includes('seer-overview')) commented out. This means the new Seer Overview UI will be shown to all users unconditionally, bypassing the feature flag gate intended to control the rollout.
| const canWrite = useCanWriteSettings(); | ||
|
|
||
| const showSeerOverview = organization.features.includes('seer-overview'); | ||
| const showSeerOverview = true; // organization.features.includes('seer-overview'); |
There was a problem hiding this comment.
Bug: The showSeerOverview variable is hardcoded to true, bypassing the seer-overview feature flag check and exposing the feature to all users.
Severity: HIGH
Suggested Fix
Remove the hardcoded true value and restore the original feature flag check by uncommenting the code. The line should be: const showSeerOverview = organization.features.includes('seer-overview');.
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: static/gsApp/views/seerAutomation/settings.tsx#L49
Potential issue: The variable `showSeerOverview` is hardcoded to `true`, while the
intended feature flag check, `organization.features.includes('seer-overview')`, is
commented out. This will cause the Seer Overview UI, including the
`AutofixOverviewSection` and `CodeReviewOverviewSection`, to be displayed to all users,
even those in organizations for which the `seer-overview` feature is not enabled. This
appears to be leftover debugging code that was accidentally committed, bypassing the
intended feature gating.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
There are 5 total unresolved issues (including 1 from previous review).
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| const preferredAgentProjectIds = new Set( | ||
| projectsWithPreferredAgent.map(s => s.projectId) | ||
| ); | ||
| const projectsToUpdate = projects.filter(p => !preferredAgentProjectIds.has(p.id)); |
There was a problem hiding this comment.
Bulk agent update uses stale selection
Medium Severity
AgentNameForm derives preferredAgentValue, preferredAgentIntegration, and projectsToUpdate from organization and projectsWithPreferredAgent, not from the current field.state.value. If the dropdown changes and bulk action is clicked before org/query refresh completes, the bulk mutation can apply the previous agent to projects.
Additional Locations (1)
| const projectsWithCreatePrIds = new Set(projectsWithCreatePr.map(s => s.projectId)); | ||
| const projectsToUpdate = projects.filter(p => !projectsWithCreatePrIds.has(p.id)); | ||
|
|
||
| const bulkMutateCreatePr = useBulkMutateCreatePr({projects: projectsToUpdate}); |
There was a problem hiding this comment.
Create PR bulk target set inverted
Medium Severity
CreatePrForm computes projectsToUpdate from projectsWithCreatePr, which is derived from organization.autoOpenPrs, while bulk mutation uses field.state.value. When the switch is toggled, the selected mode and the filtered project set can disagree, causing bulk enable/disable to run on the wrong projects or be incorrectly disabled.
Additional Locations (1)
| fn, | ||
| }: Props<Item, Result>): Promise<Array<PromiseSettledResult<Result>>> { | ||
| const results: Array<PromiseSettledResult<Result>> = []; | ||
| for (let i = 0; i < items.length; i += chunkSize) { |
| // Always invalidate to sync cache with whatever the server actually saved | ||
| queryClient.invalidateQueries({ | ||
| queryKey: autofixSettingsQueryOptions.queryKey, | ||
| }); |
There was a problem hiding this comment.
Bulk mutations leave project caches stale
Medium Severity
Both bulk hooks invalidate only bulkAutofixAutomationSettingsInfiniteOptions and skip invalidating per-project seer/preferences and project detail queries. After bulk apply, pages already using those caches can keep showing outdated agent or PR settings until a hard refresh or unrelated refetch.
Additional Locations (1)
First pass at a Seer Settings Overview page. To help people get oriented while they're getting setup.



First pass at a Seer Settings Overview page. To help people get oriented while they're getting setup.