Repository: dbt-labs/dbt-core

Issue:
[CT-2732] [Pre-regression] Selection Logic Does Not Account for Semantic Models
@Jstein77 has reported that invoking `dbt run` on the jaffle-shop project results in an error with the following stack trace.

```
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 86, in wrapper
    result, success = func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 71, in wrapper
    return func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 142, in wrapper
    return func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 168, in wrapper
    return func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 215, in wrapper
    return func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/requires.py", line 252, in wrapper
    return func(*args, **kwargs)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/cli/main.py", line 576, in run
    results = task.run()
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/task/runnable.py", line 433, in run
    self._runtime_initialize()
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/task/compile.py", line 140, in _runtime_initialize
    super()._runtime_initialize()
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/task/runnable.py", line 142, in _runtime_initialize
    self.job_queue = self.get_graph_queue()
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/task/runnable.py", line 133, in get_graph_queue
    selector = self.get_node_selector()
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/task/run.py", line 477, in get_node_selector
    return ResourceTypeSelector(
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/graph/selector.py", line 324, in __init__
    super().__init__(
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/graph/selector.py", line 54, in __init__
    graph_members = {
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/graph/selector.py", line 55, in <setcomp>
    unique_id for unique_id in self.full_graph.nodes() if self._is_graph_member(unique_id)
  File "/Users/jordanstein/Dev/jaffle-sl-template/venv/lib/python3.9/site-packages/dbt/graph/selector.py", line 171, in _is_graph_member
    node = self.manifest.nodes[unique_id]
KeyError: 'semanticmodel.jaffle_shop.raw_products_test'
```

The culprit appears to be a lack of special handling for semantic nodes in the _is_graph_member() function. We should add that special handling and evaluate the rest of the selection logic for other places where semantic models need to be taken into account.

### Expected Behavior

The jaffle shop project should run on dbt v1.6.0-b5.

### Steps To Reproduce

Run dbt v1.6.0-b5 on the jaffle shop project.



Discussion:
More editorially, this is a good example of the way a lack of abstraction makes it time consuming and error prone to add new types of nodes to dbt. Today, doing it correctly requires definitive knowledge of the entire code base.

Resolving patch:
diff --git a/core/dbt/graph/selector.py b/core/dbt/graph/selector.py
--- a/core/dbt/graph/selector.py
+++ b/core/dbt/graph/selector.py
@@ -168,6 +168,8 @@ def _is_graph_member(self, unique_id: UniqueId) -> bool:
         elif unique_id in self.manifest.metrics:
             metric = self.manifest.metrics[unique_id]
             return metric.config.enabled
+        elif unique_id in self.manifest.semantic_models:
+            return True
         node = self.manifest.nodes[unique_id]
 
         if self.include_empty_nodes:
@@ -191,6 +193,8 @@ def _is_match(self, unique_id: UniqueId) -> bool:
             node = self.manifest.exposures[unique_id]
         elif unique_id in self.manifest.metrics:
             node = self.manifest.metrics[unique_id]
+        elif unique_id in self.manifest.semantic_models:
+            node = self.manifest.semantic_models[unique_id]
         else:
             raise DbtInternalError(f"Node {unique_id} not found in the manifest!")
         return self.node_is_match(node)


Test patch: