YAMLer Action
Tags: github, githubactions
Published: 2021-05-10 08:57:43

---
title: YAMLer Action
published: true
date: 2021-04-30 09:40:13 UTC
tags: github,githubactions
canonical_url: https://michaelheap.com/yamler-action/
series: Action Spotlight
---

When running your workflows, sometimes you need to read information from a file in your repository. `YAMLer` parses the provided YAML file and makes the values in the file available as output variables.

| Fact Sheet | |
| --- | --- |
| Author | juliojimenez |
| Contributors | 1 |
| Stars | 4 |
| Repo | [https://github.com/juliojimenez/yamler](https://github.com/juliojimenez/yamler) |
| Marketplace | [https://github.com/marketplace/actions/yamler](https://github.com/marketplace/actions/yamler) |

## What does it do?

`YAMLer` takes each field in the provided YAML document and makes it available as an output variable. Nested resources are nested using a double underscore (`__`).

Take the following YAML file as an input:


```yaml
summary: This is a description
contributor:
  name: Michael
  handle: mheap
projects:
  - actions-book
  - github-default-branch
```

These variables would be available as follows:

```yaml
summary: This is a description
contributor__name: Michael
contributor__handle: mheap
contributor__projects__0: actions-book
contributor__projects__1: github-default-branch
```

The action works for deeply nested values and has been tested with scalars (strings, numbers, booleans), objects and arrays.

In addition to making nested properties available, the action also handles special characters.

Using the sample from the [YAML.org](http://yaml.org/) test file, we can see that periods and parenthesis are replaced:

```yaml
YAML Resources:
  YAML 1.2 (3rd Edition): http://yaml.org/spec/1.2/spec.html
  YAML 1.1 (2nd Edition): http://yaml.org/spec/1.1/
  YAML 1.0 (1st Edition): http://yaml.org/spec/1.0/
  YAML Issues Page: https://github.com/yaml/yaml/issues
```

Is made available as:

```yaml
yaml_resources__yaml_1_2_3rd_edition: http://yaml.org/spec/1.2/spec.html
yaml_resources__yaml_1_1_2nd_edition: http://yaml.org/spec/1.1/
yaml_resources__yaml_1_0_1st_edition: http://yaml.org/spec/1.0/
yaml_resources__yaml_issues_page: https://github.com/yaml/yaml/issues
```

Notice how the periods are replaced with underscores, and the parenthesis are removed? Let’s take a look at the rules for replacement in the source!

## How does it work?

The entire action is available [in a single file](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts) which makes it easy to understand what’s going on.

The [entry point](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L90-L100) reads the file provided in the `yaml-file` input and passes it to `traverseObject` to start building the output. This method [iterates over the keys](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L30) in the provided YAML file and decides how to process each entry.

- If the value [is a scalar](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L32-L37) (string, number or boolean) we’re at the end of a nested value (the leaf) and it’s time to [add an output](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L38-L42)
- If the value [is an object or an array](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L43), we [keep track of all the keys we saw](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L44) whilst traversing to this depth and then call either `traverseArray` or `traverseObject` as required.
  - Calling `traverseArray` [loops over all values in the array](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L56-L83) and emits a new value if we detect a scalar
  - Calling `traverseObject` is [a recursive call](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L48) which starts this set of bullet points again with the child value passed in as the argument

Whilst processing keys, the action applies the following rules:

- [Replace whitespace, `/`, `-`, `.` or `:` with an underscore](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L13)
- [Remove parenthesis `()`, square brackets `[]`, single quotes and commas](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L17)
- [Replace `+` with `p`](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L21)
- [Replace `#` with `s`](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/src/index.ts#L25)

The last two substitutions seem strange to me, but I guess the author had a use case where it made sense.

As mentioned earlier, the action has a [single required input](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/action.yml#L4-L6) which is the path to the YAML file to read. [It runs using the `node12` runtime](https://github.com/juliojimenez/yamler/blob/815b577e88e9ddf583be1d80d98443571b303677/action.yml#L7-L9) thanks to a compiled version of the action being available in the `build` directory.

Finally, the action uses semantic versioning. It’s currently at `v0` whilst it’s in beta, and uses the [release-github-actions](https://github.com/technote-space/release-github-actions) action to automatically build and commit an updated `build/index.js` file when a release is created. Then the major and minor tags are updated to point at the new release commit.