Skip to content

Commit 1a4b8ff

Browse files
authored
fix(ACI): Migrate fallthroughType to fallthrough_type (#103764)
Companion PR to #103694 to migrate `fallthroughType` to `fallthrough_type` in `Action.data`. Other PR must be merged first.
1 parent e7597d8 commit 1a4b8ff

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ tempest: 0003_use_encrypted_char_field
3939

4040
uptime: 0049_cleanup_failed_safe_deletes
4141

42-
workflow_engine: 0103_add_unique_constraint
42+
workflow_engine: 0104_action_data_fallthrough_type
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Generated by Django 5.2.8 on 2025-11-24 19:57
2+
3+
from django.db import migrations
4+
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
5+
from django.db.migrations.state import StateApps
6+
7+
from sentry.new_migrations.migrations import CheckedMigration
8+
from sentry.utils.query import RangeQuerySetWrapper
9+
10+
11+
def migrate_fallthrough_type(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
12+
Action = apps.get_model("workflow_engine", "Action")
13+
for action in RangeQuerySetWrapper(Action.objects.all()):
14+
if "fallthroughType" in action.data:
15+
new_data = action.data.copy()
16+
del new_data["fallthroughType"]
17+
new_data["fallthrough_type"] = action.data["fallthroughType"]
18+
action.data = new_data
19+
action.save()
20+
21+
22+
class Migration(CheckedMigration):
23+
# This flag is used to mark that a migration shouldn't be automatically run in production.
24+
# This should only be used for operations where it's safe to run the migration after your
25+
# code has deployed. So this should not be used for most operations that alter the schema
26+
# of a table.
27+
# Here are some things that make sense to mark as post deployment:
28+
# - Large data migrations. Typically we want these to be run manually so that they can be
29+
# monitored and not block the deploy for a long period of time while they run.
30+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
31+
# run this outside deployments so that we don't block them. Note that while adding an index
32+
# is a schema change, it's completely safe to run the operation after the code has deployed.
33+
# Once deployed, run these manually via: https://develop.sentry.dev/database-migrations/#migration-deployment
34+
35+
is_post_deployment = True
36+
37+
dependencies = [
38+
("workflow_engine", "0103_add_unique_constraint"),
39+
]
40+
41+
operations = [
42+
migrations.RunPython(
43+
code=migrate_fallthrough_type,
44+
reverse_code=migrations.RunPython.noop,
45+
hints={"tables": ["workflow_engine_action"]},
46+
),
47+
]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from sentry.notifications.models.notificationaction import ActionTarget
2+
from sentry.notifications.types import FallthroughChoiceType
3+
from sentry.testutils.cases import TestMigrations
4+
from sentry.workflow_engine.models import Action
5+
6+
7+
class TestActionDataFallthroughType(TestMigrations):
8+
migrate_from = "0103_add_unique_constraint"
9+
migrate_to = "0104_action_data_fallthrough_type"
10+
app = "workflow_engine"
11+
12+
def setup_initial_state(self) -> None:
13+
self.org = self.create_organization(name="test-org")
14+
self.project = self.create_project(organization=self.org)
15+
16+
self.action = Action.objects.create(
17+
type="email",
18+
data={"fallthroughType": FallthroughChoiceType.ACTIVE_MEMBERS},
19+
config={
20+
"target_type": ActionTarget.ISSUE_OWNERS,
21+
"target_identifier": None,
22+
},
23+
)
24+
self.action_no_fallthrough = Action.objects.create(
25+
type="email",
26+
data={},
27+
config={
28+
"target_type": ActionTarget.USER,
29+
"target_identifier": str(self.user.id),
30+
},
31+
)
32+
33+
def test_migration(self) -> None:
34+
fallthrough_action = Action.objects.filter(
35+
data={"fallthrough_type": FallthroughChoiceType.ACTIVE_MEMBERS}
36+
)
37+
assert len(fallthrough_action) == 1
38+
39+
no_fallthrough_action = Action.objects.filter(data={})
40+
assert len(no_fallthrough_action) == 1

0 commit comments

Comments
 (0)