fix: improve ignored_paths YAML guidance

Fixes #1561

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zerone0xandClaude authored and Dominik Jain committed 2026-07-17 17:10:31 +02:00
1 parent 22c135a881
commit bd9c4c9e89
4 files changed
+62 -1

No files matched your search

@@ -71,6 +71,13 @@ additional_workspace_folders: []
# list of additional paths to ignore in this project.
# Same syntax as gitignore, so you can use * and **.
# Important: quote patterns that start with `*`, otherwise YAML treats them as aliases.
# Example:
# ignored_paths:
# - "examples/**"
# - ".worktrees/**"
# - "**/bin/**"
# - "**/obj/**"
# Note: global ignored_paths from serena_config.yml are also applied additively.
ignored_paths: []
@@ -103,6 +103,7 @@ ls_specific_settings: {}
# list of paths to ignore across all projects.
# Same syntax as gitignore, so you can use * and **.
# These patterns are merged additively with each project's own ignored_paths.
# Quote patterns that start with `*`, e.g. `"**/bin/**"`.
ignored_paths: []
# list of regex patterns which, when matched, mark a memory entry as read‑only.
+11 -1
View File
@@ -68,7 +68,17 @@ def load_yaml(path: str, comment_normalisation: YamlCommentNormalisation = YamlC
"""
with open(path, encoding=SERENA_FILE_ENCODING) as f:
yaml = _create_yaml(preserve_comments=True)
commented_map: CommentedMap | None = yaml.load(f)
try:
commented_map: CommentedMap | None = yaml.load(f)
except Exception as e:
msg = str(e)
if "undefined alias" in msg:
raise ValueError(
f"Invalid YAML in {path}: values that start with `*` must be quoted. "
"This often happens in `ignored_paths` when using gitignore-style globs like "
'`"**/bin/**"` or `"**/obj/**"`.'
) from e
raise
if commented_map is None: # ruamel returns None for empty documents, but we want an empty CommentedMap
commented_map = CommentedMap()
normalise_yaml_comments(commented_map, comment_normalisation)
+43
View File
@@ -499,6 +499,25 @@ class TestProjectSerenaDataFolder:
assert project.path_to_serena_data_folder() == str(custom_serena)
class TestProjectConfigYamlValidation:
def test_ignored_paths_globs_starting_with_star_require_quotes(self):
project_dir = Path(tempfile.mkdtemp())
try:
serena_dir = project_dir / SERENA_MANAGED_DIR_NAME
serena_dir.mkdir(parents=True)
(serena_dir / "project.yml").write_text('project_name: "demo"\nlanguages: ["csharp"]\nignored_paths:\n- **/bin/**\n')
with pytest.raises(ValueError) as exc_info:
ProjectConfig.load(project_dir, create_default_serena_config())
msg = str(exc_info.value)
assert "values that start with `*` must be quoted" in msg
assert "ignored_paths" in msg
assert '"**/bin/**"' in msg
finally:
shutil.rmtree(project_dir)
class TestSerenaConfigFromConfigFileRobustness:
"""Tests that ``SerenaConfig.from_config_file`` does not abort the whole
loader when a single registered project has a broken ``project.yml``.
@@ -568,6 +587,30 @@ class TestSerenaConfigFromConfigFileRobustness:
f"Expected a warning naming {bad_project.resolve()}, got: {caplog.messages}"
)
def test_alias_like_ignored_path_error_is_logged_with_hint(self, caplog, monkeypatch):
good_project = self._make_project_dir(
"good_project",
'project_name: "good_project"\nlanguages: ["python"]\n',
)
bad_project = self._make_project_dir(
"bad_project",
'project_name: "bad_project"\nlanguages: ["csharp"]\nignored_paths:\n- **/bin/**\n',
)
self._write_master_config([good_project, bad_project])
monkeypatch.setattr(
SerenaConfig,
"_determine_config_file_path",
classmethod(lambda cls: str(self.master_config_path)),
)
with caplog.at_level(logging.ERROR):
config = SerenaConfig.from_config_file(generate_if_missing=False)
registered_roots = {Path(p.project_root).resolve() for p in config.projects}
assert registered_roots == {good_project.resolve()}
assert any("must be quoted" in msg and str(bad_project.resolve()) in msg for msg in caplog.messages), caplog.messages
class TestMemoriesManagerCustomPath:
"""Tests for MemoriesManager with a custom serena data folder."""