From 3b89cd22bb9b868d68407122d7a6cd2ebd46cafb Mon Sep 17 00:00:00 2001 From: sivel / Matt Martz Date: Wed, 8 Apr 2026 12:22:45 -0500 Subject: [PATCH] [stable-2.20] ansible-test - generate dist_info. Fixes #86695 (#86768) (#86797) (cherry picked from commit bae4284) --- .gitignore | 2 ++ .../fragments/ansible-test-dist-info.yml | 2 ++ .../targets/ansible-test-metadata/aliases | 3 ++ .../targets/ansible-test-metadata/runme.sh | 9 +++++ .../ansible_test/_internal/ansible_util.py | 36 +++++++++++++++++-- .../commands/integration/__init__.py | 2 ++ 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/ansible-test-dist-info.yml create mode 100644 test/integration/targets/ansible-test-metadata/aliases create mode 100755 test/integration/targets/ansible-test-metadata/runme.sh diff --git a/.gitignore b/.gitignore index 6551222edd2..6617ac7aba5 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,8 @@ Vagrantfile /lib/ansible_core.egg-info/ # First used in the `devel` branch during Ansible 2.18 development. /ansible_core.egg-info/ +# First used in the `devel` branch during Ansible 2.21 development. +lib/ansible_core-*.dist-info/ # vendored lib dir lib/ansible/_vendor/* !lib/ansible/_vendor/__init__.py diff --git a/changelogs/fragments/ansible-test-dist-info.yml b/changelogs/fragments/ansible-test-dist-info.yml new file mode 100644 index 00000000000..98450658747 --- /dev/null +++ b/changelogs/fragments/ansible-test-dist-info.yml @@ -0,0 +1,2 @@ +minor_changes: +- ansible-test - Generate ``dist_info`` when running tests. diff --git a/test/integration/targets/ansible-test-metadata/aliases b/test/integration/targets/ansible-test-metadata/aliases new file mode 100644 index 00000000000..a8a0999d85a --- /dev/null +++ b/test/integration/targets/ansible-test-metadata/aliases @@ -0,0 +1,3 @@ +shippable/posix/group3 # runs in the distro test containers +shippable/generic/group1 # runs in the default test container +context/controller diff --git a/test/integration/targets/ansible-test-metadata/runme.sh b/test/integration/targets/ansible-test-metadata/runme.sh new file mode 100755 index 00000000000..0824d2364a0 --- /dev/null +++ b/test/integration/targets/ansible-test-metadata/runme.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Verify that importlib.metadata can find ansible-core using the PYTHONPATH set by ansible-test. +# Regression test for https://github.com/ansible/ansible/issues/86695 + +set -eux + +VERSION=$(python -c "from importlib.metadata import version; print(version('ansible-core'))") + +test "$VERSION" = "$ANSIBLE_TEST_ANSIBLE_VERSION" diff --git a/test/lib/ansible_test/_internal/ansible_util.py b/test/lib/ansible_test/_internal/ansible_util.py index 1c42ccae951..14b80902ed5 100644 --- a/test/lib/ansible_test/_internal/ansible_util.py +++ b/test/lib/ansible_test/_internal/ansible_util.py @@ -4,6 +4,7 @@ from __future__ import annotations import json import os +import pathlib import shutil import typing as t @@ -12,6 +13,10 @@ from .constants import ( SOFT_RLIMIT_NOFILE, ) +from .io import ( + write_text_file, +) + from .util import ( common_environment, ApplicationError, @@ -22,6 +27,7 @@ from .util import ( ANSIBLE_SOURCE_ROOT, ANSIBLE_TEST_TOOLS_ROOT, MODE_FILE_EXECUTE, + get_ansible_version, raw_command, verified_chmod, ) @@ -248,15 +254,12 @@ def get_cli_path(path: str) -> str: raise RuntimeError(path) -# noinspection PyUnusedLocal @mutex def get_ansible_python_path(args: CommonConfig) -> str: """ Return a directory usable for PYTHONPATH, containing only the ansible package. If a temporary directory is required, it will be cached for the lifetime of the process and cleaned up at exit. """ - del args # not currently used - try: return get_ansible_python_path.python_path # type: ignore[attr-defined] except AttributeError: @@ -273,11 +276,38 @@ def get_ansible_python_path(args: CommonConfig) -> str: os.symlink(ANSIBLE_LIB_ROOT, os.path.join(python_path, 'ansible')) + if not args.explain: + generate_dist_info(python_path) + get_ansible_python_path.python_path = python_path # type: ignore[attr-defined] return python_path +def generate_dist_info(path: str) -> None: + """Generate a dist-info in the specified base directory.""" + version = get_ansible_version() + metadata = f'''\ +Metadata-Version: 2.1 +Name: ansible-core +Version: {version} +''' + python_path = pathlib.Path(path) + + current_dist_info = python_path / f'ansible_core-{version}.dist-info' + + for dist_info in pathlib.Path(path).glob('ansible_core-*.dist-info'): + if dist_info == current_dist_info: + continue + shutil.rmtree(dist_info, ignore_errors=True) + + metadata_path = current_dist_info / 'METADATA' + if metadata_path.is_file(): + return + + write_text_file(str(metadata_path), metadata, create_directories=True) + + class CollectionDetail: """Collection detail.""" diff --git a/test/lib/ansible_test/_internal/commands/integration/__init__.py b/test/lib/ansible_test/_internal/commands/integration/__init__.py index 421c3d4a3d4..da02bec2a11 100644 --- a/test/lib/ansible_test/_internal/commands/integration/__init__.py +++ b/test/lib/ansible_test/_internal/commands/integration/__init__.py @@ -59,6 +59,7 @@ from ...io import ( from ...util import ( ApplicationError, display, + get_ansible_version, SubprocessError, remove_tree, ) @@ -804,6 +805,7 @@ def integration_environment( ANSIBLE_CALLBACKS_ENABLED=','.join(sorted(set(callback_plugins))), ANSIBLE_TEST_CI=args.metadata.ci_provider or get_ci_provider().code, ANSIBLE_TEST_COVERAGE='check' if args.coverage_check else ('yes' if args.coverage else ''), + ANSIBLE_TEST_ANSIBLE_VERSION=get_ansible_version(), OUTPUT_DIR=test_dir, INVENTORY_PATH=os.path.abspath(inventory_path), )