-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fix] Renaming or removing a contracted model raises a BreakingChange warning/error #10221
Conversation
Thank you for your pull request! We could not find a changelog entry for this change. For details on how to document a change, see the contributing guide. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #10221 +/- ##
==========================================
- Coverage 88.68% 88.67% -0.01%
==========================================
Files 180 180
Lines 22435 22476 +41
==========================================
+ Hits 19896 19931 +35
- Misses 2539 2545 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
core/dbt/graph/selector_methods.py
Outdated
@@ -719,7 +719,9 @@ def check_modified_contract( | |||
) -> Callable[[Optional[SelectorTarget], SelectorTarget], bool]: | |||
# get a function that compares two selector target based on compare method provided | |||
def check_modified_contract(old: Optional[SelectorTarget], new: SelectorTarget) -> bool: | |||
if hasattr(new, compare_method): | |||
if new is None and hasattr(old, compare_method + "_deleted"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't say I'm in love with this but it was the best way forward I could think of that:
- reuses the
state:modified.contract
user-facing method (configured here) to detect both changes that affect deleted + non-deleted changes. - keep the diff method localized to the node type instead of a more global search logic in the StateSelection method which felt like overloading what it did + deviating from the current pattern too much.
open to other suggestions!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's good to keep the diff method localized to the node type. It's kind of a bit hacky, but I can't think of a better way.
@@ -785,6 +787,16 @@ def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[Uniqu | |||
if checker(previous_node, node, **keyword_args): # type: ignore | |||
yield unique_id | |||
|
|||
# checkers that can handle deleted nodes | |||
if checker.__name__ in ["check_modified_contract"]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could look to implement a new state:modified.deleted
selector using this codepath in the future cc @jtcohen6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ m8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Is this something that applies to disabled nodes too, or is that handled somewhere else?
core/dbt/contracts/graph/nodes.py
Outdated
if self.contract.enforced is False: | ||
return True | ||
|
||
# Deleted node is passed its deprecation_date, so deletion does not constitute a contract change |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "past", not "passed"
core/dbt/graph/selector_methods.py
Outdated
@@ -719,7 +719,9 @@ def check_modified_contract( | |||
) -> Callable[[Optional[SelectorTarget], SelectorTarget], bool]: | |||
# get a function that compares two selector target based on compare method provided | |||
def check_modified_contract(old: Optional[SelectorTarget], new: SelectorTarget) -> bool: | |||
if hasattr(new, compare_method): | |||
if new is None and hasattr(old, compare_method + "_deleted"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's good to keep the diff method localized to the node type. It's kind of a bit hacky, but I can't think of a better way.
hmm, good question. I don't believe we should be raising breaking contract changes for disabled nodes that have been deleted/renamed but cc'ing @jtcohen6 to confirm. Either way it'd be good to add a test around that. |
@gshank @MichelleArk Good catch, thank you for thinking of this!
|
Thank you! That's a case worth handling in this PR. Updated the "same_contract_deleted" method to "same_contract_removed" and plumbed disabled nodes through the state method selection method and added testing. Should be good for another look @gshank 👍 |
Looks good! It's nice that adding disabled nodes was just a minor code change (and another test). |
resolves #10116
Problem
Deleting a contracted model does not warn or error regarding a breaking contract change
Solution
Checklist