ref(uptime): remove uptime-runtime-assertions feature flag#110478
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Removing backend flag breaks frontend assertions UI
- Updated useUptimeAssertionFeatures hook to always return true for hasRuntimeAssertions since the feature is now GA'd, and removed obsolete tests that checked disabled feature flag behavior.
Or push these changes by commenting:
@cursor push 901560fb6d
Preview (901560fb6d)
diff --git a/static/app/views/alerts/rules/uptime/uptimeAlertForm.spec.tsx b/static/app/views/alerts/rules/uptime/uptimeAlertForm.spec.tsx
--- a/static/app/views/alerts/rules/uptime/uptimeAlertForm.spec.tsx
+++ b/static/app/views/alerts/rules/uptime/uptimeAlertForm.spec.tsx
@@ -432,12 +432,7 @@
});
it('sends assertion in create request when feature is enabled', async () => {
- const orgWithAssertions = OrganizationFixture({
- features: ['uptime-runtime-assertions'],
- });
- OrganizationStore.onUpdate(orgWithAssertions);
-
- render(<UptimeAlertForm />, {organization: orgWithAssertions});
+ render(<UptimeAlertForm />);
await screen.findByText('Configure Request');
// Verify the Verification section is shown
@@ -453,7 +448,7 @@
await userEvent.type(name, 'Rule with Assertion');
const createMock = MockApiClient.addMockResponse({
- url: `/projects/${orgWithAssertions.slug}/${project.slug}/uptime/`,
+ url: `/projects/${organization.slug}/${project.slug}/uptime/`,
method: 'POST',
});
@@ -490,25 +485,8 @@
);
});
- it('does not show assertions when feature is disabled', async () => {
- const orgWithoutAssertions = OrganizationFixture({
- features: [],
- });
- OrganizationStore.onUpdate(orgWithoutAssertions);
- render(<UptimeAlertForm />, {organization: orgWithoutAssertions});
- await screen.findByText('Configure Request');
-
- // Verify the Verification section is NOT shown
- expect(screen.queryByText('Verification')).not.toBeInTheDocument();
- });
-
it('renders and updates assertion for existing rule', async () => {
- const orgWithAssertions = OrganizationFixture({
- features: ['uptime-runtime-assertions'],
- });
- OrganizationStore.onUpdate(orgWithAssertions);
-
const assertion: UptimeAssertion = {
root: {
op: UptimeOpType.AND,
@@ -532,11 +510,11 @@
assertion,
});
- render(<UptimeAlertForm rule={rule} />, {organization: orgWithAssertions});
+ render(<UptimeAlertForm rule={rule} />);
await screen.findByText('Verification');
const updateMock = MockApiClient.addMockResponse({
- url: `/projects/${orgWithAssertions.slug}/${project.slug}/uptime/${rule.id}/`,
+ url: `/projects/${organization.slug}/${project.slug}/uptime/${rule.id}/`,
method: 'PUT',
});
@@ -555,12 +533,7 @@
it('displays assertion compilation errors', async () => {
const addErrorMessageSpy = jest.spyOn(indicators, 'addErrorMessage');
- const orgWithAssertions = OrganizationFixture({
- features: ['uptime-runtime-assertions'],
- });
- OrganizationStore.onUpdate(orgWithAssertions);
-
- render(<UptimeAlertForm />, {organization: orgWithAssertions});
+ render(<UptimeAlertForm />);
await screen.findByText('Verification');
await selectEvent.select(input('Project'), project.slug);
@@ -573,7 +546,7 @@
await userEvent.type(name, 'Rule with Invalid Assertion');
MockApiClient.addMockResponse({
- url: `/projects/${orgWithAssertions.slug}/${project.slug}/uptime/`,
+ url: `/projects/${organization.slug}/${project.slug}/uptime/`,
method: 'POST',
statusCode: 400,
body: {
@@ -609,12 +582,7 @@
it('displays assertion serialization error toast', async () => {
const addErrorMessageSpy = jest.spyOn(indicators, 'addErrorMessage');
- const orgWithAssertions = OrganizationFixture({
- features: ['uptime-runtime-assertions'],
- });
- OrganizationStore.onUpdate(orgWithAssertions);
-
- render(<UptimeAlertForm />, {organization: orgWithAssertions});
+ render(<UptimeAlertForm />);
await screen.findByText('Verification');
await selectEvent.select(input('Project'), project.slug);
@@ -627,7 +595,7 @@
await userEvent.type(name, 'Rule with Invalid Assertion');
MockApiClient.addMockResponse({
- url: `/projects/${orgWithAssertions.slug}/${project.slug}/uptime/`,
+ url: `/projects/${organization.slug}/${project.slug}/uptime/`,
method: 'POST',
statusCode: 400,
body: {
@@ -649,11 +617,6 @@
});
it('preserves null assertion when editing rule without assertions', async () => {
- const orgWithAssertions = OrganizationFixture({
- features: ['uptime-runtime-assertions'],
- });
- OrganizationStore.onUpdate(orgWithAssertions);
-
// Rule with no assertions (assertion: null from API)
const rule = UptimeRuleFixture({
name: 'Rule without Assertion',
@@ -663,7 +626,7 @@
assertion: null,
});
- render(<UptimeAlertForm rule={rule} />, {organization: orgWithAssertions});
+ render(<UptimeAlertForm rule={rule} />);
await screen.findByText('Verification');
// Should show empty UI - Add Assertion button but no assertion inputs
@@ -675,7 +638,7 @@
).toBeLessThanOrEqual(0);
const updateMock = MockApiClient.addMockResponse({
- url: `/projects/${orgWithAssertions.slug}/${project.slug}/uptime/${rule.id}/`,
+ url: `/projects/${organization.slug}/${project.slug}/uptime/${rule.id}/`,
method: 'PUT',
});
@@ -692,98 +655,4 @@
);
});
- it('preserves null assertion when feature flag is disabled', async () => {
- // When the feature flag is off, the assertions field isn't rendered,
- // so we need to ensure the original null assertion is preserved on submit
- const orgWithoutAssertions = OrganizationFixture({
- features: [],
- });
- OrganizationStore.onUpdate(orgWithoutAssertions);
-
- const rule = UptimeRuleFixture({
- name: 'Rule without Assertion',
- projectSlug: project.slug,
- url: 'https://existing-url.com',
- owner: ActorFixture(),
- assertion: null,
- });
-
- render(<UptimeAlertForm rule={rule} />, {organization: orgWithoutAssertions});
- await screen.findByText('Configure Request');
-
- // Verification section should NOT be shown
- expect(screen.queryByText('Verification')).not.toBeInTheDocument();
-
- const updateMock = MockApiClient.addMockResponse({
- url: `/projects/${orgWithoutAssertions.slug}/${project.slug}/uptime/${rule.id}/`,
- method: 'PUT',
- });
-
- await userEvent.click(screen.getByRole('button', {name: 'Save Rule'}));
-
- // Should submit null assertion, not the empty default structure
- expect(updateMock).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- data: expect.objectContaining({
- assertion: null,
- }),
- })
- );
- });
-
- it('preserves existing assertion when feature flag is disabled', async () => {
- // When the feature flag is off but the rule has existing assertions,
- // those assertions should be preserved on submit
- const orgWithoutAssertions = OrganizationFixture({
- features: [],
- });
- OrganizationStore.onUpdate(orgWithoutAssertions);
-
- const existingAssertion: UptimeAssertion = {
- root: {
- op: UptimeOpType.AND,
- children: [
- {
- id: 'test-1',
- op: UptimeOpType.STATUS_CODE_CHECK,
- operator: {cmp: UptimeComparisonType.EQUALS},
- value: 200,
- },
- ],
- id: 'root-1',
- },
- };
-
- const rule = UptimeRuleFixture({
- name: 'Rule with Assertion',
- projectSlug: project.slug,
- url: 'https://existing-url.com',
- owner: ActorFixture(),
- assertion: existingAssertion,
- });
-
- render(<UptimeAlertForm rule={rule} />, {organization: orgWithoutAssertions});
- await screen.findByText('Configure Request');
-
- // Verification section should NOT be shown
- expect(screen.queryByText('Verification')).not.toBeInTheDocument();
-
- const updateMock = MockApiClient.addMockResponse({
- url: `/projects/${orgWithoutAssertions.slug}/${project.slug}/uptime/${rule.id}/`,
- method: 'PUT',
- });
-
- await userEvent.click(screen.getByRole('button', {name: 'Save Rule'}));
-
- // Should submit the existing assertion unchanged
- expect(updateMock).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- data: expect.objectContaining({
- assertion: existingAssertion,
- }),
- })
- );
- });
});
diff --git a/static/app/views/alerts/rules/uptime/useUptimeAssertionFeatures.tsx b/static/app/views/alerts/rules/uptime/useUptimeAssertionFeatures.tsx
--- a/static/app/views/alerts/rules/uptime/useUptimeAssertionFeatures.tsx
+++ b/static/app/views/alerts/rules/uptime/useUptimeAssertionFeatures.tsx
@@ -3,9 +3,7 @@
export function useUptimeAssertionFeatures() {
const organization = useOrganization();
- const hasRuntimeAssertions = organization.features.includes(
- 'uptime-runtime-assertions'
- );
+ const hasRuntimeAssertions = true;
const hasAiAssertionSuggestions =
hasRuntimeAssertions &&
organization.features.includes('uptime-ai-assertion-suggestions') &&This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
Backend Test FailuresFailures on
|
499cd85 to
ccbb75c
Compare
9a9fb46 to
327f815
Compare
327f815 to
cf74167
Compare
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.
| def _validate_check_config( | ||
| attrs, uptime_subscription: UptimeSubscription | None, organization, user | ||
| ): | ||
| assertions_enabled = features.has( |
There was a problem hiding this comment.
Unused parameters after feature flag removal
Low Severity
The organization and user parameters of _validate_check_config are now completely unused after the features.has("organizations:uptime-runtime-assertions", ...) check was removed. The function body no longer references either parameter, but all three callers still pass them. These dead parameters add confusion about the function's actual dependencies.
GA'd in options-automator, so remove all flag checks and clean up the conditional logic that gated assertion validation and preview execution.
cf74167 to
ab53e0f
Compare
GA'd in options-automator, so remove all flag checks and clean up the conditional logic that gated assertion validation and preview execution.



GA'd in options-automator, so remove all flag checks and clean up the
conditional logic that gated assertion validation and preview execution.