diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 75f9bc9b..b05de88d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,10 +23,10 @@ jobs: TOX_PARALLEL_NO_SPINNER: 1 steps: - - name: Switch to using Python 3.9 by default + - name: Switch to using Python 3.12 by default uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: "3.12" - name: Install tox run: python3 -m pip install --user "tox>=4.0.0" - name: Check out src from Git diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 07ddffe8..f56f2663 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -24,6 +24,7 @@ jobs: with: min_python: "3.9" max_python: "3.12" + default_python: "3.10" other_names: | lint docs @@ -32,7 +33,10 @@ jobs: py39-ansible213 py39-ansible214 py39-ansible215 - py311-devel + py310-ansible215 + py311-ansible215 + py312-ansible216 + py312-devel smoke platforms: linux,macos macos: minmax diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 645ea7d4..14f411dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,19 +9,20 @@ ci: for more information, see https://pre-commit.ci skip: # https://github.com/pre-commit-ci/issues/issues/55 + - ccv - pip-compile # No docker on pre-commit.ci - validate-config-in-container default_language_version: # Needed in order to make pip-compile output predictable. - python: python3.9 + python: python3.10 exclude: | (?x)^( test/assets/.* )$ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.291" + rev: "v0.1.9" hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] @@ -35,7 +36,7 @@ repos: - prettier-plugin-toml - prettier-plugin-sort-json - repo: https://github.com/pre-commit/pre-commit-hooks.git - rev: v4.4.0 + rev: v4.5.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace @@ -51,23 +52,23 @@ repos: - id: debug-statements language_version: python3 - repo: https://github.com/codespell-project/codespell - rev: v2.2.5 + rev: v2.2.6 hooks: - id: codespell - repo: https://github.com/adrienverge/yamllint.git - rev: v1.32.0 + rev: v1.33.0 hooks: - id: yamllint files: \.(yaml|yml)$ types: [file, yaml] entry: yamllint --strict - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 23.12.1 hooks: - id: black language_version: python3 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.8.0 hooks: - id: mypy # empty args needed in order to match mypy cli behavior @@ -84,7 +85,7 @@ repos: - types-pkg_resources - types-jsonschema>=4.4.9 - repo: https://github.com/pycqa/pylint - rev: v3.0.0b0 + rev: v3.0.3 hooks: - id: pylint additional_dependencies: @@ -117,4 +118,10 @@ repos: rev: v1.2.0 hooks: - id: validate-config-in-container + name: packit alias: packit + - repo: https://github.com/mashi/codecov-validator + rev: "1.0.1" + hooks: + - id: ccv + name: codecov diff --git a/.vscode/settings.json b/.vscode/settings.json index d9cc730e..990033df 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,9 +4,9 @@ }, "[python]": { "editor.codeActionsOnSave": { - "source.fixAll": true, - "source.fixAll.ruff": false, - "source.organizeImports": false + "source.fixAll": "explicit", + "source.fixAll.ruff": "never", + "source.organizeImports": "never" } }, "editor.formatOnSave": true, diff --git a/codecov.yml b/codecov.yml index 9eca5046..0ba95168 100644 --- a/codecov.yml +++ b/codecov.yml @@ -3,6 +3,4 @@ codecov: comment: false coverage: status: - patch: false - project: - threshold: 0.5% + patch: true # we want github annotations diff --git a/requirements.txt b/requirements.txt index 37e64478..6610cc5f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.9 +# This file is autogenerated by pip-compile with Python 3.10 # by the following command: # # pip-compile --extra=docs --extra=test --output-file=requirements.txt --strip-extras --unsafe-package=ansible-core --unsafe-package=resolvelib --unsafe-package=typing_extensions pyproject.toml @@ -68,7 +68,7 @@ defusedxml==0.7.1 # via # cairosvg # mkdocs-ansible -exceptiongroup==1.1.3 +exceptiongroup==1.2.0 # via pytest ghp-import==2.1.0 # via @@ -87,14 +87,7 @@ idna==3.4 # mkdocs-ansible # requests importlib-metadata==6.8.0 - # via - # build - # markdown - # mkdocs - # mkdocs-ansible - # mkdocstrings -importlib-resources==5.0.7 - # via ansible-core + # via mkdocs-ansible iniconfig==2.0.0 # via pytest jinja2==3.1.2 @@ -147,7 +140,9 @@ mkdocs==1.5.3 # mkdocs-monorepo-plugin # mkdocstrings mkdocs-ansible==0.2.0 - # via ansible-compat (pyproject.toml) + # via + # ansible-compat (pyproject.toml) + # mkdocs-ansible mkdocs-autorefs==0.5.0 # via # mkdocs-ansible @@ -300,12 +295,10 @@ tomli==2.0.1 # pip-tools # pyproject-hooks # pytest -typing-extensions==4.8.0 ; python_version < "3.10" +typing-extensions==4.8.0 # via - # ansible-compat (pyproject.toml) # black # mkdocs-ansible - # mkdocstrings urllib3==2.0.5 # via # mkdocs-ansible diff --git a/src/ansible_compat/runtime.py b/src/ansible_compat/runtime.py index e2cd5e97..a2b7f153 100644 --- a/src/ansible_compat/runtime.py +++ b/src/ansible_compat/runtime.py @@ -435,7 +435,7 @@ def install_collection( if isinstance(collection, Path): collection = str(collection) # As ansible-galaxy install is not able to automatically determine - # if the range requires a pre-release, we need to manuall add the --pre + # if the range requires a pre-release, we need to manually add the --pre # flag when needed. matches = version_re.search(collection) @@ -614,14 +614,14 @@ def prepare_environment( # noqa: C901 destination=destination, ) - if Path("galaxy.yml").exists(): + if (self.project_dir / "galaxy.yml").exists(): if destination: # while function can return None, that would not break the logic colpath = Path( - f"{destination}/ansible_collections/{colpath_from_path(Path.cwd())}", + f"{destination}/ansible_collections/{colpath_from_path(self.project_dir)}", ) if colpath.is_symlink(): - if os.path.realpath(colpath) == Path.cwd(): + if os.path.realpath(colpath) == str(Path.cwd()): _logger.warning( "Found symlinked collection, skipping its installation.", ) @@ -741,7 +741,7 @@ def _prepare_ansible_paths(self) -> None: msg = "Unexpected ansible configuration" raise RuntimeError(msg) from exc - alterations_list = [ + alterations_list: list[tuple[list[str], str, bool]] = [ (library_paths, "plugins/modules", True), (roles_path, "roles", True), ] @@ -762,7 +762,7 @@ def _prepare_ansible_paths(self) -> None: if must_be_present: continue path.mkdir(parents=True, exist_ok=True) - if path not in path_list: + if str(path) not in path_list: path_list.insert(0, str(path)) if library_paths != self.config.DEFAULT_MODULE_PATH: @@ -910,7 +910,10 @@ def _get_galaxy_role_ns(galaxy_infos: dict[str, Any]) -> str: def _get_galaxy_role_name(galaxy_infos: dict[str, Any]) -> str: """Compute role name from meta/main.yml.""" - return galaxy_infos.get("role_name", "") + result = galaxy_infos.get("role_name", "") + if not isinstance(result, str): + return "" + return result def search_galaxy_paths(search_dir: Path) -> list[str]: diff --git a/test/collections/acme.minimal/galaxy.yml b/test/collections/acme.minimal/galaxy.yml new file mode 100644 index 00000000..a15e4184 --- /dev/null +++ b/test/collections/acme.minimal/galaxy.yml @@ -0,0 +1,30 @@ +name: minimal +namespace: acme +version: 1.0.0 +readme: README.md +authors: + - Red Hat +description: Sample collection to use with molecule +build_ignore: + - "*.egg-info" + - .DS_Store + - .eggs + - .gitignore + - .mypy_cache + - .pytest_cache + - .stestr + - .stestr.conf + - .tox + - .vscode + - MANIFEST.in + - build + - dist + - doc + - report.html + - setup.cfg + - setup.py + - "tests/unit/*.*" + - README.rst + - tox.ini + +license_file: LICENSE diff --git a/test/test_runtime.py b/test/test_runtime.py index 7ee29af7..453a67c4 100644 --- a/test/test_runtime.py +++ b/test/test_runtime.py @@ -861,3 +861,24 @@ def test_galaxy_path(path: str, result: list[str]) -> None: def test_is_url(name: str, result: bool) -> None: """Checks functionality of is_url.""" assert is_url(name) == result + + +def test_prepare_environment_repair_broken_symlink( + caplog: pytest.LogCaptureFixture, +) -> None: + """Ensure we can deal with broken symlinks in collections.""" + caplog.set_level(logging.INFO) + project_dir = Path(__file__).parent / "collections" / "acme.minimal" + runtime = Runtime(isolated=True, project_dir=project_dir) + assert runtime.cache_dir + acme = runtime.cache_dir / "collections" / "ansible_collections" / "acme" + acme.mkdir(parents=True, exist_ok=True) + goodies = acme / "minimal" + rmtree(goodies, ignore_errors=True) + goodies.unlink(missing_ok=True) + goodies.symlink_to("/invalid/destination") + runtime.prepare_environment(install_local=True) + assert any( + msg.startswith("Collection is symlinked, but not pointing to") + for msg in caplog.messages + ) diff --git a/tox.ini b/tox.ini index e6c42071..8918b914 100644 --- a/tox.ini +++ b/tox.ini @@ -4,8 +4,22 @@ envlist = lint pkg docs - # matrix assumed current (implicit) is 2.13: - py{39,310,311}{,-devel,-ansible212,-ansible213,-ansible214,-ansible215} + py + py-devel + py39-ansible212 + py39-ansible213 + py39-ansible214 + py39-ansible215 + py310-ansible212 + py310-ansible213 + py310-ansible214 + py310-ansible215 + py311-ansible212 + py311-ansible213 + py311-ansible214 + py311-ansible215 + py312-ansible216 + isolated_build = true skip_missing_interpreters = True requires = @@ -14,18 +28,20 @@ requires = [testenv] description = - Run the tests with {basepython} + Run the tests devel: ansible devel branch ansible212: ansible-core 2.12 ansible213: ansible-core 2.13 ansible214: ansible-core 2.14 ansible215: ansible-core 2.15 + ansible216: ansible-core 2.16 deps = ansible212: ansible-core>=2.12,<2.13 ansible213: ansible-core>=2.13,<2.14 ansible214: ansible-core>=2.14,<2.15 ansible215: ansible-core>=2.15,<2.16 + ansible216: ansible-core>=2.16,<2.17 devel: ansible-core @ git+https://github.com/ansible/ansible.git@c5d18c39d81e2b3b10856b2fb76747230e4fac4a # GPLv3+ # avoid installing ansible-core on -devel envs: @@ -71,7 +87,7 @@ setenv = PIP_DISABLE_PIP_VERSION_CHECK = 1 PIP_CONSTRAINT = {toxinidir}/requirements.txt PRE_COMMIT_COLOR = always - PYTEST_REQPASS = 91 + PYTEST_REQPASS = 92 FORCE_COLOR = 1 allowlist_externals = ansible @@ -83,7 +99,7 @@ package = editable [testenv:lint] description = Run all linters # locked basepython is needed because to keep constrains.txt predictable -basepython = python3.9 +basepython = python3.10 deps = pre-commit>=2.6.0 skip_install = true