From a2b9af7be3738f6af522f93f98f6fa6bd0633220 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Sat, 20 May 2023 17:05:45 +0100 Subject: [PATCH] Do not exclude files that given as arguments If a file or folder is given as an argument to the linter, it will be treated as explicit and exclude rules will not apply to it. This will allow linting of files outside current project too. Fixes: #2628 --- examples/playbooks/deep/empty.yml | 4 ++++ src/ansiblelint/file_utils.py | 1 + src/ansiblelint/runner.py | 13 ++++++++++--- src/ansiblelint/schemas/__store__.json | 2 +- test/test_runner.py | 24 +++++++++++++++++++++--- 5 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 examples/playbooks/deep/empty.yml diff --git a/examples/playbooks/deep/empty.yml b/examples/playbooks/deep/empty.yml new file mode 100644 index 00000000000..722df737e29 --- /dev/null +++ b/examples/playbooks/deep/empty.yml @@ -0,0 +1,4 @@ +--- +- name: some playbook with incorrect name # <- should raise name[casing] + hosts: localhost + tasks: [] diff --git a/src/ansiblelint/file_utils.py b/src/ansiblelint/file_utils.py index 9ed93fda21a..1dd2ea97e36 100644 --- a/src/ansiblelint/file_utils.py +++ b/src/ansiblelint/file_utils.py @@ -197,6 +197,7 @@ def __init__( # noqa: C901 self.line_skips: dict[int, set[str]] = defaultdict(set) self.exc: Exception | None = None # Stores data loading exceptions self.parent = parent + self.explicit = False # Indicates if the file was explicitly provided or was indirectly included. if isinstance(name, str): name = Path(name) diff --git a/src/ansiblelint/runner.py b/src/ansiblelint/runner.py index 4a62c13163e..3412ff4ef9b 100644 --- a/src/ansiblelint/runner.py +++ b/src/ansiblelint/runner.py @@ -63,10 +63,12 @@ def __init__( if exclude_paths is None: exclude_paths = [] - # Assure consistent type + # Assure consistent type and configure given lintables as explicit (so + # excludes paths would not apply on them). for item in lintables: if not isinstance(item, Lintable): item = Lintable(item) + item.explicit = True self.lintables.add(item) # Expand folders (roles) to their components @@ -99,6 +101,11 @@ def is_excluded(self, lintable: Lintable) -> bool: # Exclusions should be evaluated only using absolute paths in order # to work correctly. + + # Explicit lintables are never excluded + if lintable.explicit: + return False + abs_path = str(lintable.abspath) if self.project_dir and not abs_path.startswith(self.project_dir): _logger.debug( @@ -193,7 +200,7 @@ def _run(self) -> list[MatchError]: # noqa: C901 matches.append( MatchError( lintable=lintable, - message="File or found not found.", + message="File or directory found not found.", rule=LoadingFailureRule(), tag="load-failure[not-found]", ), @@ -251,7 +258,7 @@ def worker(lintable: Lintable) -> list[MatchError]: # remove any matches made inside excluded files matches = list( filter( - lambda match: not self.is_excluded(Lintable(match.filename)) + lambda match: not self.is_excluded(match.lintable) and hasattr(match, "lintable") and match.tag not in match.lintable.line_skips[match.lineno], matches, diff --git a/src/ansiblelint/schemas/__store__.json b/src/ansiblelint/schemas/__store__.json index 453af0ed482..1ca0e19c467 100644 --- a/src/ansiblelint/schemas/__store__.json +++ b/src/ansiblelint/schemas/__store__.json @@ -1,6 +1,6 @@ { "ansible-lint-config": { - "etag": "0c180fc60da7bfbbf70d0ffa6dd4871aefce5e6f987f9c8073cb203dacd991b2", + "etag": "b5caa5405047dad89bb9fb419a17d8a67750f3a7ecdbabe16e0eb1897d316c5a", "url": "https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/ansible-lint-config.json" }, "ansible-navigator-config": { diff --git a/test/test_runner.py b/test/test_runner.py index 7b89f79867e..c2dfbf0e9d7 100644 --- a/test/test_runner.py +++ b/test/test_runner.py @@ -48,7 +48,7 @@ pytest.param( LOTS_OF_WARNINGS_PLAYBOOK, [LOTS_OF_WARNINGS_PLAYBOOK], - 0, + 992, id="lots_of_warnings", ), pytest.param(Path("examples/playbooks/become.yml"), [], 0, id="become"), @@ -77,9 +77,9 @@ def test_runner( def test_runner_exclude_paths(default_rules_collection: RulesCollection) -> None: """Test that exclude paths do work.""" runner = Runner( - "examples/playbooks/example.yml", + "examples/playbooks/deep/", rules=default_rules_collection, - exclude_paths=["examples/"], + exclude_paths=["examples/playbooks/deep/empty.yml"], ) matches = runner.run() @@ -190,3 +190,21 @@ def test_runner_not_found(default_rules_collection: RulesCollection) -> None: assert len(runner.checked_files) == 1 assert len(result) == 1 assert result[0].tag == "load-failure[not-found]" + + +def test_runner_tmp_file( + tmp_path: Path, + default_rules_collection: RulesCollection, +) -> None: + """Ensure we do not ignore an explicit temporary file from linting.""" + # https://github.com/ansible/ansible-lint/issues/2628 + filename = tmp_path / "playbook.yml" + filename.write_text("---\n") + runner = Runner( + filename, + rules=default_rules_collection, + verbosity=0, + ) + result = runner.run() + assert len(result) == 1 + assert result[0].tag == "syntax-check[empty-playbook]"