Skip to content

Commit 2d9f1ed

Browse files
authored
Adding logic for configuring supported ansible versions (#4203)
1 parent 3f6f87f commit 2d9f1ed

File tree

12 files changed

+95
-25
lines changed

12 files changed

+95
-25
lines changed

.ansible-lint

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,7 @@ task_name_prefix: "{stem} | "
122122

123123
# Limit the depth of the nested blocks:
124124
# max_block_depth: 20
125+
126+
# Also recognize these versions of Ansible as supported:
127+
# supported_ansible_also:
128+
# - "2.14"

.github/workflows/tox.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
env:
7373
# Number of expected test passes, safety measure for accidental skip of
7474
# tests. Update value if you add/remove tests.
75-
PYTEST_REQPASS: 881
75+
PYTEST_REQPASS: 882
7676
steps:
7777
- uses: actions/checkout@v4
7878
with:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Invalid supported_ansible_also type
2+
supported_ansible_also: True

examples/meta_runtime_version_checks/pass/meta/runtime.yml

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
requires_ansible: ">=2.15.0,<2.17.0"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
requires_ansible: ">=2.9.10"

src/ansiblelint/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ def merge_config(file_config: dict[Any, Any], cli_config: Options) -> Options:
499499
"enable_list": [],
500500
"only_builtins_allow_collections": [],
501501
"only_builtins_allow_modules": [],
502+
"supported_ansible_also": [],
502503
# do not include "write_list" here. See special logic below.
503504
}
504505

src/ansiblelint/config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ class Options: # pylint: disable=too-many-instance-attributes
174174
ignore_file: Path | None = None
175175
max_tasks: int = 100
176176
max_block_depth: int = 20
177+
# Refer to https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix
178+
_default_supported = ["2.15.", "2.16.", "2.17."]
179+
supported_ansible_also: list[str] = field(default_factory=list)
177180

178181
@property
179182
def nodeps(self) -> bool:
@@ -186,6 +189,11 @@ def __post_init__(self) -> None:
186189
if self.nodeps:
187190
self.offline = True
188191

192+
@property
193+
def supported_ansible(self) -> list[str]:
194+
"""Returns list of ansible versions that are considered supported."""
195+
return sorted([*self._default_supported, *self.supported_ansible_also])
196+
189197

190198
options = Options()
191199

src/ansiblelint/rules/meta_runtime.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
# meta-runtime
22

3-
This rule checks the meta/runtime.yml `requires_ansible` key against the list of currently supported versions of ansible-core.
3+
This rule checks the meta/runtime.yml `requires_ansible` key against the list of
4+
currently supported versions of ansible-core.
45

56
This rule can produce messages such as:
67

7-
- `meta-runtime[unsupported-version]` - `requires_ansible` key must refer to a currently supported version such as: >=2.14.0, >=2.15.0, >=2.16.0
8-
- `meta-runtime[invalid-version]` - `requires_ansible` is not a valid requirement specification
8+
- `meta-runtime[unsupported-version]` - `requires_ansible` key must refer to a
9+
currently supported version such as: >=2.14.0, >=2.15.0, >=2.16.0
10+
- `meta-runtime[invalid-version]` - `requires_ansible` is not a valid
11+
requirement specification
912

10-
Please note that the linter will allow only a full version of Ansible such `2.16.0` and not allow their short form, like `2.16`. This is a safety measure
11-
for asking authors to mention an explicit version that they tested with. Over the years we spotted multiple problems caused by the use of the short versions, users
12-
ended up trying an outdated version that was never tested against by the collection maintainer.
13+
Please note that the linter will allow only a full version of Ansible such
14+
`2.16.0` and not allow their short form, like `2.16`. This is a safety measure
15+
for asking authors to mention an explicit version that they tested with. Over
16+
the years we spotted multiple problems caused by the use of the short versions,
17+
users ended up trying an outdated version that was never tested against by the
18+
collection maintainer.
1319

1420
## Problematic code
1521

@@ -19,7 +25,6 @@ ended up trying an outdated version that was never tested against by the collect
1925
requires_ansible: ">=2.9"
2026
```
2127
22-
2328
```yaml
2429
# runtime.yml
2530
---
@@ -33,3 +38,15 @@ requires_ansible: "2.15"
3338
---
3439
requires_ansible: ">=2.15.0"
3540
```
41+
42+
## Configuration
43+
44+
In addition to the internal list of supported Ansible versions, users can
45+
configure additional values. This allows those that want to maintain content
46+
that requires a version of ansible-core that is already out of support.
47+
48+
```yaml
49+
# Also recognize these versions of Ansible as supported:
50+
supported_ansible_also:
51+
- "2.14"
52+
```

src/ansiblelint/rules/meta_runtime.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,8 @@ class CheckRequiresAnsibleVersion(AnsibleLintRule):
3030
tags = ["metadata"]
3131
version_added = "v6.11.0 (last update)"
3232

33-
# Refer to https://access.redhat.com/support/policy/updates/ansible-automation-platform
34-
# Also add devel to this list
35-
supported_ansible = ["2.15.", "2.16.", "2.17."]
36-
supported_ansible_examples = [f">={x}0" for x in supported_ansible]
3733
_ids = {
38-
"meta-runtime[unsupported-version]": f"'requires_ansible' key must refer to a currently supported version such as: {', '.join(supported_ansible_examples)}",
34+
"meta-runtime[unsupported-version]": "'requires_ansible' key must refer to a currently supported version",
3935
"meta-runtime[invalid-version]": "'requires_ansible' is not a valid requirement specification",
4036
}
4137

@@ -50,22 +46,26 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
5046
if file.kind != "meta-runtime":
5147
return []
5248

53-
version_required = file.data.get("requires_ansible", None)
49+
requires_ansible = file.data.get("requires_ansible", None)
5450

55-
if version_required:
56-
if not any(
57-
version in version_required for version in self.supported_ansible
51+
if requires_ansible:
52+
if self.options and not any(
53+
version in requires_ansible
54+
for version in self.options.supported_ansible
5855
):
56+
supported_ansible = [f">={x}0" for x in self.options.supported_ansible]
57+
msg = f"'requires_ansible' key must refer to a currently supported version such as: {', '.join(supported_ansible)}"
58+
5959
results.append(
6060
self.create_matcherror(
61-
message=self._ids["meta-runtime[unsupported-version]"],
61+
message=msg,
6262
tag="meta-runtime[unsupported-version]",
6363
filename=file,
6464
),
6565
)
6666

6767
try:
68-
SpecifierSet(version_required)
68+
SpecifierSet(requires_ansible)
6969
except ValueError:
7070
results.append(
7171
self.create_matcherror(
@@ -90,10 +90,10 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
9090
("test_file", "failures", "tags"),
9191
(
9292
pytest.param(
93-
"examples/meta_runtime_version_checks/pass/meta/runtime.yml",
93+
"examples/meta_runtime_version_checks/pass_0/meta/runtime.yml",
9494
0,
9595
"meta-runtime[unsupported-version]",
96-
id="pass",
96+
id="pass0",
9797
),
9898
pytest.param(
9999
"examples/meta_runtime_version_checks/fail_0/meta/runtime.yml",
@@ -115,16 +115,37 @@ def matchyaml(self, file: Lintable) -> list[MatchError]:
115115
),
116116
),
117117
)
118-
def test_meta_supported_version(
118+
def test_default_meta_supported_version(
119119
default_rules_collection: RulesCollection,
120120
test_file: str,
121121
failures: int,
122122
tags: str,
123123
) -> None:
124-
"""Test rule matches."""
124+
"""Test for default supported ansible versions."""
125125
default_rules_collection.register(CheckRequiresAnsibleVersion())
126126
results = Runner(test_file, rules=default_rules_collection).run()
127127
for result in results:
128128
assert result.rule.id == CheckRequiresAnsibleVersion().id
129129
assert result.tag == tags
130130
assert len(results) == failures
131+
132+
@pytest.mark.parametrize(
133+
("test_file", "failures"),
134+
(
135+
pytest.param(
136+
"examples/meta_runtime_version_checks/pass_1/meta/runtime.yml",
137+
0,
138+
id="pass1",
139+
),
140+
),
141+
)
142+
def test_added_meta_supported_version(
143+
default_rules_collection: RulesCollection,
144+
test_file: str,
145+
failures: int,
146+
) -> None:
147+
"""Test for added supported ansible versions in the config."""
148+
default_rules_collection.register(CheckRequiresAnsibleVersion())
149+
default_rules_collection.options.supported_ansible_also = ["2.9"]
150+
results = Runner(test_file, rules=default_rules_collection).run()
151+
assert len(results) == failures

0 commit comments

Comments
 (0)