diff --git a/.config/constraints.txt b/.config/constraints.txt index 2deb5254f5..e35dbaa4a1 100644 --- a/.config/constraints.txt +++ b/.config/constraints.txt @@ -4,7 +4,7 @@ # # pip-compile --all-extras --no-annotate --output-file=.config/constraints.txt --strip-extras --unsafe-package=resolvelib --unsafe-package=ruamel-yaml-clib --unsafe-package=wcmatch pyproject.toml # -ansible-compat==4.1.11 +ansible-compat==24.5.1a0 ansible-core==2.16.6 astroid==3.1.0 attrs==23.2.0 diff --git a/.config/dictionary.txt b/.config/dictionary.txt index 50554be4da..27c781904c 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -1,6 +1,5 @@ Adrián Autobuild -audgirka CLICOLOR CODENOTIFY CODEOWNERS @@ -45,6 +44,7 @@ apport argparsing argspecs arxcruz +audgirka auditd autobuild autoclass @@ -379,6 +379,7 @@ tmpfs toctree toidentifier tomli +tomlsort toolset tripleo tuco diff --git a/.config/requirements-lock.txt b/.config/requirements-lock.txt index 5cf5568c00..0bbab0c0fe 100644 --- a/.config/requirements-lock.txt +++ b/.config/requirements-lock.txt @@ -4,7 +4,7 @@ # # pip-compile --no-annotate --output-file=.config/requirements-lock.txt --strip-extras --unsafe-package=resolvelib --unsafe-package=ruamel-yaml-clib pyproject.toml # -ansible-compat==4.1.11 +ansible-compat==24.5.1a0 ansible-core==2.16.6 attrs==23.2.0 black==24.4.2 diff --git a/.config/requirements.in b/.config/requirements.in index 7851701de6..ba146de7df 100644 --- a/.config/requirements.in +++ b/.config/requirements.in @@ -1,7 +1,7 @@ # Special order section for helping pip: will-not-work-on-windows-try-from-wsl-instead; platform_system=='Windows' ansible-core>=2.13.0 # GPLv3 -ansible-compat>=4.1.11 # GPLv3 +ansible-compat>=24.5.0dev0 # GPLv3 # alphabetically sorted: black>=24.3.0 # MIT (security) filelock>=3.3.0 # The Unlicense diff --git a/.github/lower-constraints.txt b/.github/lower-constraints.txt index 6b6576020a..adcc82ec53 100644 --- a/.github/lower-constraints.txt +++ b/.github/lower-constraints.txt @@ -2,7 +2,7 @@ # automatically updated by dependabot. This should be kept in sync with # minimal requirements configured inside .config/requirements.in ansible-core==2.13.0 -ansible-compat==4.1.11 # GPLv3 +ansible-compat==24.5.1a0 # GPLv3 black==24.3.0 # MIT (security) filelock==3.3.0 # The Unlicense jsonschema==4.10.0 # MIT, version needed for improved errors diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index e9c0f79b23..47d821bb5c 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -73,7 +73,7 @@ jobs: env: # Number of expected test passes, safety measure for accidental skip of # tests. Update value if you add/remove tests. - PYTEST_REQPASS: 858 + PYTEST_REQPASS: 859 steps: - uses: actions/checkout@v4 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bb86d5cd33..43a827febf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -153,7 +153,7 @@ repos: # empty args needed in order to match mypy cli behavior args: [--strict] additional_dependencies: - - ansible-compat>=4.1.11 + - ansible-compat>=24.5.1a0 - black>=22.10.0 - cryptography>=39.0.1 - filelock>=3.12.2 @@ -182,7 +182,7 @@ repos: args: - --output-format=colorized additional_dependencies: - - ansible-compat>=4.1.11 + - ansible-compat>=24.5.1a0 - ansible-core>=2.14.0 - black>=22.10.0 - docutils diff --git a/examples/.test_collection/.ansible-lint b/examples/.test_collection/.ansible-lint new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/examples/.test_collection/.ansible-lint @@ -0,0 +1 @@ +{} diff --git a/examples/playbooks/test_import_playbook.yml b/examples/playbooks/test_import_playbook.yml new file mode 100644 index 0000000000..690950aa23 --- /dev/null +++ b/examples/playbooks/test_import_playbook.yml @@ -0,0 +1,5 @@ +--- +- name: Fixture 1 for bug 4024 + import_playbook: community.molecule.validate.yml +- name: Fixture 2 for bug 4024 + ansible.builtin.import_playbook: community.molecule.validate.yml diff --git a/src/ansiblelint/runner.py b/src/ansiblelint/runner.py index b977d8b7dd..efe6e8e1a8 100644 --- a/src/ansiblelint/runner.py +++ b/src/ansiblelint/runner.py @@ -106,6 +106,8 @@ def __init__( checked_files = set() self.checked_files = checked_files + self.app = get_app(cached=True) + def _update_exclude_paths(self, exclude_paths: list[str]) -> None: if exclude_paths: # These will be (potentially) relative paths @@ -232,12 +234,12 @@ def _run(self) -> list[MatchError]: # -- phase 1 : syntax check in parallel -- if not self.skip_ansible_syntax_check: - app = get_app(cached=True) + # app = get_app(cached=True) def worker(lintable: Lintable) -> list[MatchError]: return self._get_ansible_syntax_check_matches( lintable=lintable, - app=app, + app=self.app, ) for lintable in self.lintables: @@ -518,7 +520,6 @@ def find_children(self, lintable: Lintable) -> list[Lintable]: if path != path_str: child.path = Path(path) child.name = child.path.name - results.append(child) return results @@ -532,7 +533,7 @@ def play_children( """Flatten the traversed play tasks.""" # pylint: disable=unused-argument - handlers = HandleChildren(self.rules) + handlers = HandleChildren(self.rules, app=self.app) delegate_map: dict[ str, diff --git a/src/ansiblelint/utils.py b/src/ansiblelint/utils.py index 6968ce47de..12700e272d 100644 --- a/src/ansiblelint/utils.py +++ b/src/ansiblelint/utils.py @@ -59,7 +59,7 @@ AnsibleParserErrorRule, RuntimeErrorRule, ) -from ansiblelint.app import get_app +from ansiblelint.app import App, get_app from ansiblelint.config import Options, options from ansiblelint.constants import ( ANNOTATION_KEYS, @@ -290,6 +290,7 @@ class HandleChildren: """Parse task, roles and children.""" rules: RulesCollection = field(init=True, repr=False) + app: App def include_children( self, @@ -307,9 +308,14 @@ def include_children( if not v or "{{" in v: return [] - if "import_playbook" in k and COLLECTION_PLAY_RE.match(v): - # Any import_playbooks from collections should be ignored as ansible - # own syntax check will handle them. + if k in ("import_playbook", "ansible.builtin.import_playbook"): + included = Path(basedir) / v + if self.app.runtime.has_playbook(v, basedir=Path(basedir)): + if included.exists(): + return [Lintable(included, kind=parent_type)] + return [] + msg = f"Failed to find {v} playbook." + logging.error(msg) return [] # handle include: filename.yml tags=blah diff --git a/test/test_import_playbook.py b/test/test_import_playbook.py index f695581e89..27ef4541b1 100644 --- a/test/test_import_playbook.py +++ b/test/test_import_playbook.py @@ -17,3 +17,15 @@ def test_task_hook_import_playbook(default_rules_collection: RulesCollection) -> assert "Commands should not change things" in results_text assert "[name]" in results_text assert "All tasks should be named" in results_text + + +def test_import_playbook_from_collection( + default_rules_collection: RulesCollection, +) -> None: + """Assures import_playbook from collection.""" + playbook_path = "examples/playbooks/test_import_playbook.yml" + runner = Runner(playbook_path, rules=default_rules_collection) + results = runner.run() + + assert len(runner.lintables) == 1 + assert len(results) == 0