0

我正在使用 Dhall 为 github 操作生成 Yaml 文件。在 GH Action 中,您可以指定一个矩阵来生成多个案例(例如 Scala 版本和项目名称的组合)。但您也可以指定要排除的组合。

例如:

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

另一个有效的例子:

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

最后一个:

runs-on: ${{ matrix.os }}
strategy:
  matrix:
    ruby: [2.7.3, 3.0.0]

(参见:https ://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#example- exclude-configurations-from-a-matrix )

特别是,matrix我们有多个领域是List Text,但我们也有exclude我认为是List的领域Record

如果我只是从头开始编写,我可以在 Dhall 中编写此代码,而不定义类型(并且它似乎Record使用我拥有的特定键生成 a。

但是,如果我想构建一个带有类型的库,或者更具体地说是扩展这个库,我不知道如何编写正确的类型。通常,请参见以下定义:

{ 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被定义为 a List { mapKey : Text, mapValue : List Text },但exclude不是 aList Text所以它不起作用。而且我不知道如何将此定义更改为 accept exclude

请注意,在示例中它是osand node,但它可以是任意键和任意数量的键。

那么知道如何定义该类型吗?

编辑:添加更多示例

4

1 回答 1

0

看起来这需要更改上游 github-actions-dhall 存储库。具体来说,matrix应该是Optional字段的记录而不是Map. 根据您的示例,它可能至少具有以下字段:

{ os : Optional (List Text)
, node : Optional (List Natural)
, exclude : { os : Optional Text, node : Optional Natural }
}

有关更多指导,请参阅 Dhall 手册的这些章节,其中讨论了在绑定到配置格式时如何对 Dhall 类型进行建模:

编辑:将示例 YAML 配置转换为 Dhall 值或相应 Dhall 类型的简单方法是使用yaml-to-dhall. 例如,如果您将给我的三个示例放入 YAML 数组中(每个示例一个元素),如下所示:

- 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
- 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
- runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      ruby: [2.7.3, 3.0.0]

然后您可以询问yaml-to-dhall您可以使用哪种类型来统一所有这三个示例,如下所示:

$ yaml-to-dhall type < examples.yaml  
List
  { runs-on : Text
  , strategy :
      { matrix :
          { exclude :
              Optional
                ( List
                    { jvm : Optional Natural
                    , node : Optional Natural
                    , os : Optional Text
                    , scala : Optional Text
                    }
                )
          , jvm : Optional (List Natural)
          , node : Optional (List Natural)
          , os : Optional (List Text)
          , ruby : Optional (List Text)
          , scala : Optional (List Text)
          }
      }
  }

然后,如果您只是List从推断类型中删除 ,那么对于您的配置来说,这是可以处理这三个示例的有效类型:

  { runs-on : Text
  , strategy :
      { matrix :
          { exclude :
              Optional
                ( List
                    { jvm : Optional Natural
                    , node : Optional Natural
                    , os : Optional Text
                    , scala : Optional Text
                    }
                )
          , jvm : Optional (List Natural)
          , node : Optional (List Natural)
          , os : Optional (List Text)
          , ruby : Optional (List Text)
          , scala : Optional (List Text)
          }
      }
  }

…并且yaml-to-dhall还可以向您展示该类型的相应 Dhall 值是什么:

$ ✓ yaml-to-dhall < examples.yaml     
[ { runs-on = "\${{ matrix.os }}"
  , strategy.matrix
    =
    { exclude = Some
      [ { jvm = None Natural
        , node = None Natural
        , os = Some "macos-latest"
        , scala = None Text
        }
      , { jvm = None Natural, node = Some 8, os = None Text, scala = None Text }
      ]
    , jvm = None (List Natural)
    , node = Some [ 8, 10, 12, 14 ]
    , os = Some [ "macos-latest", "windows-latest", "ubuntu-18.04" ]
    , ruby = None (List Text)
    , scala = None (List Text)
    }
  }
, { runs-on = "\${{ matrix.os }}"
  , strategy.matrix
    =
    { exclude = Some
      [ { jvm = Some 8, node = None Natural, os = None Text, scala = None Text }
      , { jvm = None Natural
        , node = None Natural
        , os = None Text
        , scala = Some "2.12.12"
        }
      ]
    , jvm = Some [ 8, 11 ]
    , node = None (List Natural)
    , os = None (List Text)
    , ruby = None (List Text)
    , scala = Some [ "2.12.12", "2.13.5", "3.0.0" ]
    }
  }
, { runs-on = "\${{ matrix.os }}"
  , strategy.matrix
    =
    { exclude =
        None
          ( List
              { jvm : Optional Natural
              , node : Optional Natural
              , os : Optional Text
              , scala : Optional Text
              }
          )
    , jvm = None (List Natural)
    , node = None (List Natural)
    , os = None (List Text)
    , ruby = Some [ "2.7.3", "3.0.0" ]
    , scala = None (List Text)
    }
  }
]

…尽管您可能希望使用 Dhall 对模式的支持来缩短它。上面关于默认处理的 Dhall 手册的链接有更多详细信息,但简短的总结是您可以将以下三个模式保存到名为 的文件中./schemas.dhall

-- ./schemas.dhall

let Exclusion =
      { Type =
          { jvm : Optional Natural
          , node : Optional Natural
          , os : Optional Text
          , scala : Optional Text
          }
      , default =
        { jvm = None Natural
        , node = None Natural
        , os = None Natural
        , scala = None Text
        }
      }

let Matrix =
      { Type =
          { exclude : Optional (List Exclusion.Type)
          , jvm : Optional (List Natural)
          , node : Optional (List Natural)
          , os : Optional (List Text)
          , ruby : Optional (List Text)
          , scala : Optional (List Text)
          }
      , default =
        { exclude = None (List Exclusion.Type)
        , jvm = None (List Natural)
        , node = None (List Natural)
        , os = None (List Text)
        , ruby = None (List Text)
        , scala = None (List Text)
        }
      }

let Config =
      { Type = { runs-on : Text, strategy : { matrix : Matrix.Type } }
      , default = {=}
      }

in  { Exclusion, Matrix, Config }

…然后重写结果以使用这些模式,如下所示:

$ yaml-to-dhall < examples.yaml | dhall rewrite-with-schemas --schemas ./schemas.dhall
let schemas = ./schemas.dhall

in  [ schemas.Config::{
      , runs-on = "\${{ matrix.os }}"
      , strategy.matrix
        = schemas.Matrix::{
        , exclude = Some
          [ schemas.Exclusion::{ os = Some "macos-latest" }
          , schemas.Exclusion::{ node = Some 8, os = None Text }
          ]
        , node = Some [ 8, 10, 12, 14 ]
        , os = Some [ "macos-latest", "windows-latest", "ubuntu-18.04" ]
        }
      }
    , schemas.Config::{
      , runs-on = "\${{ matrix.os }}"
      , strategy.matrix
        = schemas.Matrix::{
        , exclude = Some
          [ schemas.Exclusion::{ jvm = Some 8, os = None Text }
          , schemas.Exclusion::{ os = None Text, scala = Some "2.12.12" }
          ]
        , jvm = Some [ 8, 11 ]
        , scala = Some [ "2.12.12", "2.13.5", "3.0.0" ]
        }
      }
    , schemas.Config::{
      , runs-on = "\${{ matrix.os }}"
      , strategy.matrix = schemas.Matrix::{ ruby = Some [ "2.7.3", "3.0.0" ] }
      }
    ]
于 2021-05-12T15:18:29.987 回答