diff --git a/.changes/unreleased/Under the Hood-20250110-202057.yaml b/.changes/unreleased/Under the Hood-20250110-202057.yaml new file mode 100644 index 00000000000..fdd9b0ec9ba --- /dev/null +++ b/.changes/unreleased/Under the Hood-20250110-202057.yaml @@ -0,0 +1,6 @@ +kind: Under the Hood +body: Fix error counts for exposures +time: 2025-01-10T20:20:57.01632Z +custom: + Author: aranke + Issue: ' ' diff --git a/core/dbt/task/printer.py b/core/dbt/task/printer.py index 01ccd75a586..42d4ed6d6cd 100644 --- a/core/dbt/task/printer.py +++ b/core/dbt/task/printer.py @@ -1,6 +1,7 @@ from typing import Dict, Optional, Union from dbt.artifacts.schemas.results import NodeStatus +from dbt.contracts.graph.nodes import Exposure from dbt.events.types import ( CheckNodeTestFailure, EndOfRunSummary, @@ -83,7 +84,9 @@ def print_run_result_error( node_info = None if hasattr(result, "node") and result.node: node_info = result.node.node_info - if result.status == NodeStatus.Fail or (is_warning and result.status == NodeStatus.Warn): + if result.status in (NodeStatus.Fail, NodeStatus.Error) or ( + is_warning and result.status == NodeStatus.Warn + ): if newline: fire_event(Formatting("")) if is_warning: @@ -115,11 +118,11 @@ def print_run_result_error( else: fire_event(RunResultErrorNoMessage(status=result.status, node_info=node_info)) - if result.node.compiled_path is not None: + if getattr(result.node, "compiled_path", None): fire_event(Formatting("")) fire_event(SQLCompiledPath(path=result.node.compiled_path, node_info=node_info)) - if result.node.should_store_failures: + if getattr(result.node, "should_store_failures", None): fire_event(Formatting("")) fire_event( CheckNodeTestFailure(relation_name=result.node.relation_name, node_info=node_info) @@ -139,10 +142,13 @@ def print_run_end_messages(results, keyboard_interrupt: bool = False) -> None: for r in results: if r.status in (NodeStatus.RuntimeErr, NodeStatus.Error, NodeStatus.Fail): errors.append(r) - elif r.status == NodeStatus.Skipped and r.message is not None: - # this means we skipped a node because of an issue upstream, - # so include it as an error - errors.append(r) + elif r.status == NodeStatus.Skipped and r.message: + if isinstance(r.node, Exposure): + # Don't include exposure skips in errors list + continue + else: + # This means we skipped a node because of an issue upstream, so include it as an error + errors.append(r) elif r.status == NodeStatus.Warn: warnings.append(r) elif r.status == NodeStatus.PartialSuccess: diff --git a/core/dbt/task/runnable.py b/core/dbt/task/runnable.py index 20dd2d7879d..76fc6ce044e 100644 --- a/core/dbt/task/runnable.py +++ b/core/dbt/task/runnable.py @@ -23,7 +23,7 @@ from dbt.cli.flags import Flags from dbt.config.runtime import RuntimeConfig from dbt.contracts.graph.manifest import Manifest -from dbt.contracts.graph.nodes import ResultNode +from dbt.contracts.graph.nodes import Exposure, ResultNode from dbt.contracts.state import PreviousState from dbt.events.types import ( ArtifactWritten, @@ -619,19 +619,19 @@ def interpret_results(cls, results): if results is None: return False - failures = [ - r - for r in results - if r.status - in ( - NodeStatus.RuntimeErr, - NodeStatus.Error, - NodeStatus.Fail, - NodeStatus.Skipped, # propogate error message causing skip - NodeStatus.PartialSuccess, # because partial success also means partial failure - ) - ] - return len(failures) == 0 + num_runtime_errors = len([r for r in results if r.status == NodeStatus.RuntimeErr]) + num_errors = len([r for r in results if r.status == NodeStatus.Error]) + num_fails = len([r for r in results if r.status == NodeStatus.Fail]) + num_skipped = len( + [ + r + for r in results + if r.status == NodeStatus.Skipped and not isinstance(r.node, Exposure) + ] + ) + num_partial_success = len([r for r in results if r.status == NodeStatus.PartialSuccess]) + num_total = num_runtime_errors + num_errors + num_fails + num_skipped + num_partial_success + return num_total == 0 def get_model_schemas(self, adapter, selected_uids: Iterable[str]) -> Set[BaseRelation]: if self.manifest is None: diff --git a/tests/unit/test_events.py b/tests/unit/test_events.py index 9e43faca0d7..764c6448aae 100644 --- a/tests/unit/test_events.py +++ b/tests/unit/test_events.py @@ -575,6 +575,9 @@ def test_single_run_error(): class MockNode: unique_id: str = "" node_info = None + resource_type: str = "model" + name: str = "my_model" + original_file_path: str = "path/to/model.sql" error_result = RunResult( status=RunStatus.Error,