diff --git a/fixtures/backup/model_dependencies/detailed.json b/fixtures/backup/model_dependencies/detailed.json index e8f1a408d32fd0..484150578d6b61 100644 --- a/fixtures/backup/model_dependencies/detailed.json +++ b/fixtures/backup/model_dependencies/detailed.json @@ -6505,12 +6505,17 @@ ] }, "workflow_engine.detector": { - "dangling": false, + "dangling": true, "foreign_keys": { + "created_by_id": { + "kind": "HybridCloudForeignKey", + "model": "sentry.user", + "nullable": true + }, "organization": { "kind": "FlexibleForeignKey", "model": "sentry.organization", - "nullable": false + "nullable": true }, "owner_team": { "kind": "FlexibleForeignKey", @@ -6522,6 +6527,11 @@ "model": "sentry.user", "nullable": true }, + "project": { + "kind": "FlexibleForeignKey", + "model": "sentry.project", + "nullable": true + }, "workflow_condition_group": { "kind": "FlexibleForeignKey", "model": "workflow_engine.dataconditiongroup", @@ -6591,11 +6601,31 @@ "workflow_engine.workflow": { "dangling": false, "foreign_keys": { + "created_by_id": { + "kind": "HybridCloudForeignKey", + "model": "sentry.user", + "nullable": true + }, + "environment": { + "kind": "FlexibleForeignKey", + "model": "sentry.environment", + "nullable": true + }, "organization": { "kind": "FlexibleForeignKey", "model": "sentry.organization", "nullable": false }, + "owner_team": { + "kind": "FlexibleForeignKey", + "model": "sentry.team", + "nullable": true + }, + "owner_user_id": { + "kind": "HybridCloudForeignKey", + "model": "sentry.user", + "nullable": true + }, "when_condition_group": { "kind": "FlexibleForeignKey", "model": "workflow_engine.dataconditiongroup", diff --git a/fixtures/backup/model_dependencies/flat.json b/fixtures/backup/model_dependencies/flat.json index 42e4fe237389f3..19a7288b784fd6 100644 --- a/fixtures/backup/model_dependencies/flat.json +++ b/fixtures/backup/model_dependencies/flat.json @@ -899,6 +899,7 @@ ], "workflow_engine.detector": [ "sentry.organization", + "sentry.project", "sentry.team", "sentry.user", "workflow_engine.dataconditiongroup" @@ -911,7 +912,10 @@ "workflow_engine.workflow" ], "workflow_engine.workflow": [ + "sentry.environment", "sentry.organization", + "sentry.team", + "sentry.user", "workflow_engine.dataconditiongroup" ], "workflow_engine.workflowdataconditiongroup": [ diff --git a/fixtures/backup/model_dependencies/sorted.json b/fixtures/backup/model_dependencies/sorted.json index 66ced698878d1a..ed161f7396d898 100644 --- a/fixtures/backup/model_dependencies/sorted.json +++ b/fixtures/backup/model_dependencies/sorted.json @@ -53,12 +53,6 @@ "workflow_engine.dataconditiongroup", "workflow_engine.dataconditiongroupaction", "workflow_engine.datasource", - "workflow_engine.detector", - "workflow_engine.detectorstate", - "workflow_engine.workflow", - "workflow_engine.workflowdataconditiongroup", - "workflow_engine.detectorworkflow", - "workflow_engine.datasourcedetector", "workflow_engine.datacondition", "sentry.savedsearch", "sentry.rollbackuser", @@ -119,6 +113,9 @@ "flags.flagwebhooksigningsecretmodel", "flags.flagauditlogmodel", "feedback.feedback", + "workflow_engine.workflow", + "workflow_engine.detector", + "workflow_engine.datasourcedetector", "uptime.projectuptimesubscription", "sentry.userreport", "sentry.useroption", @@ -205,6 +202,9 @@ "sentry.apiauthorization", "sentry.alertrule", "hybridcloud.apitokenreplica", + "workflow_engine.workflowdataconditiongroup", + "workflow_engine.detectorworkflow", + "workflow_engine.detectorstate", "sentry.teamkeytransaction", "sentry.snubaqueryeventtype", "sentry.sentryappinstallation", diff --git a/fixtures/backup/model_dependencies/truncate.json b/fixtures/backup/model_dependencies/truncate.json index 8f0aa950ece716..ca18f7967a33b4 100644 --- a/fixtures/backup/model_dependencies/truncate.json +++ b/fixtures/backup/model_dependencies/truncate.json @@ -53,12 +53,6 @@ "workflow_engine_dataconditiongroup", "workflow_engine_dataconditiongroupaction", "workflow_engine_datasource", - "workflow_engine_detector", - "workflow_engine_detectorstate", - "workflow_engine_workflow", - "workflow_engine_workflowdataconditiongroup", - "workflow_engine_detectorworkflow", - "workflow_engine_datasourcedetector", "workflow_engine_datacondition", "sentry_savedsearch", "sentry_rollbackuser", @@ -119,6 +113,9 @@ "flags_webhooksigningsecret", "flags_audit_log", "feedback_feedback", + "workflow_engine_workflow", + "workflow_engine_detector", + "workflow_engine_datasourcedetector", "uptime_projectuptimesubscription", "sentry_userreport", "sentry_useroption", @@ -205,6 +202,9 @@ "sentry_apiauthorization", "sentry_alertrule", "hybridcloud_apitokenreplica", + "workflow_engine_workflowdataconditiongroup", + "workflow_engine_detectorworkflow", + "workflow_engine_detectorstate", "sentry_performanceteamkeytransaction", "sentry_snubaqueryeventtype", "sentry_sentryappinstallation", diff --git a/migrations_lockfile.txt b/migrations_lockfile.txt index 2d5deeb60aa756..0b551bac149069 100644 --- a/migrations_lockfile.txt +++ b/migrations_lockfile.txt @@ -13,4 +13,4 @@ replays: 0004_index_together sentry: 0792_add_unique_index_apiauthorization social_auth: 0002_default_auto_field uptime: 0018_add_trace_sampling_field_to_uptime -workflow_engine: 0013_related_name_conditions_on_dcg +workflow_engine: 0014_model_additions_for_milestones diff --git a/src/sentry/testutils/factories.py b/src/sentry/testutils/factories.py index 4afe946574b83d..9dc7d5513e3c29 100644 --- a/src/sentry/testutils/factories.py +++ b/src/sentry/testutils/factories.py @@ -2126,21 +2126,14 @@ def create_data_source( @staticmethod @assume_test_silo_mode(SiloMode.REGION) def create_detector( - organization: Organization | None = None, name: str | None = None, - owner_user_id: int | None = None, - owner_team: Team | None = None, **kwargs, ) -> Detector: - if organization is None: - organization = Factories.create_organization() if name is None: name = petname.generate(2, " ", letters=10).title() + return Detector.objects.create( - organization=organization, name=name, - owner_user_id=owner_user_id, - owner_team=owner_team, **kwargs, ) diff --git a/src/sentry/testutils/fixtures.py b/src/sentry/testutils/fixtures.py index 7cb89c175ff15d..26413e962a48c4 100644 --- a/src/sentry/testutils/fixtures.py +++ b/src/sentry/testutils/fixtures.py @@ -634,8 +634,16 @@ def create_data_condition( condition_group=condition_group, ) - def create_detector(self, *args, **kwargs) -> Detector: - return Factories.create_detector(*args, **kwargs) + def create_detector( + self, + *args, + project=None, + **kwargs, + ) -> Detector: + if project is None: + project = self.create_project(organization=self.organization) + + return Factories.create_detector(*args, project=project, **kwargs) def create_detector_state(self, *args, **kwargs) -> DetectorState: return Factories.create_detector_state(*args, **kwargs) diff --git a/src/sentry/testutils/helpers/backups.py b/src/sentry/testutils/helpers/backups.py index ce1bd24a36e1b1..a5912a71043342 100644 --- a/src/sentry/testutils/helpers/backups.py +++ b/src/sentry/testutils/helpers/backups.py @@ -659,7 +659,7 @@ def create_exhaustive_organization( # Setup a test 'Issue Rule' and 'Automation' workflow = self.create_workflow(organization=org) - detector = self.create_detector(organization=org) + detector = self.create_detector(project=project) self.create_detector_workflow(detector=detector, workflow=workflow) self.create_detector_state(detector=detector) diff --git a/src/sentry/workflow_engine/migrations/0014_model_additions_for_milestones.py b/src/sentry/workflow_engine/migrations/0014_model_additions_for_milestones.py new file mode 100644 index 00000000000000..00ab4ba74e3098 --- /dev/null +++ b/src/sentry/workflow_engine/migrations/0014_model_additions_for_milestones.py @@ -0,0 +1,120 @@ +# Generated by Django 5.1.1 on 2024-11-21 21:05 + +import django.db.models.deletion +from django.db import migrations, models + +import sentry.db.models.fields.foreignkey +import sentry.db.models.fields.hybrid_cloud_foreign_key +from sentry.new_migrations.migrations import CheckedMigration + + +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 = False + + dependencies = [ + ("sentry", "0792_add_unique_index_apiauthorization"), + ("workflow_engine", "0013_related_name_conditions_on_dcg"), + ] + + operations = [ + migrations.AddField( + model_name="detector", + name="config", + field=models.JSONField(db_default={}), + ), + migrations.AddField( + model_name="detector", + name="created_by_id", + field=sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( + "sentry.User", db_index=True, null=True, on_delete="SET_NULL" + ), + ), + migrations.AddField( + model_name="detector", + name="description", + field=models.TextField(null=True), + ), + migrations.AddField( + model_name="detector", + name="enabled", + field=models.BooleanField(db_default=True), + ), + migrations.AddField( + model_name="detector", + name="project", + field=sentry.db.models.fields.foreignkey.FlexibleForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to="sentry.project" + ), + ), + migrations.AddField( + model_name="workflow", + name="config", + field=models.JSONField(db_default={}), + ), + migrations.AddField( + model_name="workflow", + name="created_by_id", + field=sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( + "sentry.User", db_index=True, null=True, on_delete="SET_NULL" + ), + ), + migrations.AddField( + model_name="workflow", + name="enabled", + field=models.BooleanField(db_default=True), + ), + migrations.AddField( + model_name="workflow", + name="environment", + field=sentry.db.models.fields.foreignkey.FlexibleForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to="sentry.environment" + ), + ), + migrations.AddField( + model_name="workflow", + name="owner_team", + field=sentry.db.models.fields.foreignkey.FlexibleForeignKey( + null=True, on_delete=django.db.models.deletion.SET_NULL, to="sentry.team" + ), + ), + migrations.AddField( + model_name="workflow", + name="owner_user_id", + field=sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey( + "sentry.User", db_index=True, null=True, on_delete="SET_NULL" + ), + ), + migrations.AlterField( + model_name="action", + name="required", + field=models.BooleanField(default=False, null=True), + ), + migrations.AlterField( + model_name="detector", + name="organization", + field=sentry.db.models.fields.foreignkey.FlexibleForeignKey( + null=True, on_delete=django.db.models.deletion.CASCADE, to="sentry.organization" + ), + ), + migrations.AlterField( + model_name="workflow", + name="when_condition_group", + field=sentry.db.models.fields.foreignkey.FlexibleForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="workflow_engine.dataconditiongroup", + ), + ), + ] diff --git a/src/sentry/workflow_engine/models/action.py b/src/sentry/workflow_engine/models/action.py index c291e0b0aea7d6..6dd13d6c491870 100644 --- a/src/sentry/workflow_engine/models/action.py +++ b/src/sentry/workflow_engine/models/action.py @@ -24,17 +24,13 @@ class Type(models.TextChoices): Notification = "SendNotificationAction" TriggerWorkflow = "TriggerWorkflowAction" - """ - Required actions cannot be disabled by the user, and will not be displayed in the UI. - These actions will be used internally, to trigger other aspects of the system. - For example, creating a new issue in the Issue Platform or a detector emitting an event. - """ - required = models.BooleanField(default=False) - # The type field is used to denote the type of action we want to trigger type = models.TextField(choices=Type.choices) data = models.JSONField(default=dict) + # TODO - finish removing this field + required = models.BooleanField(default=False, null=True) + # LEGACY: The integration_id is used to map the integration_id found in the AlertRuleTriggerAction # This allows us to map the way we're saving the notification channels to the action. integration_id = HybridCloudForeignKey( diff --git a/src/sentry/workflow_engine/models/detector.py b/src/sentry/workflow_engine/models/detector.py index 8a17ee38e8ea56..6a0ffeadc5f8f6 100644 --- a/src/sentry/workflow_engine/models/detector.py +++ b/src/sentry/workflow_engine/models/detector.py @@ -4,15 +4,19 @@ import logging from typing import TYPE_CHECKING, Any +from django.conf import settings from django.db import models from django.db.models import UniqueConstraint from sentry.backup.scopes import RelocationScope from sentry.db.models import DefaultFieldsModel, FlexibleForeignKey, region_silo_model +from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey from sentry.issues import grouptype from sentry.issues.grouptype import GroupType from sentry.models.owner_base import OwnerModel +from .json_config import JSONConfigBase + if TYPE_CHECKING: from sentry.workflow_engine.processors.detector import DetectorHandler @@ -20,10 +24,13 @@ @region_silo_model -class Detector(DefaultFieldsModel, OwnerModel): +class Detector(DefaultFieldsModel, OwnerModel, JSONConfigBase): __relocation_scope__ = RelocationScope.Organization - organization = FlexibleForeignKey("sentry.Organization") + # TODO - Finish removing this field + organization = FlexibleForeignKey("sentry.Organization", on_delete=models.CASCADE, null=True) + + project = FlexibleForeignKey("sentry.Project", on_delete=models.CASCADE, null=True) name = models.CharField(max_length=200) # The data sources that the detector is watching @@ -31,7 +38,12 @@ class Detector(DefaultFieldsModel, OwnerModel): "workflow_engine.DataSource", through="workflow_engine.DataSourceDetector" ) - # The conditions that must be met for the detector to be considered 'active' + # If the detector is not enabled, it will not be evaluated. This is how we "snooze" a detector + enabled = models.BooleanField(db_default=True) + + # Optionally set a description of the detector, this will be used in notifications + description = models.TextField(null=True) + # This will emit an event for the workflow to process workflow_condition_group = FlexibleForeignKey( "workflow_engine.DataConditionGroup", @@ -40,8 +52,18 @@ class Detector(DefaultFieldsModel, OwnerModel): unique=True, on_delete=models.SET_NULL, ) + + # The type of detector that is being used, this is used to determine the class + # to load for the detector type = models.CharField(max_length=200) + # The user that created the detector + created_by_id = HybridCloudForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete="SET_NULL") + + @property + def CONFIG_SCHEMA(self) -> dict[str, Any]: + raise NotImplementedError('Subclasses must define a "CONFIG_SCHEMA" attribute') + class Meta(OwnerModel.Meta): constraints = OwnerModel.Meta.constraints + [ UniqueConstraint( @@ -50,11 +72,6 @@ class Meta(OwnerModel.Meta): ) ] - @property - def project_id(self): - # XXX: Temporary property until we add `project_id` to the model. - return 1 - @property def group_type(self) -> builtins.type[GroupType] | None: return grouptype.registry.get_by_slug(self.type) diff --git a/src/sentry/workflow_engine/models/json_config.py b/src/sentry/workflow_engine/models/json_config.py new file mode 100644 index 00000000000000..1b353ccf18cbcb --- /dev/null +++ b/src/sentry/workflow_engine/models/json_config.py @@ -0,0 +1,22 @@ +from abc import abstractproperty +from typing import Any + +from django.db import models +from jsonschema import ValidationError, validate + + +class JSONConfigBase(models.Model): + config = models.JSONField(db_default={}) + + @abstractproperty + def CONFIG_SCHEMA(self) -> dict[str, Any]: + pass + + def validate_config(self) -> None: + try: + validate(self.config, self.CONFIG_SCHEMA) + except ValidationError as e: + raise ValidationError(f"Invalid config: {e.message}") + + class Meta: + abstract = True diff --git a/src/sentry/workflow_engine/models/workflow.py b/src/sentry/workflow_engine/models/workflow.py index 4cb8fde6721cf4..d2f6e5fd5f0e01 100644 --- a/src/sentry/workflow_engine/models/workflow.py +++ b/src/sentry/workflow_engine/models/workflow.py @@ -1,13 +1,18 @@ +from typing import Any + +from django.conf import settings from django.db import models from sentry.backup.scopes import RelocationScope from sentry.db.models import DefaultFieldsModel, FlexibleForeignKey, region_silo_model, sane_repr +from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey +from sentry.models.owner_base import OwnerModel -from .data_condition_group import DataConditionGroup +from .json_config import JSONConfigBase @region_silo_model -class Workflow(DefaultFieldsModel): +class Workflow(DefaultFieldsModel, OwnerModel, JSONConfigBase): """ A workflow is a way to execute actions in a specified order. Workflows are initiated after detectors have been processed, driven by changes to their state. @@ -17,8 +22,19 @@ class Workflow(DefaultFieldsModel): name = models.CharField(max_length=200) organization = FlexibleForeignKey("sentry.Organization") + # If the workflow is not enabled, it will not be evaluated / invoke actions. This is how we "snooze" a workflow + enabled = models.BooleanField(db_default=True) + # Required as the 'when' condition for the workflow, this evalutes states emitted from the detectors - when_condition_group = FlexibleForeignKey(DataConditionGroup, blank=True, null=True) + when_condition_group = FlexibleForeignKey("workflow_engine.DataConditionGroup", null=True) + + environment = FlexibleForeignKey("sentry.Environment", null=True) + + created_by_id = HybridCloudForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete="SET_NULL") + + @property + def CONFIG_SCHEMA(self) -> dict[str, Any]: + raise NotImplementedError('Subclasses must define a "CONFIG_SCHEMA" attribute') __repr__ = sane_repr("name", "organization_id") diff --git a/tests/sentry/backup/snapshots/SanitizationExhaustiveTests/test_clean_pks.pysnap b/tests/sentry/backup/snapshots/SanitizationExhaustiveTests/test_clean_pks.pysnap index 3cdb0b1b55e1dd..5cfdb6869774b8 100644 --- a/tests/sentry/backup/snapshots/SanitizationExhaustiveTests/test_clean_pks.pysnap +++ b/tests/sentry/backup/snapshots/SanitizationExhaustiveTests/test_clean_pks.pysnap @@ -1,5 +1,5 @@ --- -created: '2024-11-06T18:15:33.745643+00:00' +created: '2024-11-15T23:09:32.075671+00:00' creator: sentry source: tests/sentry/backup/test_sanitize.py --- @@ -227,33 +227,6 @@ source: tests/sentry/backup/test_sanitize.py sanitized_fields: - date_added - date_updated -- model_name: workflow_engine.detector - ordinal: 1 - sanitized_fields: - - date_added - - date_updated - - name -- model_name: workflow_engine.workflow - ordinal: 1 - sanitized_fields: - - date_added - - date_updated - - name -- model_name: workflow_engine.workflowdataconditiongroup - ordinal: 1 - sanitized_fields: - - date_added - - date_updated -- model_name: workflow_engine.detectorworkflow - ordinal: 1 - sanitized_fields: - - date_added - - date_updated -- model_name: workflow_engine.datasourcedetector - ordinal: 1 - sanitized_fields: - - date_added - - date_updated - model_name: workflow_engine.datacondition ordinal: 1 sanitized_fields: @@ -484,6 +457,23 @@ source: tests/sentry/backup/test_sanitize.py - client_secret - date_added - name +- model_name: workflow_engine.workflow + ordinal: 1 + sanitized_fields: + - date_added + - date_updated + - name +- model_name: workflow_engine.detector + ordinal: 1 + sanitized_fields: + - date_added + - date_updated + - name +- model_name: workflow_engine.datasourcedetector + ordinal: 1 + sanitized_fields: + - date_added + - date_updated - model_name: sentry.useroption ordinal: 1 sanitized_fields: [] @@ -750,6 +740,16 @@ source: tests/sentry/backup/test_sanitize.py - date_added - date_modified - name +- model_name: workflow_engine.workflowdataconditiongroup + ordinal: 1 + sanitized_fields: + - date_added + - date_updated +- model_name: workflow_engine.detectorworkflow + ordinal: 1 + sanitized_fields: + - date_added + - date_updated - model_name: sentry.snubaqueryeventtype ordinal: 1 sanitized_fields: [] diff --git a/tests/sentry/backup/snapshots/test_comparators/test_default_comparators.pysnap b/tests/sentry/backup/snapshots/test_comparators/test_default_comparators.pysnap index 7f86fa482d0cc6..e7a8cbb8f59fd5 100644 --- a/tests/sentry/backup/snapshots/test_comparators/test_default_comparators.pysnap +++ b/tests/sentry/backup/snapshots/test_comparators/test_default_comparators.pysnap @@ -1,5 +1,5 @@ --- -created: '2024-11-14T18:22:29.534257+00:00' +created: '2024-11-21T21:10:04.656611+00:00' creator: sentry source: tests/sentry/backup/test_comparators.py --- @@ -1718,9 +1718,11 @@ source: tests/sentry/backup/test_comparators.py - date_updated - class: ForeignKeyComparator fields: + - created_by_id - organization - owner_team - owner_user_id + - project - workflow_condition_group model_name: workflow_engine.detector - comparators: @@ -1749,7 +1751,11 @@ source: tests/sentry/backup/test_comparators.py - date_updated - class: ForeignKeyComparator fields: + - created_by_id + - environment - organization + - owner_team + - owner_user_id - when_condition_group model_name: workflow_engine.workflow - comparators: diff --git a/tests/sentry/tasks/snapshots/PreprocessingTransferTest/test_success.pysnap b/tests/sentry/tasks/snapshots/PreprocessingTransferTest/test_success.pysnap index 917c0e9f5eb59b..973f822b2df6a8 100644 --- a/tests/sentry/tasks/snapshots/PreprocessingTransferTest/test_success.pysnap +++ b/tests/sentry/tasks/snapshots/PreprocessingTransferTest/test_success.pysnap @@ -1,5 +1,5 @@ --- -created: '2024-11-06T18:16:10.211369+00:00' +created: '2024-11-15T23:09:46.023372+00:00' creator: sentry source: tests/sentry/tasks/test_relocation.py --- @@ -96,7 +96,7 @@ steps: - -U - postgres - -c - - TRUNCATE sentry_controloption,sentry_integration,sentry_option,sentry_organization,sentry_organizationintegration,sentry_organizationoptions,sentry_projecttemplate,sentry_projecttemplateoption,sentry_relay,sentry_relayusage,sentry_repository,sentry_team,auth_user,sentry_userip,sentry_userpermission,sentry_userrole,sentry_userrole_users,workflow_engine_dataconditiongroup,workflow_engine_datasource,workflow_engine_detector,workflow_engine_workflow,workflow_engine_workflowdataconditiongroup,workflow_engine_detectorworkflow,workflow_engine_datasourcedetector,workflow_engine_datacondition,sentry_savedsearch,sentry_recentsearch,sentry_project,sentry_orgauthtoken,sentry_organizationmember,sentry_organizationaccessrequest,sentry_monitor,sentry_groupsearchview,sentry_environment,sentry_email,sentry_datasecrecywaiver,sentry_dashboardtombstone,sentry_dashboard,sentry_customdynamicsamplingrule,sentry_projectcounter,sentry_authprovider,sentry_authidentity,auth_authenticator,sentry_apikey,sentry_apiapplication,sentry_useroption,sentry_useremail,sentry_snubaquery,sentry_sentryapp,sentry_rule,sentry_querysubscription,sentry_projectteam,sentry_projectredirect,sentry_projectownership,sentry_projectoptions,sentry_projectkey,sentry_projectintegration,sentry_projectbookmark,sentry_organizationmember_teams,sentry_notificationaction,sentry_neglectedrule,sentry_environmentproject,sentry_dashboardwidget,sentry_dashboardpermissions,sentry_customdynamicsamplingruleproject,sentry_apitoken,sentry_apigrant,sentry_apiauthorization,sentry_alertrule,sentry_snubaqueryeventtype,sentry_sentryappinstallation,sentry_sentryappcomponent,sentry_rulesnooze,sentry_ruleactivity,sentry_notificationactionproject,sentry_dashboardwidgetquery,sentry_dashboardpermissionsteam,sentry_alertruletrigger,sentry_alertruleprojects,sentry_alertruleexcludedprojects,sentry_alertruleactivity,sentry_alertruleactivationcondition,sentry_servicehook,sentry_incident,sentry_dashboardwidgetqueryondemand,sentry_alertruletriggerexclusion,sentry_alertruletriggeraction,sentry_timeseriessnapshot,sentry_pendingincidentsnapshot,sentry_incidenttrigger,sentry_incidentsubscription,sentry_incidentsnapshot,sentry_incidentactivity + - TRUNCATE sentry_controloption,sentry_integration,sentry_option,sentry_organization,sentry_organizationintegration,sentry_organizationoptions,sentry_projecttemplate,sentry_projecttemplateoption,sentry_relay,sentry_relayusage,sentry_repository,sentry_team,auth_user,sentry_userip,sentry_userpermission,sentry_userrole,sentry_userrole_users,workflow_engine_dataconditiongroup,workflow_engine_datasource,workflow_engine_datacondition,sentry_savedsearch,sentry_recentsearch,sentry_project,sentry_orgauthtoken,sentry_organizationmember,sentry_organizationaccessrequest,sentry_monitor,sentry_groupsearchview,sentry_environment,sentry_email,sentry_datasecrecywaiver,sentry_dashboardtombstone,sentry_dashboard,sentry_customdynamicsamplingrule,sentry_projectcounter,sentry_authprovider,sentry_authidentity,auth_authenticator,sentry_apikey,sentry_apiapplication,workflow_engine_workflow,workflow_engine_detector,workflow_engine_datasourcedetector,sentry_useroption,sentry_useremail,sentry_snubaquery,sentry_sentryapp,sentry_rule,sentry_querysubscription,sentry_projectteam,sentry_projectredirect,sentry_projectownership,sentry_projectoptions,sentry_projectkey,sentry_projectintegration,sentry_projectbookmark,sentry_organizationmember_teams,sentry_notificationaction,sentry_neglectedrule,sentry_environmentproject,sentry_dashboardwidget,sentry_dashboardpermissions,sentry_customdynamicsamplingruleproject,sentry_apitoken,sentry_apigrant,sentry_apiauthorization,sentry_alertrule,workflow_engine_workflowdataconditiongroup,workflow_engine_detectorworkflow,sentry_snubaqueryeventtype,sentry_sentryappinstallation,sentry_sentryappcomponent,sentry_rulesnooze,sentry_ruleactivity,sentry_notificationactionproject,sentry_dashboardwidgetquery,sentry_dashboardpermissionsteam,sentry_alertruletrigger,sentry_alertruleprojects,sentry_alertruleexcludedprojects,sentry_alertruleactivity,sentry_alertruleactivationcondition,sentry_servicehook,sentry_incident,sentry_dashboardwidgetqueryondemand,sentry_alertruletriggerexclusion,sentry_alertruletriggeraction,sentry_timeseriessnapshot,sentry_pendingincidentsnapshot,sentry_incidenttrigger,sentry_incidentsubscription,sentry_incidentsnapshot,sentry_incidentactivity RESTART IDENTITY CASCADE; id: clear-database name: gcr.io/cloud-builders/docker diff --git a/tests/sentry/workflow_engine/processors/test_detector.py b/tests/sentry/workflow_engine/processors/test_detector.py index 07ad0a2e5ecfcd..e85704090fbf3c 100644 --- a/tests/sentry/workflow_engine/processors/test_detector.py +++ b/tests/sentry/workflow_engine/processors/test_detector.py @@ -86,7 +86,9 @@ def tearDown(self): def create_detector_and_conditions(self, type: str | None = None): if type is None: type = "handler_with_state" + self.project = self.create_project() detector = self.create_detector( + project=self.project, workflow_condition_group=self.create_data_condition_group(), type=type, ) @@ -464,7 +466,7 @@ def test_above_below_threshold(self): is_active=False, result=StatusChangeMessage( fingerprint=[f"{handler.detector.id}:val1"], - project_id=1, + project_id=self.project.id, new_status=1, new_substatus=None, ), @@ -613,7 +615,7 @@ def test_status_change(self): DetectorPriorityLevel.OK, result=StatusChangeMessage( fingerprint=[f"{handler.detector.id}:group_key"], - project_id=1, + project_id=self.project.id, new_status=1, new_substatus=None, ),