Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow running with incompatible yamllint config #4158

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ repos:
- pytest-mock
- pytest>=7.2.2
- rich>=13.2.0
- ruamel-yaml-clib>=0.2.7
- ruamel-yaml>=0.18.2
- ruamel-yaml-clib>=0.2.8
- ruamel-yaml>=0.18.6
- subprocess-tee
- types-PyYAML
- types-jsonschema>=4.20.0.0
Expand Down
8 changes: 8 additions & 0 deletions src/ansiblelint/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,15 @@
match.ignored = True
_logger.debug("Ignored: %s", match)

if app.yamllint_config.incompatible:
logging.log(

Check warning on line 377 in src/ansiblelint/__main__.py

View check run for this annotation

Codecov / codecov/patch

src/ansiblelint/__main__.py#L377

Added line #L377 was not covered by tests
level=logging.ERROR if options.write_list else logging.WARNING,
msg=app.yamllint_config.incompatible,
)

if options.write_list:
if app.yamllint_config.incompatible:
sys.exit(RC.INVALID_CONFIG)

Check warning on line 384 in src/ansiblelint/__main__.py

View check run for this annotation

Codecov / codecov/patch

src/ansiblelint/__main__.py#L384

Added line #L384 was not covered by tests
fix(runtime_options=options, result=result, rules=rules)

app.render_matches(result.matches)
Expand Down
5 changes: 5 additions & 0 deletions src/ansiblelint/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ def __init__(self, options: Options):
verbosity=options.verbosity,
)

# pylint: disable=import-outside-toplevel
from ansiblelint.yaml_utils import load_yamllint_config # noqa: 811,I001

self.yamllint_config = load_yamllint_config()

def render_matches(self, matches: list[MatchError]) -> None:
"""Display given matches (if they are not fixed)."""
matches = [match for match in matches if not match.fixed]
Expand Down
27 changes: 19 additions & 8 deletions src/ansiblelint/yaml_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import logging
import os
import re
import sys
from collections.abc import Callable, Iterator, Sequence
from io import StringIO
from pathlib import Path
Expand All @@ -31,7 +30,6 @@
ANNOTATION_KEYS,
NESTED_TASK_KEYS,
PLAYBOOK_TASK_KEYWORDS,
RC,
)
from ansiblelint.utils import Task

Expand All @@ -48,6 +46,19 @@
_logger = logging.getLogger(__name__)


class CustomYamlLintConfig(YamlLintConfig): # type: ignore[misc]
"""Extension of YamlLintConfig."""

def __init__(
self,
content: str | None = None,
file: str | Path | None = None,
) -> None:
"""Initialize config."""
super().__init__(content, file)
self.incompatible = ""


def deannotate(data: Any) -> Any:
"""Remove our annotations like __file__ and __line__ and return a JSON serializable object."""
if isinstance(data, dict):
Expand All @@ -63,9 +74,10 @@ def deannotate(data: Any) -> Any:
return data


def load_yamllint_config() -> YamlLintConfig:
def load_yamllint_config() -> CustomYamlLintConfig:
"""Load our default yamllint config and any customized override file."""
config = YamlLintConfig(file=Path(__file__).parent / "data" / ".yamllint")
config = CustomYamlLintConfig(file=Path(__file__).parent / "data" / ".yamllint")
config.incompatible = ""
# if we detect local yamllint config we use it but raise a warning
# as this is likely to get out of sync with our internal config.
for path in [
Expand All @@ -82,7 +94,7 @@ def load_yamllint_config() -> YamlLintConfig:
"internal yamllint config.",
file,
)
custom_config = YamlLintConfig(file=str(file))
custom_config = CustomYamlLintConfig(file=str(file))
custom_config.extend(config)
config = custom_config
break
Expand Down Expand Up @@ -138,9 +150,8 @@ def load_yamllint_config() -> YamlLintConfig:
errors.append(msg)
if errors:
nl = "\n"
msg = f"Found incompatible custom yamllint configuration ({file}), please either remove the file or edit it to comply with:{nl} - {nl + ' - '.join(errors)}.{nl}{nl}Read https://ansible.readthedocs.io/projects/lint/rules/yaml/ for more details regarding why we have these requirements."
logging.fatal(msg)
sys.exit(RC.INVALID_CONFIG)
msg = f"Found incompatible custom yamllint configuration ({file}), please either remove the file or edit it to comply with:{nl} - {(nl + ' - ').join(errors)}.{nl}{nl}Read https://ansible.readthedocs.io/projects/lint/rules/yaml/ for more details regarding why we have these requirements. Fix mode will not be available."
config.incompatible = msg

_logger.debug("Effective yamllint rules used: %s", config.rules)
return config
Expand Down
9 changes: 3 additions & 6 deletions test/test_yaml_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from yamllint.linter import run as run_yamllint

import ansiblelint.yaml_utils
from ansiblelint.constants import RC
from ansiblelint.file_utils import Lintable, cwd
from ansiblelint.utils import task_in_list

Expand Down Expand Up @@ -996,8 +995,6 @@ def test_deannotate(

def test_yamllint_incompatible_config() -> None:
"""Ensure we can detect incompatible yamllint settings."""
with (
cwd(Path("examples/yamllint/incompatible-config")),
pytest.raises(SystemExit, match=f"^{RC.INVALID_CONFIG}$"),
):
ansiblelint.yaml_utils.load_yamllint_config()
with (cwd(Path("examples/yamllint/incompatible-config")),):
config = ansiblelint.yaml_utils.load_yamllint_config()
assert config.incompatible