Skip to content

Commit

Permalink
Improve output with broken multiline playbooks (#4506)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssbarnea authored Feb 3, 2025
1 parent 5314965 commit 0811894
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 16 deletions.
3 changes: 3 additions & 0 deletions src/ansiblelint/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ def main(argv: list[str] | None = None) -> int:
if argv is None: # pragma: no cover
argv = sys.argv

warnings.simplefilter(
"ignore", ResourceWarning
) # suppress "enable tracemalloc to get the object allocation traceback"
with warnings.catch_warnings(record=True) as warns:
# do not use "ignore" as we will miss to collect them
warnings.simplefilter(action="default")
Expand Down
3 changes: 2 additions & 1 deletion src/ansiblelint/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,8 @@ def is_owned_by_ansible(self) -> bool:
def failed(self) -> bool:
"""Return true if we already found syntax-check errors on this file."""
return any(
match.rule.id in ("syntax-check", "load-failure") for match in self.matches
match.rule.id in ("syntax-check", "load-failure", "internal-error")
for match in self.matches
)

@property
Expand Down
4 changes: 2 additions & 2 deletions src/ansiblelint/rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
yaml = [yaml]

for play in yaml:
# Bug #849
if play is None:
# Bug #849 and #4492
if play is None or not hasattr(play, "get"):
continue

if self.id in play.get(SKIPPED_RULES_KEY, ()):
Expand Down
17 changes: 11 additions & 6 deletions src/ansiblelint/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,12 @@ def worker(lintable: Lintable) -> list[MatchError]:
# do our processing only when ansible syntax check passed in order
# to avoid causing runtime exceptions. Our processing is not as
# resilient to be able process garbage.
matches.extend(self._emit_matches(files))
matches.extend(
self._emit_matches([file for file in files if not file.failed()])
)

# remove duplicates from files list
files = [value for n, value in enumerate(files) if value not in files[:n]]
files = list(dict.fromkeys(files))

for file in self.lintables:
if file in self.checked_files or not file.kind or file.failed():
Expand All @@ -296,7 +298,7 @@ def worker(lintable: Lintable) -> list[MatchError]:

return sorted(set(matches))

# pylint: disable=too-many-locals
# pylint: disable=too-many-locals,too-many-statements
def _get_ansible_syntax_check_matches(
self,
lintable: Lintable,
Expand Down Expand Up @@ -432,6 +434,7 @@ def _get_ansible_syntax_check_matches(
f"Unexpected error code {run.returncode} from "
f"execution of: {' '.join(cmd)}"
)
filename.failed()
results.append(
MatchError(
message=message,
Expand Down Expand Up @@ -461,6 +464,8 @@ def _emit_matches(self, files: list[Lintable]) -> Generator[MatchError, None, No
while visited != self.lintables:
for lintable in self.lintables - visited:
visited.add(lintable)
if lintable.failed():
continue
if not lintable.path.exists():
continue
try:
Expand Down Expand Up @@ -498,9 +503,9 @@ def find_children(self, lintable: Lintable) -> list[Lintable]:
try:
playbook_ds = ansiblelint.utils.parse_yaml_from_file(str(lintable.path))
except AnsibleError as exc:
msg = f"Loading {lintable.filename} caused an {type(exc).__name__} exception: {exc}, file was ignored."
_logger.exception(msg)
return []
raise MatchError(
lintable=lintable, rule=self.rules["load-failure"]
) from exc
results = []
# playbook_ds can be an AnsibleUnicode string, which we consider invalid
if isinstance(playbook_ds, str):
Expand Down
3 changes: 3 additions & 0 deletions src/ansiblelint/skip_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,8 @@ def is_nested_task(task: dict[str, Any]) -> bool:
# Cannot really trust the input
if isinstance(task, str):
return False
# https://github.com/ansible/ansible-lint/issues/4492
if not hasattr(task, "get"):
return False

return any(task.get(key) for key in NESTED_TASK_KEYS)
6 changes: 0 additions & 6 deletions test/rules/test_syntax_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@
pytest.param(
"examples/playbooks/conflicting_action2.yml",
[
(
"parser-error",
1,
None,
"conflicting action statements: block, include_role",
),
(
"syntax-check[specific]",
5,
Expand Down
2 changes: 1 addition & 1 deletion test/test_import_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
4,
id="0",
),
pytest.param("examples/playbooks/test_import_with_malformed.yml", 2, 2, id="1"),
pytest.param("examples/playbooks/test_import_with_malformed.yml", 1, 1, id="1"),
),
)
def test_import_tasks(
Expand Down

0 comments on commit 0811894

Please sign in to comment.