Skip to content

Commit

Permalink
Improve requirements.yml detection (#275)
Browse files Browse the repository at this point in the history
Gives explicit error message about invalid requirements.yml files,
especially as an unsupported format was used during the 2020 split.

Closes: #274
Related: ansible-community/community-topics#230
  • Loading branch information
ssbarnea authored May 21, 2023
1 parent 18aae33 commit 34c1459
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
4 changes: 4 additions & 0 deletions examples/reqs_broken/requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
roles: []
collections: []
integration_tests_dependencies: [] # <-- invalid key
unit_tests_dependencies: [] # <-- invalid key
10 changes: 10 additions & 0 deletions src/ansible_compat/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
"""Constants used by ansible_compat."""


REQUIREMENT_LOCATIONS = [
"requirements.yml",
"roles/requirements.yml",
"collections/requirements.yml",
# These is more of less the official way to store test requirements in collections so far, comments shows number of repos using this reported by https://sourcegraph.com/ at the time of writing
"tests/requirements.yml", # 170
"tests/integration/requirements.yml", # 3
"tests/unit/requirements.yml", # 1
]

# Minimal version of Ansible we support for runtime
ANSIBLE_MIN_VERSION = "2.12"

Expand Down
20 changes: 12 additions & 8 deletions src/ansible_compat/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
ansible_collections_path,
parse_ansible_version,
)
from ansible_compat.constants import MSG_INVALID_FQRL, RC_ANSIBLE_OPTIONS_ERROR
from ansible_compat.constants import (
MSG_INVALID_FQRL,
RC_ANSIBLE_OPTIONS_ERROR,
REQUIREMENT_LOCATIONS,
)
from ansible_compat.errors import (
AnsibleCommandError,
AnsibleCompatError,
Expand Down Expand Up @@ -411,6 +415,12 @@ def install_requirements( # noqa: C901
msg = f"{requirement} file is not a valid Ansible requirements file."
raise InvalidPrerequisiteError(msg)

if isinstance(reqs_yaml, dict):
for key in reqs_yaml:
if key not in ("roles", "collections"):
msg = f"{requirement} file is not a valid Ansible requirements file. Only 'roles' and 'collections' keys are allowed at root level. Recognized valid locations are: {', '.join(REQUIREMENT_LOCATIONS)}"
raise InvalidPrerequisiteError(msg)

if isinstance(reqs_yaml, list) or "roles" in reqs_yaml:
cmd = [
"ansible-galaxy",
Expand Down Expand Up @@ -485,13 +495,7 @@ def prepare_environment( # noqa: C901
# are part of Tower specification
# https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#ansible-galaxy-support
# https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#collections-support
for req_file in [
"requirements.yml",
"roles/requirements.yml",
"collections/requirements.yml",
# These is more of less the official way to store test requirements in collections so far:
"tests/requirements.yml",
]:
for req_file in REQUIREMENT_LOCATIONS:
self.install_requirements(Path(req_file), retry=retry, offline=offline)

galaxy_path = Path("galaxy.yml")
Expand Down
7 changes: 7 additions & 0 deletions test/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ def test_prerun_reqs_v2(caplog: pytest.LogCaptureFixture, runtime: Runtime) -> N
)


def test_prerun_reqs_broken(runtime: Runtime) -> None:
"""Checks that the we report invalid requirements.yml file."""
path = (Path(__file__).parent.parent / "examples" / "reqs_broken").resolve()
with cwd(path), pytest.raises(InvalidPrerequisiteError):
runtime.prepare_environment()


def test__update_env_no_old_value_no_default_no_value(monkeypatch: MonkeyPatch) -> None:
"""Make sure empty value does not touch environment."""
monkeypatch.delenv("DUMMY_VAR", raising=False)
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ setenv =
PIP_DISABLE_PIP_VERSION_CHECK = 1
PIP_CONSTRAINT = {toxinidir}/requirements.txt
PRE_COMMIT_COLOR = always
PYTEST_REQPASS = 80
PYTEST_REQPASS = 81
FORCE_COLOR = 1
allowlist_externals =
ansible
Expand Down

0 comments on commit 34c1459

Please sign in to comment.