From a173a9a5d31cca96aeba32f3fd83062fe519bcc8 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Wed, 5 Apr 2023 18:28:26 -0400 Subject: [PATCH] Ensure that same_contract is called for state:modified --- .../unreleased/Fixes-20230405-182927.yaml | 6 ++ core/dbt/contracts/graph/nodes.py | 5 +- .../defer_state/test_modified_state.py | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Fixes-20230405-182927.yaml diff --git a/.changes/unreleased/Fixes-20230405-182927.yaml b/.changes/unreleased/Fixes-20230405-182927.yaml new file mode 100644 index 00000000000..b4e8aab6036 --- /dev/null +++ b/.changes/unreleased/Fixes-20230405-182927.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Ensure same_contract is called for state:modified +time: 2023-04-05T18:29:27.369084-04:00 +custom: + Author: gshank + Issue: "7282" diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index 89c7866a406..43e735579f0 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -430,13 +430,16 @@ def same_contents(self, old) -> bool: if old is None: return False + # Need to ensure that same_contract is called because it + # could throw an error + same_contract = self.same_contract(old) return ( self.same_body(old) and self.same_config(old) and self.same_persisted_description(old) and self.same_fqn(old) and self.same_database_representation(old) - and self.same_contract(old) + and same_contract and True ) diff --git a/tests/functional/defer_state/test_modified_state.py b/tests/functional/defer_state/test_modified_state.py index a0e3ec1580e..6a2038ed2a8 100644 --- a/tests/functional/defer_state/test_modified_state.py +++ b/tests/functional/defer_state/test_modified_state.py @@ -309,3 +309,62 @@ def test_changed_contract(self, project): write_file(schema_yml, "models", "schema.yml") with pytest.raises(ModelContractError): results = run_dbt(["run", "--models", "state:modified.contract", "--state", "./state"]) + + +my_model_sql = """ +select 1 as id +""" + +modified_my_model_sql = """ +-- a comment +select 1 as id +""" + +my_model_yml = """ +models: + - name: my_model + config: + contract: + enforced: true + columns: + - name: id + data_type: int +""" + +modified_my_model_yml = """ +models: + - name: my_model + config: + contract: + enforced: true + columns: + - name: id + data_type: string +""" + + +class TestModifiedBodyAndContract: + @pytest.fixture(scope="class") + def models(self): + return { + "my_model.sql": my_model_sql, + "my_model.yml": my_model_yml, + } + + def copy_state(self): + if not os.path.exists("state"): + os.makedirs("state") + shutil.copyfile("target/manifest.json", "state/manifest.json") + + def test_modified_body_and_contract(self, project): + results = run_dbt(["run"]) + assert len(results) == 1 + self.copy_state() + + # Change both body and contract + write_file(modified_my_model_yml, "models", "my_model.yml") + write_file(modified_my_model_sql, "models", "my_model.sql") + + # should raise even without specifying state:modified.contract + with pytest.raises(ModelContractError): + results = run_dbt(["run", "--models", "state:modified", "--state", "./state"])