Skip to content

Commit

Permalink
feat: Add match_action for plugin configs (#22177)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored and timgl committed May 24, 2024
1 parent 79d309f commit 7571f51
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 4 deletions.
2 changes: 1 addition & 1 deletion latest_migrations.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ contenttypes: 0002_remove_content_type_name
ee: 0016_rolemembership_organization_member
otp_static: 0002_throttling
otp_totp: 0002_auto_20190420_0723
posthog: 0414_personalapikey_mask_value
posthog: 0415_pluginconfig_match_action
sessions: 0001_initial
social_django: 0010_uid_db_index
two_factor: 0007_auto_20201201_1019
4 changes: 2 additions & 2 deletions posthog/management/commands/test_migrations_are_safe.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def validate_migration_sql(sql) -> bool:
) # Ignore for brand-new tables
):
print(
f"\n\n\033[91mFound a CONSTRAINT command. This locks tables which causes downtime. Please avoid adding constraints to existing tables.\nSource: `{operation_sql}`"
f"\n\n\033[91mFound a CONSTRAINT command. This locks tables which causes downtime. Please avoid adding constraints to existing tables. For an example of how to do this safely see 0412_pluginconfig_match_action.py \nSource: `{operation_sql}`"
)
return True
if (
Expand All @@ -82,7 +82,7 @@ def validate_migration_sql(sql) -> bool:
and _get_table(" ON", operation_sql) not in new_tables
):
print(
f"\n\n\033[91mFound a CREATE INDEX command that isn't run CONCURRENTLY. This locks tables which causes downtime. Please add this index CONCURRENTLY instead.\nSource: `{operation_sql}`"
f"\n\n\033[91mFound a CREATE INDEX command that isn't run CONCURRENTLY. This locks tables which causes downtime. Please add this index CONCURRENTLY instead. For an example of how to do this safely see 0412_pluginconfig_match_action.py \nSource: `{operation_sql}`"
)
return True

Expand Down
86 changes: 86 additions & 0 deletions posthog/migrations/0415_pluginconfig_match_action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Generated by Django 4.2.11 on 2024-05-06 09:46

from django.db import migrations, models
import django.db.models.deletion

# NOTE for future readers: This migration handles adding a constraint in a non-blocking way
# Got this by running
# DEBUG=1 python manage.py makemigrations
# then
# DEBUG=1 python manage.py sqlmigrate posthog 0412_pluginconfig_match_action
# which output:
### BEGIN;
### --
### -- Add field match_action to pluginconfig
### --
### ALTER TABLE "posthog_pluginconfig" ADD COLUMN "match_action_id" integer NULL CONSTRAINT "posthog_pluginconfig_match_action_id_1cbf8562_fk_posthog_a" REFERENCES "posthog_action"("id") DEFERRABLE INITIALLY DEFERRED; SET CONSTRAINTS "posthog_pluginconfig_match_action_id_1cbf8562_fk_posthog_a" IMMEDIATE;
### CREATE INDEX "posthog_pluginconfig_match_action_id_1cbf8562" ON "posthog_pluginconfig" ("match_action_id");
### COMMIT;
# and then modify the migration from the below commented version to a safe non-blocking version


# # ORIGINIAL migration
# class Migration(migrations.Migration):
# dependencies = [
# ("posthog", "0411_eventproperty_indexes"),
# ]

# operations = [
# migrations.AddField(
# model_name="pluginconfig",
# name="match_action",
# field=models.ForeignKey(
# blank=True,
# null=True,
# on_delete=django.db.models.deletion.SET_NULL,
# related_name="plugin_configs",
# to="posthog.action",
# ),
# ),
# ]


class Migration(migrations.Migration):
atomic = False # Added to support concurrent index creation
dependencies = [
("posthog", "0414_personalapikey_mask_value"),
]

operations = [
migrations.SeparateDatabaseAndState(
state_operations=[
migrations.AddField(
model_name="pluginconfig",
name="match_action",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="plugin_configs",
to="posthog.action",
),
)
],
database_operations=[
# We add -- existing-table-constraint-ignore to ignore the constraint validation in CI.
migrations.RunSQL(
"""
ALTER TABLE "posthog_pluginconfig" ADD COLUMN "match_action_id" integer NULL CONSTRAINT "posthog_pluginconfig_match_action_id_1cbf8562_fk_posthog_a" REFERENCES "posthog_action"("id") DEFERRABLE INITIALLY DEFERRED; -- existing-table-constraint-ignore
SET CONSTRAINTS "posthog_pluginconfig_match_action_id_1cbf8562_fk_posthog_a" IMMEDIATE; -- existing-table-constraint-ignore
""",
reverse_sql="""
ALTER TABLE "posthog_pluginconfig" DROP COLUMN IF EXISTS "match_action_id";
""",
),
# We add CONCURRENTLY to the create command
migrations.RunSQL(
"""
CREATE INDEX CONCURRENTLY "posthog_pluginconfig_match_action_id_1cbf8562" ON "posthog_pluginconfig" ("match_action_id");
""",
reverse_sql="""
DROP INDEX IF EXISTS "posthog_pluginconfig_match_action_id_1cbf8562";
""",
),
],
),
]
10 changes: 9 additions & 1 deletion posthog/models/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,16 @@ class Meta:
# Used in the frontend
name: models.CharField = models.CharField(max_length=400, null=True, blank=True)
description: models.CharField = models.CharField(max_length=1000, null=True, blank=True)
# Used in the frontend to hide pluginConfgis that user deleted
# Used in the frontend to hide pluginConfigs that user deleted
deleted: models.BooleanField = models.BooleanField(default=False, null=True)
# If set, the plugin-server will only trigger this plugin for events that match this action
match_action = models.ForeignKey(
"posthog.Action",
on_delete=models.SET_NULL,
related_name="plugin_configs",
blank=True,
null=True,
)


class PluginAttachment(models.Model):
Expand Down

0 comments on commit 7571f51

Please sign in to comment.