I'm using Dhall to generate a Yaml file for github action. In GH Action, you can specify a matrix to generate multiple cases (e.g. combination of Scala version and project name). But you can also specify combination to exclude.
For example:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04]
node: [8, 10, 12, 14]
exclude:
# excludes node 8 on macOS
- os: macos-latest
- node: 8
Another valid example:
runs-on: ${{ matrix.os }}
strategy:
matrix:
jvm: [8, 11]
scala: [2.12.12, 2.13.5, 3.0.0]
exclude:
- jvm: 8
- scala: 2.12.12
A last one:
runs-on: ${{ matrix.os }}
strategy:
matrix:
ruby: [2.7.3, 3.0.0]
For matrix in particular, we have multiple fields that are List Text, but we also have exclude that I believe is a List of Record.
I can write this code in Dhall if I'm just writing it from scratch, without defining types (and it seems to generate a Record with the specific keys I have.
However if I want to build a library with types, or more specifically extends this one, I can't figure out how to write the correct type. Typically, see this definition:
{ matrix : List { mapKey : Text, mapValue : List Text }
, fail-fast : Optional Bool
, max-parallel : Optional Natural
}
https://github.com/regadas/github-actions-dhall/blob/master/types/Strategy.dhall
matrix is defined as a List { mapKey : Text, mapValue : List Text }, but exclude is not a List Text so it doesn't work. And I can't figure out how to change this definition to accept exclude.
Note that in the example it was os and node, but it can be any key, and any number of key.
So any idea how to define that type?
Edit: added more examples
It looks this requires a change to the upstream github-actions-dhall repository. Specifically,
matrixshould probably be a record ofOptionalfields rather than aMap. It would probably have at least these fields based on your example:For more guidance, see these chapters of the Dhall manual, which talk about how to model Dhall types when binding to configuration formats:
Edit: An easy way to convert example YAML configurations to either a Dhall value or the corresponding Dhall type is to use
yaml-to-dhall. For example, if you take the three examples you gave me and stick them in a YAML array (one element per example), like this:Then you can ask
yaml-to-dhallwhat type you can use that unifies all three of those examples, like this:Then if you just remove the
Listfrom the inferred type, then that is a valid type for your configuration that can handle those three examples:… and
yaml-to-dhallcan also show you what the corresponding Dhall values of that type would be:… although you will probably want to shorten that using Dhall's support for schemas. The above link to the Dhall manual on default handling has more details, but the short summary is that you can save the following three schemas to a file named
./schemas.dhall:… and then rewrite the result to use those schemas, like this: