Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ variable, use `fix_code`:
- item
- item
```
- Quote jobs.*.containers.volumes entries in GitHub Actions workflow yamls to not confuse GitHubs Yaml parser.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't say this is a feature, but a fix for an unexpected behavior, isn't it? If you agree I'd remove this line


# Configuration

Expand Down
17 changes: 17 additions & 0 deletions src/yamlfix/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
from io import StringIO
from typing import Any, Callable, List, Match, Optional, Tuple

from ruyaml.comments import CommentedMap, CommentedSeq
from ruyaml.main import YAML
from ruyaml.nodes import MappingNode, Node, ScalarNode, SequenceNode
from ruyaml.representer import RoundTripRepresenter
from ruyaml.scalarstring import DoubleQuotedScalarString, SingleQuotedScalarString
from ruyaml.tokens import CommentToken

from yamlfix.model import YamlfixConfig, YamlNodeStyle
Expand Down Expand Up @@ -379,12 +381,27 @@ def _ruamel_yaml_fixer(self, source_code: str) -> str:
# Return the output to a string
string_stream = StringIO()
for source_dict in source_dicts:
self._quote_gha_container_volumes(source_dict)
self.yaml.dump(source_dict, string_stream)
source_code = string_stream.getvalue()
string_stream.close()

return source_code.strip()

def _quote_gha_container_volumes(
self, source_dict: CommentedMap | CommentedSeq
) -> None:
"""Quote jobs.*.container.volumes entries."""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the phrasing of the docstring confusing. Wouldn't it be clearer something like prevent list strings to be converted to dictionaries?

I'd add an example of what this function fixes (the one in the issue is just fine)

I'd also change the name of the method, as it's not specific to gha_container_volumes, there may be other strings with colons that will benefit from this method

if not isinstance(source_dict, CommentedMap):
return
scalar_type = SingleQuotedScalarString
if self.config.quote_representation == '"':
scalar_type = DoubleQuotedScalarString
for job in source_dict.get("jobs", {}).values():
if volumes := job.get("container", {}).get("volumes", []):
for i, _ in enumerate(volumes):
volumes[i] = scalar_type(volumes[i])

@staticmethod
def _fix_top_level_lists(source_code: str) -> str:
"""Deindent the source with a top level list.
Expand Down
75 changes: 75 additions & 0 deletions tests/unit/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -1034,3 +1034,78 @@ def test_fix_code_fix_whitelines(
result = fix_code(source_code=source, config=config)

assert result == desired_source

@pytest.mark.parametrize(
("source", "config", "desired_source"),
[
(
dedent(
"""\
---
jobs:
test:
container:
volumes:
- /data:/data
- a:b # commented
- 'c:d'
- >-
multi:
line
"""
),
YamlfixConfig(sequence_style=YamlNodeStyle.FLOW_STYLE),
dedent(
"""\
---
jobs:
test:
container:
volumes:
- '/data:/data'
- 'a:b' # commented
- 'c:d'
- 'multi: line'
"""
),
),
(
dedent(
"""\
---
jobs:
test2:
container:
volumes:
- /data:/data
- a:b
- 'c:d'
- >-
multi:
line
"""
),
YamlfixConfig(sequence_style=YamlNodeStyle.FLOW_STYLE),
dedent(
"""\
---
jobs:
test2:
container:
volumes: ['/data:/data', 'a:b', 'c:d', 'multi: line']
"""
),
),
],
)
def test_strings_with_colons_are_quoted(
self, source: str, config: Optional[YamlfixConfig], desired_source: str
) -> None:
"""
Given: A GitHub Action workflow yaml containing jobs.*.containers.volumes
When: fix_code is run
Then: The volumes entries are quoted
"""
result = fix_code(source, config=config)

assert result == desired_source