Skip to content

Commit c81e65f

Browse files
authored
Temporary avoid auto-fixing YAML files not owned by ansible (#3837)
1 parent 3c90628 commit c81e65f

File tree

6 files changed

+73
-10
lines changed

6 files changed

+73
-10
lines changed

.github/workflows/tox.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
env:
7171
# Number of expected test passes, safety measure for accidental skip of
7272
# tests. Update value if you add/remove tests.
73-
PYTEST_REQPASS: 831
73+
PYTEST_REQPASS: 832
7474
steps:
7575
- uses: actions/checkout@v4
7676
with:

examples/.github/workflows/sample.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
name: ack
3+
on: # <-- ansible-lint should not complain or touch about this 'on'
4+
pull_request_target:
5+
types: [opened]
6+
7+
jobs:
8+
ack:
9+
uses: ansible/devtools/.github/workflows/ack.yml@main

src/ansiblelint/config.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,21 @@
9898
{"text/python": "**/*.py"},
9999
]
100100

101+
# File kinds that are recognized by ansible, used internally to force use of
102+
# YAML 1.1 instead of 1.2 due to ansible-core dependency on pyyaml.
103+
ANSIBLE_OWNED_KINDS = {
104+
"handlers",
105+
"galaxy",
106+
"meta",
107+
"meta-runtime",
108+
"playbook",
109+
"requirements",
110+
"role-arg-spec",
111+
"rulebook",
112+
"tasks",
113+
"vars",
114+
}
115+
101116
PROFILES = yaml_from_file(Path(__file__).parent / "data" / "profiles.yml")
102117

103118
LOOP_VAR_PREFIX = "^(__|{role}_)"

src/ansiblelint/file_utils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import wcmatch.wcmatch
1717
from yaml.error import YAMLError
1818

19-
from ansiblelint.config import BASE_KINDS, Options, options
19+
from ansiblelint.config import ANSIBLE_OWNED_KINDS, BASE_KINDS, Options, options
2020
from ansiblelint.constants import CONFIG_FILENAMES, FileType, States
2121

2222
if TYPE_CHECKING:
@@ -386,6 +386,10 @@ def __repr__(self) -> str:
386386
"""Return user friendly representation of a lintable."""
387387
return f"{self.name} ({self.kind})"
388388

389+
def is_owned_by_ansible(self) -> bool:
390+
"""Return true for YAML files that are managed by Ansible."""
391+
return self.kind in ANSIBLE_OWNED_KINDS
392+
389393
@property
390394
def data(self) -> Any:
391395
"""Return loaded data representation for current file, if possible."""

src/ansiblelint/transformer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ def run(self) -> None:
108108
if self.write_set != {"none"}:
109109
self._do_transforms(file, ruamel_data or data, file_is_yaml, matches)
110110

111+
if not file.is_owned_by_ansible():
112+
return
113+
111114
if file_is_yaml:
112115
# noinspection PyUnboundLocalVariable
113116
file.content = yaml.dumps(ruamel_data)

test/test_transformer.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import ansiblelint.__main__ as main
1313
from ansiblelint.app import App
14+
from ansiblelint.file_utils import Lintable
1415

1516
# noinspection PyProtectedMember
1617
from ansiblelint.runner import LintResult, get_matches
@@ -34,119 +35,150 @@ def fixture_runner_result(
3435

3536

3637
@pytest.mark.parametrize(
37-
("playbook_str", "matches_count", "transformed"),
38+
("playbook_str", "matches_count", "transformed", "is_owned_by_ansible"),
3839
(
3940
# reuse TestRunner::test_runner test cases to ensure transformer does not mangle matches
4041
pytest.param(
4142
"examples/playbooks/nomatchestest.yml",
4243
0,
4344
False,
45+
True,
4446
id="nomatchestest",
4547
),
46-
pytest.param("examples/playbooks/unicode.yml", 1, False, id="unicode"),
48+
pytest.param("examples/playbooks/unicode.yml", 1, False, True, id="unicode"),
4749
pytest.param(
4850
"examples/playbooks/lots_of_warnings.yml",
4951
993,
5052
False,
53+
True,
5154
id="lots_of_warnings",
5255
),
53-
pytest.param("examples/playbooks/become.yml", 0, False, id="become"),
56+
pytest.param("examples/playbooks/become.yml", 0, False, True, id="become"),
5457
pytest.param(
5558
"examples/playbooks/contains_secrets.yml",
5659
0,
5760
False,
61+
True,
5862
id="contains_secrets",
5963
),
6064
pytest.param(
6165
"examples/playbooks/vars/empty_vars.yml",
6266
0,
6367
False,
68+
True,
6469
id="empty_vars",
6570
),
66-
pytest.param("examples/playbooks/vars/strings.yml", 0, True, id="strings"),
67-
pytest.param("examples/playbooks/vars/empty.yml", 1, False, id="empty"),
68-
pytest.param("examples/playbooks/name-case.yml", 1, True, id="name_case"),
69-
pytest.param("examples/playbooks/fqcn.yml", 3, True, id="fqcn"),
71+
pytest.param(
72+
"examples/playbooks/vars/strings.yml",
73+
0,
74+
True,
75+
True,
76+
id="strings",
77+
),
78+
pytest.param("examples/playbooks/vars/empty.yml", 1, False, True, id="empty"),
79+
pytest.param("examples/playbooks/name-case.yml", 1, True, True, id="name_case"),
80+
pytest.param("examples/playbooks/fqcn.yml", 3, True, True, id="fqcn"),
7081
pytest.param(
7182
"examples/playbooks/multi_yaml_doc.yml",
7283
1,
7384
False,
85+
True,
7486
id="multi_yaml_doc",
7587
),
7688
pytest.param(
7789
"examples/playbooks/transform_command_instead_of_shell.yml",
7890
3,
7991
True,
92+
True,
8093
id="cmd_instead_of_shell",
8194
),
8295
pytest.param(
8396
"examples/playbooks/transform-deprecated-local-action.yml",
8497
1,
8598
True,
99+
True,
86100
id="dep_local_action",
87101
),
88102
pytest.param(
89103
"examples/playbooks/transform-block-indentation-indicator.yml",
90104
0,
91105
True,
106+
True,
92107
id="multiline_msg_with_indent_indicator",
93108
),
94109
pytest.param(
95110
"examples/playbooks/transform-jinja.yml",
96111
7,
97112
True,
113+
True,
98114
id="jinja_spacing",
99115
),
100116
pytest.param(
101117
"examples/playbooks/transform-no-jinja-when.yml",
102118
3,
103119
True,
120+
True,
104121
id="no_jinja_when",
105122
),
106123
pytest.param(
107124
"examples/playbooks/vars/transform_nested_data.yml",
108125
3,
109126
True,
127+
True,
110128
id="nested",
111129
),
112130
pytest.param(
113131
"examples/playbooks/transform-key-order.yml",
114132
6,
115133
True,
134+
True,
116135
id="key_order_transform",
117136
),
118137
pytest.param(
119138
"examples/playbooks/transform-no-free-form.yml",
120139
2,
121140
True,
141+
True,
122142
id="no_free_form_transform",
123143
),
124144
pytest.param(
125145
"examples/playbooks/transform-partial-become.yml",
126146
4,
127147
True,
148+
True,
128149
id="partial_become",
129150
),
130151
pytest.param(
131152
"examples/playbooks/transform-key-order-play.yml",
132153
1,
133154
True,
155+
True,
134156
id="key_order_play_transform",
135157
),
158+
pytest.param(
159+
"examples/.github/workflows/sample.yml",
160+
0,
161+
False,
162+
False,
163+
id="github-workflow",
164+
),
136165
),
137166
)
138167
@mock.patch.dict(os.environ, {"ANSIBLE_LINT_WRITE_TMP": "1"}, clear=True)
139-
def test_transformer(
168+
def test_transformer( # pylint: disable=too-many-arguments
140169
config_options: Options,
141170
playbook_str: str,
142171
runner_result: LintResult,
143172
transformed: bool,
173+
is_owned_by_ansible: bool,
144174
matches_count: int,
145175
) -> None:
146176
"""Test that transformer can go through any corner cases.
147177
148178
Based on TestRunner::test_runner
149179
"""
180+
# test ability to detect is_owned_by_ansible
181+
assert Lintable(playbook_str).is_owned_by_ansible() == is_owned_by_ansible
150182
playbook = Path(playbook_str)
151183
config_options.write_list = ["all"]
152184
transformer = Transformer(result=runner_result, options=config_options)

0 commit comments

Comments
 (0)