Skip to content

Commit da2d53d

Browse files
committed
Improve results with broken multiline playbooks
- Reduce the logged exceptions caused by invalid data - Reduce number of errors cased by the same root cause Fixes: #4492
1 parent d427f59 commit da2d53d

File tree

9 files changed

+26
-21
lines changed

9 files changed

+26
-21
lines changed

.github/workflows/tox.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ jobs:
134134
- name: Install tox
135135
run: |
136136
python3 -m pip install --upgrade pip
137-
python3 -m pip install --upgrade "tox>=4.0.0" "tox-uv>=1.16.0" uv
137+
python3 -m pip install --upgrade "tox>=4.0.0" "tox-uv>=1.20.2" uv
138138
139139
- name: Log installed dists
140140
run: python3 -m pip freeze --all

src/ansiblelint/__main__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,9 @@ def main(argv: list[str] | None = None) -> int:
280280
if argv is None: # pragma: no cover
281281
argv = sys.argv
282282

283+
warnings.simplefilter(
284+
"ignore", ResourceWarning
285+
) # suppress "enable tracemalloc to get the object allocation traceback"
283286
with warnings.catch_warnings(record=True) as warns:
284287
# do not use "ignore" as we will miss to collect them
285288
warnings.simplefilter(action="default")

src/ansiblelint/file_utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ def is_owned_by_ansible(self) -> bool:
407407
def failed(self) -> bool:
408408
"""Return true if we already found syntax-check errors on this file."""
409409
return any(
410-
match.rule.id in ("syntax-check", "load-failure") for match in self.matches
410+
match.rule.id in ("syntax-check", "load-failure", "internal-error")
411+
for match in self.matches
411412
)
412413

413414
@property

src/ansiblelint/rules/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
241241
yaml = [yaml]
242242

243243
for play in yaml:
244-
# Bug #849
245-
if play is None:
244+
# Bug #849 and #4492
245+
if play is None or not hasattr(play, "get"):
246246
continue
247247

248248
if self.id in play.get(SKIPPED_RULES_KEY, ()):

src/ansiblelint/runner.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,12 @@ def worker(lintable: Lintable) -> list[MatchError]:
270270
# do our processing only when ansible syntax check passed in order
271271
# to avoid causing runtime exceptions. Our processing is not as
272272
# resilient to be able process garbage.
273-
matches.extend(self._emit_matches(files))
273+
matches.extend(
274+
self._emit_matches([file for file in files if not file.failed()])
275+
)
274276

275277
# remove duplicates from files list
276-
files = [value for n, value in enumerate(files) if value not in files[:n]]
278+
files = list(dict.fromkeys(files))
277279

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

297299
return sorted(set(matches))
298300

299-
# pylint: disable=too-many-locals
301+
# pylint: disable=too-many-locals,too-many-statements
300302
def _get_ansible_syntax_check_matches(
301303
self,
302304
lintable: Lintable,
@@ -433,6 +435,7 @@ def _get_ansible_syntax_check_matches(
433435
f"Unexpected error code {run.returncode} from "
434436
f"execution of: {' '.join(cmd)}"
435437
)
438+
filename.failed()
436439
results.append(
437440
MatchError(
438441
message=message,
@@ -462,6 +465,8 @@ def _emit_matches(self, files: list[Lintable]) -> Generator[MatchError, None, No
462465
while visited != self.lintables:
463466
for lintable in self.lintables - visited:
464467
visited.add(lintable)
468+
if lintable.failed():
469+
continue
465470
if not lintable.path.exists():
466471
continue
467472
try:
@@ -499,9 +504,12 @@ def find_children(self, lintable: Lintable) -> list[Lintable]:
499504
try:
500505
playbook_ds = ansiblelint.utils.parse_yaml_from_file(str(lintable.path))
501506
except AnsibleError as exc:
502-
msg = f"Loading {lintable.filename} caused an {type(exc).__name__} exception: {exc}, file was ignored."
503-
_logger.exception(msg)
504-
return []
507+
raise MatchError(
508+
lintable=lintable, rule=self.rules["load-failure"]
509+
) from exc
510+
# msg = f"Loading {lintable.filename} caused an {type(exc).__name__} exception: {exc}, file was ignored."
511+
# _logger.exception(msg)
512+
# return []
505513
results = []
506514
# playbook_ds can be an AnsibleUnicode string, which we consider invalid
507515
if isinstance(playbook_ds, str):

src/ansiblelint/skip_utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,8 @@ def is_nested_task(task: dict[str, Any]) -> bool:
316316
# Cannot really trust the input
317317
if isinstance(task, str):
318318
return False
319+
# https://github.com/ansible/ansible-lint/issues/4492
320+
if not hasattr(task, "get"):
321+
return False
319322

320323
return any(task.get(key) for key in NESTED_TASK_KEYS)

test/rules/test_syntax_check.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727
pytest.param(
2828
"examples/playbooks/conflicting_action2.yml",
2929
[
30-
(
31-
"parser-error",
32-
1,
33-
None,
34-
"conflicting action statements: block, include_role",
35-
),
3630
(
3731
"syntax-check[specific]",
3832
5,

test/test_import_tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
4,
1616
id="0",
1717
),
18-
pytest.param("examples/playbooks/test_import_with_malformed.yml", 2, 2, id="1"),
18+
pytest.param("examples/playbooks/test_import_with_malformed.yml", 1, 1, id="1"),
1919
),
2020
)
2121
def test_import_tasks(

tox.ini

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,6 @@ package = editable
9898

9999
[testenv:lint]
100100
description = Run all linters
101-
# pip compile includes python version in output constraints, so we want to
102-
# be sure that version does not change randomly.
103-
basepython = python3.10
104101
deps =
105102
pre-commit>=4.0.1
106103
pre-commit-uv>=4.1.4
@@ -128,7 +125,6 @@ description = Bump all test dependencies
128125
# we reuse the lint environment
129126
envdir = {toxworkdir}/lint
130127
skip_install = true
131-
basepython = python3.10
132128
deps =
133129
{[testenv:lint]deps}
134130
commands_pre =

0 commit comments

Comments
 (0)