Have you ever needed to update a YAML document on the fly?

Dasel is making this easier than ever before.

The Problem Space

There have been countless times that I’ve needed to manipulate YAML files from the command line, either because I’m running some kind of automation script or because I need to update a config file whilst running a pipeline.

One such time is in the deployment of this blog.

This blog is made using Hugo and requires a config.yml file to operate properly. One of the values you can set is an env which by default is development. When the blog is deployed this value should be changed to production - easy enough right?

Well… no. The blog is built and deployed using Github Actions so I can’t just open up the file in an editor and change this value.

Let’s look at how we can solve this.

Using Dasel

Let’s take a basic config.yaml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
baseURL: "/"
title: Tom Wright
paginate: 8
theme: papermod

sitemap:
  changefreq: weekly
  filename: sitemap.xml
  priority: 0.5

params:
  env: development
  title: Tom Wright
  author: "Tom Wright"

The line we’re interested in has been highlighted.

You can see that the current value of env is development. Let’s use dasel to change that.

You just need one command:

dasel put string -f data.yaml '.params.env' production

The contents of the file are now:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
baseURL: "/"
title: Tom Wright
paginate: 8
theme: papermod

sitemap:
  changefreq: weekly
  filename: sitemap.xml
  priority: 0.5

params:
  env: production
  title: Tom Wright
  author: "Tom Wright"

Great! We’re there. The config file now has an env value of production.

Let’s dig into that command so as we can understand exactly what’s going on.

Breaking down the command

So we used the following command:

dasel put string -f data.yaml '.params.env' production

It can be broken down into 4 parts.

dasel put string

Here we are telling dasel that we want to put a string value into a document.

-f data.yaml

This tells dasel which file we want to update. The data type is automatically picked up using the .yaml file extension.

If you don’t want to edit the file in-place you can pass add -o new_data.yaml which will write the results to a new file.

'.params.env'

This part of the command is called the selector. It tells dasel where to put the value.

This is a basic selector but there are many more that can be used to navigate through complex data structures.

If you want to read more you can do so in the selector documentation.

production

The final part of the command is the new value we want stored in the config file.

Piecing things together

Installation

The first thing we need to do is to get dasel installed. This is easy enough.

Just grab an executable from the latest release.

If you are on linux you can use the following command:

curl -s https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -qi - && mv dasel_linux_amd64 dasel && chmod +x dasel
mv ./dasel /usr/local/bin/dasel

This will download the latest release binary for linux and move it to /usr/local/bin.

You should now be able to run dasel --version and see something like this:

$ dasel --version
dasel version v1.12.1

Putting it into a GitHub Action

This part is simple - just re-produce the previous steps!

This is an example of a finished GitHub Action.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
on:
  push:
    tags:
      - 'v*.*.*'
name: Build
jobs:
  publish:
    strategy:
      matrix:
        go-version: [1.15.x]
        os:
          - ubuntu-latest
    name: Docker Build
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v2
      - name: Set env
        run: echo RELEASE_VERSION=${GITHUB_REF:10} >> $GITHUB_ENV
      - name: Download dasel
        run: curl -s https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -qi - && mv dasel_linux_amd64 dasel && chmod +x dasel && ./dasel --version
      - name: Set production
        run: ./dasel put string -f config.yml .params.env production
      - name: Build docker image
        run: docker build -t tomwright/blog:latest .
      - name: Docker login
        run: echo "${{ secrets.GHCR_PAT }}" | docker login ghcr.io -u TomWright --password-stdin
      - name: Docker tag latest
        run: docker tag tomwright/blog:latest ghcr.io/tomwright/blog:latest
      - name: Docker tag release
        run: docker tag tomwright/blog:latest ghcr.io/tomwright/blog:${{ env.RELEASE_VERSION }}
      - name: Docker push latest
        run: docker push ghcr.io/tomwright/blog:latest
      - name: Docker push release
        run: docker push ghcr.io/tomwright/blog:${{ env.RELEASE_VERSION }}

The above action does a few things, but the major steps are highlighted:

  1. Install the latest dasel release
  2. Updates the config file so as the hugo site is built for a production environment.

Finishing notes

Release versions

As with any other tool, it is recommended that you use a fixed release of dasel in your pipelines rather than just pulling the latest release.

This will stop you encountering any breaking changes as new releases are pushed out.

Local usage

My example above is within a GitHub Action but there’s nothing stopping you from using dasel locally!

More advanced usage

Dasel allows you to do more than just update a string in a YAML document.

Be sure to check the documentation so as you can use it to it’s fullest potential.