diff --git a/migrations_lockfile.txt b/migrations_lockfile.txt index 4438ef2b222d73..ee75c5be2377b2 100644 --- a/migrations_lockfile.txt +++ b/migrations_lockfile.txt @@ -29,4 +29,4 @@ tempest: 0002_make_message_type_nullable uptime: 0032_stats_on_subscription -workflow_engine: 0045_add_unique_constraint_alert_rule_detector +workflow_engine: 0046_drop_metric_alert_fire_detectors diff --git a/src/sentry/workflow_engine/migrations/0046_drop_metric_alert_fire_detectors.py b/src/sentry/workflow_engine/migrations/0046_drop_metric_alert_fire_detectors.py new file mode 100644 index 00000000000000..e7bcdfbb3711fe --- /dev/null +++ b/src/sentry/workflow_engine/migrations/0046_drop_metric_alert_fire_detectors.py @@ -0,0 +1,52 @@ +# Generated by Django 5.1.7 on 2025-04-18 01:22 + +from django.db import migrations +from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.migrations.state import StateApps + +from sentry.new_migrations.migrations import CheckedMigration + + +def delete_metric_alert_fire_detectors( + apps: StateApps, schema_editor: BaseDatabaseSchemaEditor +) -> None: + Detector = apps.get_model("workflow_engine", "Detector") + DetectorWorkflow = apps.get_model("workflow_engine", "DetectorWorkflow") + Workflow = apps.get_model("workflow_engine", "Workflow") + + detectors = Detector.objects.filter(type="metric_alert_fire") + workflow_ids = DetectorWorkflow.objects.filter(detector__in=detectors).values_list( + "workflow__id", flat=True + ) + workflows = Workflow.objects.filter(id__in=workflow_ids) + + workflows.delete() + detectors.delete() + + +class Migration(CheckedMigration): + # This flag is used to mark that a migration shouldn't be automatically run in production. + # This should only be used for operations where it's safe to run the migration after your + # code has deployed. So this should not be used for most operations that alter the schema + # of a table. + # Here are some things that make sense to mark as post deployment: + # - Large data migrations. Typically we want these to be run manually so that they can be + # monitored and not block the deploy for a long period of time while they run. + # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to + # run this outside deployments so that we don't block them. Note that while adding an index + # is a schema change, it's completely safe to run the operation after the code has deployed. + # Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment + + is_post_deployment = True + + dependencies = [ + ("workflow_engine", "0045_add_unique_constraint_alert_rule_detector"), + ] + + operations = [ + migrations.RunPython( + code=delete_metric_alert_fire_detectors, + reverse_code=migrations.RunPython.noop, + hints={"tables": ["workflow_engine.Detector"]}, + ), + ] diff --git a/tests/sentry/workflow_engine/migrations/test_0046_drop_metric_alert_fire_detectors.py b/tests/sentry/workflow_engine/migrations/test_0046_drop_metric_alert_fire_detectors.py new file mode 100644 index 00000000000000..aeb6bb2c156803 --- /dev/null +++ b/tests/sentry/workflow_engine/migrations/test_0046_drop_metric_alert_fire_detectors.py @@ -0,0 +1,39 @@ +from sentry.models.organization import Organization +from sentry.testutils.cases import TestMigrations +from sentry.workflow_engine.models.detector import Detector + + +class DropMetricAlertFireDetectors(TestMigrations): + app = "workflow_engine" + migrate_from = "0045_add_unique_constraint_alert_rule_detector" + migrate_to = "0046_drop_metric_alert_fire_detectors" + + def setup_before_migration(self, app): + self.organization = Organization.objects.create(name="test", slug="test") + self.project = self.create_project(organization=self.organization) + + detector_field_values = { + "project_id": self.project.id, + "name": "test", + "description": "test", + "workflow_condition_group": None, + "owner_user_id": None, + "owner_team": None, + "config": { + "threshold_period": 1, + "comparison_delta": 300, + "detection_type": "static", + }, + "enabled": True, + "created_by_id": None, + "type": "metric_alert_fire", + } + + Detector.objects.create(**detector_field_values) + detector_field_values["type"] = "monitor_check_in_failure" + Detector.objects.create(**detector_field_values) + + assert Detector.objects.filter(type="metric_alert_fire").count() == 1 + + def test(self): + assert Detector.objects.filter(type="metric_alert_fire").count() == 0