Skip to content

Commit 9dbccb8

Browse files
authored
Recognize standalone galaxy roles (#1363)
Identify when run with a standalone galaxy roles and attempt to make them available. This change may produce a specific error when 'author' field inside galaxy_info is missing or not matching namespace requirements. Fixes: #1329
1 parent 1452a0f commit 9dbccb8

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/ansiblelint/_prerun.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import pathlib
23
import re
34
import subprocess
45
import sys
@@ -13,7 +14,19 @@
1314
ANSIBLE_MISSING_RC,
1415
ANSIBLE_MOCKED_MODULE,
1516
INVALID_CONFIG_RC,
17+
INVALID_PREREQUISITES_RC,
1618
)
19+
from ansiblelint.loaders import yaml_from_file
20+
21+
MISSING_GALAXY_NAMESPACE = """\
22+
A valid role namespace is required, edit meta/main.yml and assure that
23+
author field is also a valid namespace:
24+
25+
galaxy_info:
26+
author: your_galaxy_namespace
27+
28+
See: https://galaxy.ansible.com/docs/contributing/namespaces.html#galaxy-namespace-limitations
29+
"""
1730

1831

1932
def check_ansible_presence() -> None:
@@ -87,10 +100,33 @@ def prepare_environment() -> None:
87100
if run.returncode != 0:
88101
sys.exit(run.returncode)
89102

103+
_install_galaxy_role()
90104
_perform_mockings()
91105
_prepare_ansible_paths()
92106

93107

108+
def _install_galaxy_role() -> None:
109+
"""Detect standalone galaxy role and installs it."""
110+
if not os.path.exists("meta/main.yml"):
111+
return
112+
yaml = yaml_from_file("meta/main.yml")
113+
if 'galaxy_info' not in 'yaml':
114+
return
115+
role_name = yaml['galaxy_info'].get('role_name', None)
116+
role_author = yaml['galaxy_info'].get('author', None)
117+
if not role_name:
118+
role_name = os.path.dirname(".")
119+
role_name = re.sub(r'^{0}'.format(re.escape('ansible-role-')), '', role_name)
120+
if not role_author or not re.match(r"[\w\d_]{2,}", role_name):
121+
print(MISSING_GALAXY_NAMESPACE, file=sys.stderr)
122+
sys.exit(INVALID_PREREQUISITES_RC)
123+
p = pathlib.Path(".cache/roles")
124+
p.mkdir(parents=True, exist_ok=True)
125+
link_path = p / f"{role_author}.{role_name}"
126+
if not link_path.exists:
127+
link_path.symlink_to(pathlib.Path("../..", target_is_directory=True))
128+
129+
94130
def _prepare_ansible_paths() -> None:
95131
"""Configure Ansible environment variables."""
96132
library_paths: List[str] = []

src/ansiblelint/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
INVALID_CONFIG_RC = 2
1616
ANSIBLE_FAILURE_RC = 3
1717
ANSIBLE_MISSING_RC = 4
18+
INVALID_PREREQUISITES_RC = 10
1819

1920
# Minimal version of Ansible we support for runtime
2021
ANSIBLE_MIN_VERSION = "2.9"

src/ansiblelint/loaders.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""Utilities for loading various files."""
2+
from typing import Any
3+
4+
import yaml
5+
6+
7+
def yaml_from_file(filepath: str) -> Any:
8+
"""Return a loaded YAML file."""
9+
with open(filepath) as content:
10+
return yaml.load(content, Loader=yaml.FullLoader)

0 commit comments

Comments
 (0)