Skip to content

Commit 8e83781

Browse files
committed
fix(ci): install [codebase] extra + skip tree-sitter tests without it
CI failure on 197155e+dc129b9: regex fallback path in codebase_parser.parse_file produces basename-only symbol names ("bar" not "Foo.bar") because tree-sitter isn't installed in CI. The L6-ring feature legitimately requires tree-sitter; the fallback is graceful but cannot emit caller-qualified chains. Two-part fix: 1. .github/workflows/ci.yml — install `.[dev,postgresql,codebase]` so CI actually exercises the feature with tree-sitter. 2. tests_py/infrastructure/test_workflow_graph_source_native_ast.py — mark every test that depends on dotted qnames / MEMBER_OF / CALLS with @requires_tree_sitter (`pytest.mark.skipif` on ast_parser.is_available()). Local-dev configs without the [codebase] extra now skip cleanly instead of asserting on unachievable shapes. Tests that don't require tree-sitter (empty list, non-source skip, file cap, unresolved-import dropped) stay unmarked and continue to run in both configs. Local: 16 tests pass as before. CI should now pass the codebase-extra-backed tests and skip nothing.
1 parent dc129b9 commit 8e83781

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767
key: ${{ runner.os }}-hf-all-MiniLM-L6-v2
6868

6969
- name: Install dependencies
70-
run: pip install -e ".[dev,postgresql]"
70+
run: pip install -e ".[dev,postgresql,codebase]"
7171

7272
- name: Pre-download embedding model
7373
run: python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2', device='cpu')"

tests_py/infrastructure/test_workflow_graph_source_native_ast.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,23 @@
1212

1313
import pytest
1414

15+
from mcp_server.core.ast_parser import is_available as _ast_available
1516
from mcp_server.infrastructure.workflow_graph_source_native_ast import (
1617
WorkflowGraphNativeASTSource,
1718
)
1819

20+
# Tree-sitter is an optional extra (``pip install -e ".[codebase]"``).
21+
# Without it, ``parse_file_ast`` falls back to the regex path in
22+
# ``codebase_parser.parse_file``, which produces basename-only symbol
23+
# names (e.g. ``"bar"``) and does not populate ``calls_per_function``.
24+
# The feature this module tests — dotted qnames, MEMBER_OF, and CALLS
25+
# chains — requires tree-sitter. Skip cleanly when it isn't installed
26+
# so CI configs that omit the [codebase] extra don't fail spuriously.
27+
requires_tree_sitter = pytest.mark.skipif(
28+
not _ast_available(),
29+
reason="tree-sitter not installed — install the [codebase] extra",
30+
)
31+
1932

2033
@pytest.fixture
2134
def source() -> WorkflowGraphNativeASTSource:
@@ -44,6 +57,7 @@ def test_empty_file_list_returns_empty(self, source):
4457
def test_unreadable_paths_are_skipped(self, source):
4558
assert source.load_symbols(["/no/such/file.py"]) == []
4659

60+
@requires_tree_sitter
4761
def test_python_class_and_method_emit_symbol_rows(self, tmp_path, source):
4862
path = _write(
4963
tmp_path,
@@ -77,6 +91,7 @@ def test_non_source_files_skipped(self, tmp_path, source):
7791

7892

7993
class TestLoadASTEdges:
94+
@requires_tree_sitter
8095
def test_member_of_emitted_for_method(self, tmp_path, source):
8196
path = _write(
8297
tmp_path,
@@ -96,6 +111,7 @@ def test_member_of_emitted_for_method(self, tmp_path, source):
96111
assert e["confidence"] == 1.0
97112
assert "native-ast" in e["reason"]
98113

114+
@requires_tree_sitter
99115
def test_imports_resolve_to_sibling_symbol(self, tmp_path, source):
100116
_write(
101117
tmp_path,
@@ -137,8 +153,10 @@ def test_empty_file_list_returns_empty(self, source):
137153
class TestCallEdges:
138154
"""Caller-qualified CALLS: ``src_name`` is the enclosing method's
139155
qualified name, so the L6 ring can render the full method-to-method
140-
chain inside and across files."""
156+
chain inside and across files. All tests here require tree-sitter
157+
(the regex fallback cannot produce caller-qualified names)."""
141158

159+
@requires_tree_sitter
142160
def test_intra_file_method_to_method_call(self, tmp_path, source):
143161
path = _write(
144162
tmp_path,
@@ -168,6 +186,7 @@ def test_intra_file_method_to_method_call(self, tmp_path, source):
168186
assert e["confidence"] == 1.0
169187
assert "native-ast:call" in e["reason"]
170188

189+
@requires_tree_sitter
171190
def test_cross_file_call_resolved(self, tmp_path, source):
172191
_write(
173192
tmp_path,
@@ -208,6 +227,7 @@ def test_unresolved_callee_dropped(self, tmp_path, source):
208227
# "os", "path", "join" are all unknown — no edges emitted.
209228
assert not calls, f"expected no call edges, got {calls}"
210229

230+
@requires_tree_sitter
211231
def test_dedup_within_caller(self, tmp_path, source):
212232
"""A caller that invokes the same callee N times yields one edge."""
213233
path = _write(
@@ -240,6 +260,7 @@ class TestEndToEndContract:
240260
``symbol_id`` and returns early at the ``dst_id not in b._nodes``
241261
guard."""
242262

263+
@requires_tree_sitter
243264
def test_calls_edge_lands_in_builder_output(self, tmp_path, source):
244265
from mcp_server.core.workflow_graph_builder import (
245266
WorkflowGraphBuilder,
@@ -293,6 +314,7 @@ def test_calls_edge_lands_in_builder_output(self, tmp_path, source):
293314
)
294315
assert len(calls) == 1
295316

317+
@requires_tree_sitter
296318
def test_cross_file_calls_edge_lands(self, tmp_path, source):
297319
from mcp_server.core.workflow_graph_builder import (
298320
WorkflowGraphBuilder,

0 commit comments

Comments
 (0)