Auto-formatting YAML files with yamlfmt

I decided to see if there was an equivalent of Black or Prettier for YAML files. I found yamlfmt from Google.

Update: It turns out Prettier can format YAML too.

Installation

They suggest this:

go install github.com/google/yamlfmt/cmd/yamlfmt@latest

This worked on my machine because I had Go installed via Homebrew (go version go1.20.4 darwin/arm64 according to go version).

I wasn't sure where it had been installed - it turns out that if you don't have a GOPATH environment variable set then tools installed like this default to landing in ~/go/bin.

If you don't have Go installed, you can instead download a compiled binary from google/yamlfmt/releases.

Usage

You can pass files to it explicitly:

~/go/bin/yamlfmt .github/workflows/*.yml

Or you can run against every file .yml or .yaml file in a directory and its subdirectories:

~/go/bin/yamlfmt .

The default format looked like this:

name: Publish Python Package
on:
  release:
    types: [created]
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11"]
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}

Configuration

It removed some of my whitespace (I had newlines in front of those on: and jobs: keys), and I really didn't like the way it handled lists - adding an unnecessary additional two spaces of indent before each list item.

You can pass it configuration to fix this.

Here's what I ended up with:

~/go/bin/yamlfmt \
  -formatter indentless_arrays=true,retain_line_breaks=true \
  .github/workflows/*.yml

The order of this matters: you can't put -formatter after the list of files or it will be silently ignored.

This gave me:

name: Publish Python Package

on:
  release:
    types: [created]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11"]
    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}

There's also a mechanism where you can put configuration options in a .yamlfmt file, or a file passed using --conf - those are explained here.

Configuring defaults

You can set system-wide defaults for the tool by adding a .yamlfmt in the right place. On macOS I found it worked putting it here:

/.config/yamlfmt/.yamlfmt

I set the following options in that file:

formatter:
  retain_line_breaks: true
  indentless_arrays: true
  scan_folded_as_literal: true

Now I can run ymalfmt anywhere without extra arguments and get my preferred formatting rules.

I added scan_folded_as_literal: true because I noticed that it was reformatting my > string literal blocks to a single line, which I didn't like. Here's what it was doing:

   expected: >
-    Here comes a table <table>
-    <thead><tr><th>One</th><th>Two</th></tr></thead>
-    <tbody> <tr><td>1</td><td>2</td></tr> </tbody>
-    </table> Done
+    Here comes a table <table> <thead><tr><th>One</th><th>Two</th></tr></thead> <tbody> <tr><td>1</td><td>2</td></tr> </tbody> </table> Done

Running it in CI with -lint

The -lint option lets you check formatting in CI and fail if it would reformat (like black --check). You can run it like this:

~/go/bin/yamlfmt \
  -formatter indentless_arrays=true,retain_line_breaks=true \
  -lint \
  .github/workflows/*.yml

Which will output a full copy of the reformatted file, with as indicator as to which lines it changes.

I found that a bit noisy. You can add -quiet to get a less verbose output showing just the file paths that would change:

~/go/bin/yamlfmt \
  -formatter indentless_arrays=true,retain_line_breaks=true \
  -lint \
  -quiet \
  .github/workflows/*.yml

Output:

2023/07/13 07:16:36 The following files had formatting differences:

.github/workflows/publish.yml

Created 2023-07-13T07:11:44-07:00, updated 2023-07-13T08:28:37-07:00 · History · Edit