Tooling for Maintaining YAML Files
Table of Contents
YAML is an essential part of modern software development. It has been an established format for configurations for years, and is unlikely to be replaced for a long time to come. Many, many products now use YAML for configuration, from developer tools and continuous integration pipelines to tools for managing systems like Kubernetes and Ansible.
Ideally, we generate YAML files. This ensures that they are valid, correctly formatted and consistent. However, many YAML files are manually edited, even if they were originally generated by systems. This article describes some standard tools that help us maintain YAML documents, regardless of how they are created or changed.
All of these tools become most effective when they work automatically. We can run them in text editors and with pre-commit hooks that call them when we commit changes to version control. We should also run them in continuous integration pipelines. If they run in continuous integration, we ensure that all of the YAML files in a project are always maintained to the same standard.
Formatting, Linting and Validating YAML #
These tools will work on files that use standard YAML:
- Prettier - Formats many types of file, including YAML
- yamllint - Lints YAML files
- check-jsonschema - Checks JSON and YAML files with identified types against their schema
You can run them with both pre-commit hooks and on-demand by using the pre-commit tool. Since they are command-line tools, you can also run them as part of continuous integration pipelines.
All of these tools have useful default configurations, so you only need to add configuration files if you need to customize their behavior.
Prettier and schemas also work in modern text editors. These editors can run Prettier on your code. They usually require a plugin, but Zed has Prettier built-in. Editors use the same schemas as check-jsonschema for error checking and autocompletion.
Formatting with Prettier #
Prettier formats files for a wide range of programming languages and data types, including YAML. It is deliberately opinionated, so that every installation of Prettier formats files in exactly the same way, unless users decide to override it.
If your text editor supports Prettier and is configured to format YAML files on save then it works automatically. The Zed editor has Prettier built-in. For other editors, the documentation for the Prettier plugin should explain how to set it up.
Automated code formatting improves software projects for no cost. When we apply the same formatter on every change, the format of the code becomes consistent and predictable, which enables us to rapidly refactor projects. Automatic code formatting also removes the need for commits that only format files.
Linting with yamllint #
The yamllint tool ensures that files are valid YAML. It applies rules that are designed for standard YAML.
If you have YAML files that are templates, you will need to provide a custom configuration for yamllint, or use a specialized tool for the files that are in that format, such as cfn-lint for CloudFormation. For Ansible, we do both: the ansible-lint tool is intended to be used alongside yamllint.
By design,
yamllintignores files with a double file extension, such as.yaml.jinja. These files are likely to be templates.
Validation with check-jsonschema #
The schemas for YAML formats are JSON Schemas. Each schema is a JSON file that describes JSON or YAML. Vendors publish the schemas for their products to the Schema Store. You can create your own schemas.
Modern text editors like Visual Studio Code, JetBrains IDEs, Neovim and Zed use JSON Schemas for autocompletion and error-checking. These editors download schemas for YAML files from the Schema Store, which means that both editors and tools like check-jsonschema apply the same rules.
Visual Studio Code requires the redhat.vscode-yaml extension to support schemas for YAML.
The check-jsonschema tool checks YAML and JSON files against the relevant schema. It includes copies of schemas for popular tools and can use other schemas, including your own schemas. It also provides hooks for pre-commit.
Running Tools with pre-commit #
The pre-commit tool both manages Git pre-commit hooks and enables you to run the same actions at any time, not just when you commit changes. The pre-commit tool itself requires Python to run, but it will download the other runtimes and tools that the hooks need. This means that pre-commit provides a cross-platform way to install and run a complete set of tools for formatting and checking code.
Installing pre-commit #
To install pre-commit, use either pipx or uv:
pipx install pre-commit
uv tool install pre-commit
Adding pre-commit To a Project #
The pre-commit configuration must be in a file called .pre-commit-config.yaml file. Save this file in the root directory of your project:
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v6.0.0"
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/rbubley/mirrors-prettier
rev: "v3.5.2"
hooks:
- id: prettier
- repo: https://github.com/adrienverge/yamllint.git
rev: "v1.37.1"
hooks:
- id: yamllint
args: ["--strict"]
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: "0.33.3"
hooks:
- id: check-github-workflows
- id: check-taskfile
This configuration enables Prettier, yamllint and check-jsonschema. It also includes check-yaml, one of the standard pre-commit-hooks. This hook uses ruamel.yaml to check YAML files for syntax errors. I leave it in place because it does not slow down small projects. It is redundant, and you might choose to remove it.
To activate the configuration, run pre-commit install. This adds the pre-commit hooks to the Git configuration for your copy of the project, so that the tools automatically run on the staged changes each time that you commit.
cd my-project
pre-commit install
Since the
pre-commitconfiguration file is YAML, it will automatically be formatted and checked by the same tools thatpre-commitruns itself.
Using pre-commit #
The tools automatically run on the staged changes each time that you commit. To run a tool without commiting a change, use precommit run. If you add the option --all-files it will check the current files in the project, not just staged changes.
For example, to run the check-github-workflows hook on the project, use this command:
pre-commit run check-github-workflows --all-files
To run all of the hooks on the project, use this command:
pre-commit run --all-files
Updating pre-commit Hooks #
To update all of the hooks to their current version, run this command:
pre-commit autoupdate
It automatically edits the .pre-commit-config.yaml file to update the versions of the hooks. You then commit this change to source control, so that other copies of the repository will use the same versions.