Repository: fal-ai/dbt-fal

Issue:
Stop trying to run sources in dbt runner
<!-- *** Make sure you have searched for an existing bug report for this issue *** -->

**Describe the bug**
fal takes sources as valid nodes to run in dbt and tries to run them.
It mostly ends up in a no-op operation, but if the source shares name with a model it can run the wrong model.

**Expected behavior**
fal should not try to run sources in dbt.

**Screenshots**

![image](https://user-images.githubusercontent.com/2745502/181391848-7c2fc583-06be-44d9-8812-af867a7e3bc7.png)




Discussion:

Resolving patch:
diff --git a/src/fal/cli/selectors.py b/src/fal/cli/selectors.py
--- a/src/fal/cli/selectors.py
+++ b/src/fal/cli/selectors.py
@@ -44,24 +44,23 @@ def create_plan_from_graph(cls, parsed, nodeGraph: NodeGraph, fal_dbt: FalDbt):
         Creates and ExecutionPlan from the cli arguments
         """
         unique_ids = list(nodeGraph.graph.nodes.keys())
-        ids_to_execute = []
-
-        ids_to_exclude = []
 
+        ids_to_execute = unique_ids
         if parsed.select:
             ids_to_execute = _filter_node_ids(
                 unique_ids, fal_dbt, list(parsed.select), nodeGraph
             )
 
-        else:
-            ids_to_execute.extend(unique_ids)
-
+        ids_to_exclude = []
         if "exclude" in parsed and parsed.exclude:
             ids_to_exclude = _filter_node_ids(
                 unique_ids, fal_dbt, list(parsed.exclude), nodeGraph
             )
 
         ids_to_execute = [i for i in ids_to_execute if i not in ids_to_exclude]
+
+        # Remove non-model nodes (sources, maybe more?) by making sure they are in the node_lookup dict
+        ids_to_execute = [i for i in ids_to_execute if i in nodeGraph.node_lookup]
         return cls(list(set(ids_to_execute)), fal_dbt.project_name)
 
 


Test patch:
diff --git a/tests/graph/test_selectors.py b/tests/graph/test_selectors.py
--- a/tests/graph/test_selectors.py
+++ b/tests/graph/test_selectors.py
@@ -1,3 +1,4 @@
+from typing import Any, Dict
 from fal.cli.selectors import ExecutionPlan
 from fal.node_graph import NodeGraph
 import networkx as nx
@@ -131,7 +132,8 @@ def _after_script_for_model(model: str) -> str:
             modelm = _model(f"model{n}_{m}")
             digraph.add_edge(modeln, modelm)
 
-    graph = NodeGraph(digraph, {})
+    node_lookup: Dict[str, Any] = {node: None for node in digraph.nodes}
+    graph = NodeGraph(digraph, node_lookup)
 
     parsed = Namespace(select=["model0+70"])
 
@@ -224,8 +226,12 @@ def _create_test_graph():
     modelA = "model.test_project.modelA"
     modelB = "model.test_project.modelB"
 
+    sourceA = "source.test_project.results.some_source"
+
     graph = nx.DiGraph()
 
+    graph.add_node(sourceA)
+
     graph.add_node(scriptA)
     graph.add_node(scriptB)
     graph.add_node(scriptC)
@@ -233,9 +239,13 @@ def _create_test_graph():
     graph.add_node(modelA)
     graph.add_node(modelB)
 
+    graph.add_edge(sourceA, modelA)
     graph.add_edge(modelA, scriptA)
     graph.add_edge(modelA, scriptB)
     graph.add_edge(scriptC, modelA)
     graph.add_edge(scriptD, modelA)
 
-    return NodeGraph(graph, {})
+    node_lookup: Dict[str, Any] = {
+        node: None for node in graph.nodes if not node.startswith("source.")
+    }
+    return NodeGraph(graph, node_lookup)