Skip to content

Commit f9ad8ea

Browse files
ziegenbergssbarnea
andauthored
Improve cli argument handling (#2099)
* Include opt-in rules when listing tags and rules With PR #1450 optional rules with the 'opt-in' tag were introduced and according to the docs, listing rules and tags should also list the opt-in rules. Fixes: #2068 Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at> * gracefully handle invalid format options with listing rules Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at> * put arguments -L and -T into a mutually exclusive group We either print a list of rules or a list of tags, but never both at the same time. So it makes no sense to allow giving both arguments at the same time. Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at> * always provide a long form of cli arguments Having short cli arguments for often used options is nice to have when using the command in an interactive shell. For writing scripts it would be better to have long forms of arguments as it increases the readebility. Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at> * Update tox.yml Co-authored-by: Sorin Sbarnea <sorin.sbarnea@gmail.com>
1 parent cd32348 commit f9ad8ea

6 files changed

Lines changed: 119 additions & 9 deletions

File tree

.github/workflows/tox.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ jobs:
155155
WSLENV: FORCE_COLOR:PYTEST_REQPASS:TOXENV:TOX_PARALLEL_NO_SPINNER
156156
# Number of expected test passes, safety measure for accidental skip of
157157
# tests. Update value if you add/remove tests.
158-
PYTEST_REQPASS: 611
158+
PYTEST_REQPASS: 621
159+
159160
steps:
160161
- name: Activate WSL1
161162
if: "contains(matrix.shell, 'wsl')"

docs/rules.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ The following shows the available tags in an example set of rules, and the
2727
rules associated with each tag:
2828

2929

30-
.. command-output:: ansible-lint -v -T
30+
.. command-output:: ansible-lint -T
3131
:cwd: ..
3232
:returncode: 0
3333
:nostderr:

src/ansiblelint/cli.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,27 @@ def get_cli_parser() -> argparse.ArgumentParser:
213213
"""Initialize an argument parser."""
214214
parser = argparse.ArgumentParser()
215215

216-
parser.add_argument(
216+
listing_group = parser.add_mutually_exclusive_group()
217+
listing_group.add_argument(
217218
"-L",
219+
"--list-rules",
218220
dest="listrules",
219221
default=False,
220222
action="store_true",
221-
help="list all the rules",
223+
help="List all the rules. For listing rules only the following formats "
224+
"for argument -f are supported: {plain, rich, rst}",
225+
)
226+
listing_group.add_argument(
227+
"-T",
228+
"--list-tags",
229+
dest="listtags",
230+
action="store_true",
231+
help="List all the tags and the rules they cover. Increase the verbosity level "
232+
"with `-v` to include 'opt-in' tag and its rules.",
222233
)
223234
parser.add_argument(
224235
"-f",
236+
"--format",
225237
dest="format",
226238
default="rich",
227239
choices=[
@@ -245,6 +257,7 @@ def get_cli_parser() -> argparse.ArgumentParser:
245257
)
246258
parser.add_argument(
247259
"-p",
260+
"--parseable",
248261
dest="parseable",
249262
default=False,
250263
action="store_true",
@@ -268,6 +281,7 @@ def get_cli_parser() -> argparse.ArgumentParser:
268281
)
269282
parser.add_argument(
270283
"-r",
284+
"--rules-dir",
271285
action=AbspathArgAction,
272286
dest="rulesdir",
273287
default=[],
@@ -310,14 +324,12 @@ def get_cli_parser() -> argparse.ArgumentParser:
310324
)
311325
parser.add_argument(
312326
"-t",
327+
"--tags",
313328
dest="tags",
314329
action="append",
315330
default=[],
316331
help="only check rules whose id/tags match these values",
317332
)
318-
parser.add_argument(
319-
"-T", dest="listtags", action="store_true", help="list all the tags"
320-
)
321333
parser.add_argument(
322334
"-v",
323335
dest="verbosity",
@@ -327,13 +339,15 @@ def get_cli_parser() -> argparse.ArgumentParser:
327339
)
328340
parser.add_argument(
329341
"-x",
342+
"--skip-list",
330343
dest="skip_list",
331344
default=[],
332345
action="append",
333346
help="only check rules whose id/tags do not " "match these values",
334347
)
335348
parser.add_argument(
336349
"-w",
350+
"--warn-list",
337351
dest="warn_list",
338352
default=[],
339353
action="append",
@@ -372,6 +386,7 @@ def get_cli_parser() -> argparse.ArgumentParser:
372386
)
373387
parser.add_argument(
374388
"-c",
389+
"--config-file",
375390
dest="config_file",
376391
help="Specify configuration file to use. By default it will look for '.ansible-lint' or '.config/ansible-lint.yml'",
377392
)
@@ -482,6 +497,13 @@ def get_config(arguments: List[str]) -> Namespace:
482497
parser = get_cli_parser()
483498
options = parser.parse_args(arguments)
484499

500+
if options.listrules and options.format not in ["plain", "rich", "rst"]:
501+
parser.error(
502+
f"argument -f: invalid choice: '{options.format}'. "
503+
f"In combination with argument -L only 'plain', "
504+
f"'rich' or 'rst' are supported with -f."
505+
)
506+
485507
file_config = load_config(options.config_file)
486508

487509
config = merge_config(file_config, options)

src/ansiblelint/rules/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,16 @@ def __init__(
344344

345345
def register(self, obj: AnsibleLintRule) -> None:
346346
"""Register a rule."""
347-
# We skip opt-in rules which were not manually enabled
348-
if "opt-in" not in obj.tags or obj.id in self.options.enable_list:
347+
# We skip opt-in rules which were not manually enabled.
348+
# But we do include opt-in rules when listing all rules or tags
349+
if any(
350+
[
351+
"opt-in" not in obj.tags,
352+
obj.id in self.options.enable_list,
353+
self.options.listrules,
354+
self.options.listtags,
355+
]
356+
):
349357
self.rules.append(obj)
350358

351359
def __iter__(self) -> Iterator[BaseRule]:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
{}

test/test_list_rules.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""Tests related to our logging/verbosity setup."""
2+
3+
import os
4+
5+
import pytest
6+
7+
from ansiblelint.testing import run_ansible_lint
8+
9+
10+
def test_list_rules_includes_opt_in_rules() -> None:
11+
"""Checks that listing rules also includes the opt-in rules."""
12+
# Piggyback off the .yamllint in the root of the repo, just for testing.
13+
# We'll "override" it with the one in the fixture.
14+
cwd = os.path.realpath(
15+
os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
16+
)
17+
fakerole = os.path.join("test", "fixtures", "list-rules-tests")
18+
19+
result_list_rules = run_ansible_lint("-L", fakerole, cwd=cwd)
20+
21+
assert ("opt-in" in result_list_rules.stdout) is True
22+
23+
24+
@pytest.mark.parametrize(
25+
("result", "returncode", "format_string"),
26+
(
27+
(False, 0, "plain"),
28+
(False, 0, "rich"),
29+
(False, 0, "rst"),
30+
(True, 2, "json"),
31+
(True, 2, "codeclimate"),
32+
(True, 2, "quiet"),
33+
(True, 2, "pep8"),
34+
(True, 2, "foo"),
35+
),
36+
ids=(
37+
"plain",
38+
"rich",
39+
"rst",
40+
"json",
41+
"codeclimate",
42+
"quiet",
43+
"pep8",
44+
"foo",
45+
),
46+
)
47+
def test_list_rules_with_format_option(
48+
result: bool, returncode: int, format_string: str
49+
) -> None:
50+
"""Checks that listing rules with format options works."""
51+
# Piggyback off the .yamllint in the root of the repo, just for testing.
52+
# We'll "override" it with the one in the fixture.
53+
cwd = os.path.realpath(
54+
os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
55+
)
56+
fakerole = os.path.join("test", "fixtures", "list-rules-tests")
57+
58+
result_list_rules = run_ansible_lint("-f", format_string, "-L", fakerole, cwd=cwd)
59+
print(result_list_rules.stdout)
60+
61+
assert (f"invalid choice: '{format_string}'" in result_list_rules.stderr) is result
62+
assert ("syntax-check" in result_list_rules.stdout) is not result
63+
assert result_list_rules.returncode is returncode
64+
65+
66+
def test_list_tags_includes_opt_in_rules() -> None:
67+
"""Checks that listing tags also includes the opt-in rules."""
68+
# Piggyback off the .yamllint in the root of the repo, just for testing.
69+
# We'll "override" it with the one in the fixture.
70+
cwd = os.path.realpath(
71+
os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
72+
)
73+
fakerole = os.path.join("test", "fixtures", "list-rules-tests")
74+
75+
result_list_tags = run_ansible_lint("-L", fakerole, cwd=cwd)
76+
77+
assert ("opt-in" in result_list_tags.stdout) is True

0 commit comments

Comments
 (0)