From 4e0ed5c922883ddb878a0c7373f92b1fb597b6fe Mon Sep 17 00:00:00 2001 From: Iaroslav Zeigerman Date: Thu, 18 Sep 2025 20:19:08 -0700 Subject: [PATCH 1/2] Fix: Exempt seed models from migration --- sqlmesh/core/snapshot/definition.py | 2 +- tests/core/test_integration.py | 36 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/sqlmesh/core/snapshot/definition.py b/sqlmesh/core/snapshot/definition.py index 0d64736ffb..600d84fe83 100644 --- a/sqlmesh/core/snapshot/definition.py +++ b/sqlmesh/core/snapshot/definition.py @@ -1480,7 +1480,7 @@ def expiration_ts(self) -> int: @property def supports_schema_migration_in_prod(self) -> bool: """Returns whether or not this snapshot supports schema migration when deployed to production.""" - return self.is_paused and self.is_model and not self.is_symbolic + return self.is_paused and self.is_model and not self.is_symbolic and not self.is_seed @property def requires_schema_migration_in_prod(self) -> bool: diff --git a/tests/core/test_integration.py b/tests/core/test_integration.py index a0e41f329f..0f3ece812e 100644 --- a/tests/core/test_integration.py +++ b/tests/core/test_integration.py @@ -1672,6 +1672,42 @@ def test_run_with_select_models( } +@time_machine.travel("2023-01-08 15:00:00 UTC") +def test_seed_model_promote_to_prod_after_dev( + init_and_plan_context: t.Callable, +): + context, plan = init_and_plan_context("examples/sushi") + context.apply(plan) + + with open(context.path / "seeds" / "waiter_names.csv", "a") as f: + f.write("\n10,New Waiter") + + context.load() + + waiter_names_snapshot = context.get_snapshot("sushi.waiter_names") + plan = context.plan("dev", skip_tests=True, auto_apply=True, no_prompts=True) + assert waiter_names_snapshot.snapshot_id in plan.directly_modified + + # Trigger a metadata change to reuse the previous version + waiter_names_model = waiter_names_snapshot.model.copy( + update={"description": "Updated description"} + ) + context.upsert_model(waiter_names_model) + context.plan("dev", skip_tests=True, auto_apply=True, no_prompts=True) + + # Promote all changes to prod + waiter_names_snapshot = context.get_snapshot("sushi.waiter_names") + plan = context.plan_builder("prod", skip_tests=True).build() + # Clear the cache to source the dehydrated model instance from the state + context.clear_caches() + context.apply(plan) + + assert ( + context.engine_adapter.fetchone("SELECT COUNT(*) FROM sushi.waiter_names WHERE id = 10")[0] + == 1 + ) + + @time_machine.travel("2023-01-08 15:00:00 UTC") def test_plan_with_run( init_and_plan_context: t.Callable, From 2007cc0a9e1f1884df7bd0ebfb887a79796c3234 Mon Sep 17 00:00:00 2001 From: Iaroslav Zeigerman Date: Thu, 18 Sep 2025 20:23:20 -0700 Subject: [PATCH 2/2] Update tests/core/test_integration.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/core/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/test_integration.py b/tests/core/test_integration.py index 0f3ece812e..fdc3353dac 100644 --- a/tests/core/test_integration.py +++ b/tests/core/test_integration.py @@ -1698,7 +1698,7 @@ def test_seed_model_promote_to_prod_after_dev( # Promote all changes to prod waiter_names_snapshot = context.get_snapshot("sushi.waiter_names") plan = context.plan_builder("prod", skip_tests=True).build() - # Clear the cache to source the dehydrated model instance from the state + # Clear the cache to source the dehydrated model instance from the state context.clear_caches() context.apply(plan)