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

feat(yaml): autofix GitHub Workflow files #437

Merged
merged 39 commits into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ba27873
test: steps should exist in the workflow
andreoliwa Jan 8, 2022
70870d2
Merge branch 'develop' into test-github-workflows
andreoliwa Jan 8, 2022
a63ab6a
test: list of scalars: change/add elements starting from index 0
andreoliwa Jan 8, 2022
a22ace1
refactor: use pydantic models for list details
andreoliwa Jan 9, 2022
f92951b
refactor: compare_list_elements()
andreoliwa Jan 9, 2022
5b4e168
refactor: rename to element_key, write comments
andreoliwa Jan 9, 2022
5601569
chore: fix mypy
andreoliwa Jan 9, 2022
e16bc72
refactor: join parent and nested keys again
andreoliwa Jan 9, 2022
eb7337a
refactor: deal with empty JMES expression
andreoliwa Jan 9, 2022
172f3b3
refactor: replace or add a new element in a YAML list
andreoliwa Jan 9, 2022
22dba62
refactor: remove unnecessary constants for classes
andreoliwa Jan 9, 2022
457cf1c
refactor: remove unused if condition
andreoliwa Jan 9, 2022
f838001
refactor: remove unused ValueError
andreoliwa Jan 9, 2022
8f04698
chore: some tomlkit classes and their representation on ruamel.yaml
andreoliwa Jan 9, 2022
decf76d
refactor: remove unused code
andreoliwa Jan 9, 2022
ea55cf8
docs: next change
andreoliwa Jan 9, 2022
73cbe4d
refactor: Comparison class
andreoliwa Jan 10, 2022
75f00f2
refactor: move compare_list_elements() to Comparison class
andreoliwa Jan 10, 2022
cd3e944
refactor: extract _compare_children()
andreoliwa Jan 10, 2022
ea1b486
refactor: typing and moving a chunk out
andreoliwa Jan 10, 2022
b9d3a91
feat: list of dicts: compare elements by hash when there's no key
andreoliwa Jan 11, 2022
5b1a923
refactor: rename again to __list_keys
andreoliwa Jan 11, 2022
72d11ec
docs: add special configuration section
andreoliwa Jan 11, 2022
838abf4
test: objects are compared by hash and new ones are added
andreoliwa Jan 11, 2022
0a0fcae
test: maximum of two-level nesting on lists
andreoliwa Jan 12, 2022
c9a2336
refactor: back to the simple syntax parent_key.child_key
andreoliwa Jan 12, 2022
1b81999
ci: change UTF-8 failing on Windows
andreoliwa Jan 12, 2022
df74aec
ci: UTF-8 still failing on Windows; remove umlaut
andreoliwa Jan 12, 2022
117cd38
feat: use wildcards on __list_keys
andreoliwa Jan 12, 2022
74c16fb
build: remove pydantic, use attrs
andreoliwa Jan 12, 2022
15c19ee
Merge branch 'develop' into test-github-workflows
andreoliwa Jan 13, 2022
3cea7cf
feat: merge the predefined plugin config with the style dict
andreoliwa Jan 13, 2022
cc82132
test: steps are present in any order
andreoliwa Jan 13, 2022
a89f10d
test: elements with the same key: only the first one will be considered
andreoliwa Jan 13, 2022
02422d7
docs: remove redundant file type from README
andreoliwa Jan 13, 2022
f00015e
style(pylint): whitelist pydantic
andreoliwa Jan 13, 2022
105143f
docs: __exact idea
andreoliwa Jan 13, 2022
f02e1ac
docs: fix comments
andreoliwa Jan 13, 2022
8fbc00f
test: fix expected pylint
andreoliwa Jan 13, 2022
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
3 changes: 3 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ load-plugins=
# Use multiple processes to speed up Pylint.
jobs=1

# https://github.com/samuelcolvin/pydantic/issues/1961#issuecomment-759522422
extension-pkg-whitelist=pydantic

[REPORTS]

# Set the output format. Available formats are text, parseable, colorized, msvs
Expand Down
17 changes: 1 addition & 16 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Implemented
* - `Any JSON file <https://nitpick.rtfd.io/en/latest/plugins.html#json-files>`_
- ✅
- ✅
* - `Any text file <https://nitpick.rtfd.io/en/latest/plugins.html#text-files>`_
* - `Any plain text file <https://nitpick.rtfd.io/en/latest/plugins.html#text-files>`_
- ✅
- ❌
* - `Any TOML file <https://nitpick.rtfd.io/en/latest/plugins.html#toml-files>`_
Expand All @@ -115,21 +115,9 @@ Implemented
* - `.editorconfig <https://nitpick.rtfd.io/en/latest/examples.html#example-editorconfig>`_
- ✅
- ✅
* - `package.json <https://nitpick.rtfd.io/en/latest/examples.html#example-package-json>`_
- ✅
- ✅
* - `.pre-commit-config.yaml <https://nitpick.rtfd.io/en/latest/plugins.html#pre-commit-config-yaml>`_
- ✅
- ✅
* - `.pylintrc <https://nitpick.rtfd.io/en/latest/plugins.html#ini-files>`_
- ✅
- ✅
* - `pyproject.toml <https://nitpick.rtfd.io/en/latest/plugins.html#toml-files>`_
- ✅
- ✅
* - `requirements.txt <https://nitpick.rtfd.io/en/latest/plugins.html#text-files>`_
- ✅
- ❌
* - `setup.cfg <https://nitpick.rtfd.io/en/latest/plugins.html#ini-files>`_
- ✅
- ✅
Expand Down Expand Up @@ -166,9 +154,6 @@ Planned
* - Makefile
- `#277 <https://github.com/andreoliwa/nitpick/issues/277>`_ 🚧
- ❓
* - .travis.yml
- `#15 <https://github.com/andreoliwa/nitpick/issues/15>`_ 🚧
- `#15 <https://github.com/andreoliwa/nitpick/issues/15>`_ 🚧
.. auto-generated-end-planned

Quickstart
Expand Down
4 changes: 4 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ Contents of `resources/python/github-workflow.toml <https://github.com/andreoliw
PYTHONUNBUFFERED = 1

[[".github/workflows/python.yaml".jobs.build.steps]]
name = "Checkout"
uses = "actions/checkout@v2"

[[".github/workflows/python.yaml".jobs.build.steps]]
Expand Down Expand Up @@ -570,6 +571,9 @@ Contents of `resources/python/pylint.toml <https://github.com/andreoliwa/nitpick
# Use multiple processes to speed up Pylint.
jobs = 1

# https://github.com/samuelcolvin/pydantic/issues/1961#issuecomment-759522422
extension-pkg-whitelist = "pydantic"

[".pylintrc".REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs (visual studio) and html.
# You can also give a reporter class, eg mypackage.mymodule.MyReporterClass.
Expand Down
10 changes: 1 addition & 9 deletions docs/generate_rst.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@
CONFIG_FILES,
DOT,
EDITOR_CONFIG,
PACKAGE_JSON,
PRE_COMMIT_CONFIG_YAML,
PROJECT_OWNER,
PYLINTRC,
PYPROJECT_TOML,
READ_THE_DOCS_URL,
SETUP_CFG,
)
Expand Down Expand Up @@ -164,23 +161,18 @@ def row(self) -> Tuple[str, str, str]:
IMPLEMENTED_FILE_TYPES: Set[FileType] = {
FileType("Any INI file", f"{READ_THE_DOCS_URL}plugins.html#ini-files", True, True),
FileType("Any JSON file", f"{READ_THE_DOCS_URL}plugins.html#json-files", True, True),
FileType("Any text file", f"{READ_THE_DOCS_URL}plugins.html#text-files", True, False),
FileType("Any plain text file", f"{READ_THE_DOCS_URL}plugins.html#text-files", True, False),
FileType("Any TOML file", f"{READ_THE_DOCS_URL}plugins.html#toml-files", True, True),
FileType("Any YAML file", f"{READ_THE_DOCS_URL}plugins.html#yaml-files", True, True),
FileType(EDITOR_CONFIG, f"{READ_THE_DOCS_URL}examples.html#example-editorconfig", True, True),
FileType(PRE_COMMIT_CONFIG_YAML, f"{READ_THE_DOCS_URL}plugins.html#pre-commit-config-yaml", True, True),
FileType(PYLINTRC, f"{READ_THE_DOCS_URL}plugins.html#ini-files", True, True),
FileType(PACKAGE_JSON, f"{READ_THE_DOCS_URL}examples.html#example-package-json", True, True),
FileType(PYPROJECT_TOML, f"{READ_THE_DOCS_URL}plugins.html#toml-files", True, True),
FileType("requirements.txt", f"{READ_THE_DOCS_URL}plugins.html#text-files", True, False),
FileType(SETUP_CFG, f"{READ_THE_DOCS_URL}plugins.html#ini-files", True, True),
}
PLANNED_FILE_TYPES: Set[FileType] = {
FileType("Any Markdown file", "", 280, 0),
FileType("Any Terraform file", "", 318, 0),
FileType(".dockerignore", "", 8, 8),
FileType(".gitignore", "", 8, 8),
FileType(".travis.yml", "", 15, 15),
FileType("Dockerfile", "", 272, 272),
FileType("Jenkinsfile", "", 278, 0),
FileType("Makefile", "", 277, 0),
Expand Down
24 changes: 16 additions & 8 deletions docs/ideas/yaml/lists.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
# 1. For some lists, only check if the element is present but don't enforce the whole list to be the same
[".pre-commit-config.yaml".ci]
skip = ["pylint"]
# List behaviours that are still not implemented in YAML (maybe they can be used in other formats too)

# 2. Search lists by a hash of the JSON/dic object another idea: . In a list of dicts, hash each dict of the actual list
# (all key/value pairs). Then loop through the new elements and only add those who were not found with the same hash
["some-file.yaml".__search_object_hash]
# Hash all fields
# 1. List behaviour: Exact list (dict or scalar) __exact
# The whole list will be replaced exactly by what's defined in the style
# Use the "__exact" suffix on the list name
[[".pre-commit-config.yaml".repos]]
repo = "https://github.com/alessandrojcm/commitlint-pre-commit-hook"
[[".pre-commit-config.yaml".repos.hooks]]
additional_dependencies__exact = ["@commitlint/config-conventional"]
id = "commitlint"
stages = ["commit-msg"]

# 2. List behaviour: Define the fields that should be part of the hash
["some-file.yaml".__list_hash_fields]
# Hash all fields (default)
some_list = "*"
# Hash only specific fields
person_list = "name,age,gender"
# Hash all fields except these
another_list = "-price,size"

# 3. Search using a custom function
# 3. List behaviour: Custom function (dict or scalar)
# Search using a custom function.
# A custom function called by Nitpick that receives X, Y, Z arguments (to be defined)
# And returns the new element and its index it should be in the list:
# - 0 to len(list)
Expand Down
7 changes: 7 additions & 0 deletions docs/source/nitpick.config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
nitpick.config module
=====================

.. automodule:: nitpick.config
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/source/nitpick.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Submodules
nitpick.blender
nitpick.cli
nitpick.compat
nitpick.config
nitpick.constants
nitpick.core
nitpick.enums
Expand Down
65 changes: 63 additions & 2 deletions docs/styles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,72 @@ To enforce all your projects to ignore missing imports, add this to your `nitpic
["setup.cfg".mypy]
ignore_missing_imports = true

.. _breaking-changes:
.. _special-configurations:

Breaking style changes
Special configurations
----------------------

Comparing elements on lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. note::

At the moment, this feature only works on `the YAML plugin <yamlplugin>`_.

On YAML files, a list (called a "sequence" in the YAML spec) can contain different elements:

- Scalar values like int, float and string;
- Dictionaries or objects with key/value pairs (called "mappings" in the YAML spec)
- Other lists (sequences).

The default behaviour for all lists: when applying a style, Nitpick_ searches
if the element already exists in the list; if not found, the element is appended at the end of list.

1. With scalar values, Nitpick_ compares the elements by their exact value.
Strings are compared in a case-sensitive manner, and spaces are considered.
2. Dicts are compared by a "hash" of their key/value pairs.

On lists containing dicts, it is possible to define a custom "list key" used to search for an element,
overriding the default compare mechanism above.

If an element is found by its key, the other key/values are compared and Nitpick_ applies the difference.
If the key doesn't exist, the new dict is appended at the end of the list.

Some files have a predefined configuration:

1. On ``.pre-commit-config.yaml``, repos are searched by their hook IDs.
2. On GitHub Workflow YAML files, steps are searched by their names.

You can define your own list keys for your YAML files (or override the predefined configs above) by using ``__list_keys`` on your style:

.. code-block:: toml

["path/from/root/to/your/config.yaml".__list_keys]
"<list expression>" = "<search key expression>"

``<list expression>``:

- a dotted path to a list, e.g. ``repos``, ``path.to.some.key``; or
- a pattern containing wildcards (``?`` and ``*``).
For example, ``jobs.*.steps``: all ``jobs`` containing ``steps`` will use the same ``<search key expression>``.

``<search key expression>``:

- a key from the dict inside the list, e.g. ``name``; or
- a parent key and its child key separated by a dot, e.g. ``hooks.id``.

.. warning::

For now, only two-level nesting is possible: parent and child keys.

If you have suggestions for predefined list keys for other popular YAML files not covered by Nitpick_ (e.g.: GitLab CI config),
feel free to `create an issue <https://github.com/andreoliwa/nitpick/issues/new/choose>`_ or submit a pull request.

.. _breaking-changes:

Breaking changes
----------------

.. warning::

Below are the breaking changes in the style before the API is stable.
Expand Down
67 changes: 7 additions & 60 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ marshmallow-polyfield = "^5.10"
identify = "*"
"more-itertools" = "*"
pluggy = "*"
pydantic = "*"
dataclasses = { version = "*", python = ">=3.6, <3.7" } # TODO: use attrs instead
autorepr = "*"
loguru = "*"
ConfigUpdater = "*"
Expand Down
Loading