Processing YAML In GitHub Workflows
Tags: github, yaml, typescript, devops
Published: 2020-12-11 16:54:23

My team deploys infrastructure to the cloud using GitHub Workflows, allowing us to validate, test, and flexibly build infrastructure-as-code prior to applying changes. To target specific environments and solutions, we have developed global and per-project YAML configurations to accompany our workflow matrix strategy.

To use these configurations, we need something in our workflow to read them. The GitHub Marketplace has a wide selection of YAML validators and linters, but only a couple of actual YAML processors.

At the time of this writing, the processors in existence were of varying degrees of functionality and reliability, either in their ability, or inability, to set GitHub Workflow output variables by default, leaving the developer to add additional steps in creating the variables.  Others had the right idea as described in their README, but the action itself would not execute due to errors.

As a temporary solution to unblock ourselves from jobs failing because of non-working actions, I came up with what I called the “Poor Man’s YAML Processor”, it is not pretty but it got the job done for the day.

```
- name: 'Config'
  run: echo "::set-output name=foo::$(echo $(egrep "^foo\:\ [^\S]*" .ci_config.yaml | cut -d':' -f2 | sed s/\S//g))"
  id: config

- name: ‘Use The Output’
  Run: echo “${{ steps.config.outputs.foo }}
```
# Enter The Dragon

Try doing this for more than two values in your GitHub Workflow config file, and you will quickly feel the pain.  Enter the dragon...err...[yamler](https://github.com/marketplace/actions/yamler).

**yamler** is a GitHub Action that processes an entire YAML document and makes all elements available as GitHub Workflow output variables.

```
- name: yamler
  uses: juliojimenez/yamler@v0
  id: yamler
  with:
    yaml-file: "example.yaml"
```

Let's say our example.yaml file contains the following...

```
foo: bar
bar: foo
```

We can access these key/values as GitHub Workflow output variables from the yamler step above:

```
# Use the output from the yamler step
- name: Output
run: |
  echo "${{ steps.yamler.outputs.foo }}"
  echo "${{ steps.yamler.outputs.bar }}"
```

yamler preserves document structure using double-underscore (`__`) notation. If a value is located at `foo.bar`, the yamler output variable will become `foo__bar`. Arrays are indexed in a similar way, the element `bar.foo[5]` can be accessed with yamler at `bar__foo__5`.

# Faster Than Green Grass Through A Goose

I was pheasantly surprised at our GitHub Check time savings after switching to yamler from the _other_ processor. The reason for this is that yamler is written in Typescript (which compiles to Javascript), and our previous processor was installed from a Docker container, which took almost an entire minute.

You can find more information about different types of actions and creating your own actions [here](https://docs.github.com/en/free-pro-team@latest/actions/creating-actions/about-actions).

Thank you for reading, and I hope yamler makes someones day easier. Drop us a star!

https://github.com/marketplace/actions/yamler
https://github.com/juliojimenez/yamler