GitHub Actions矩阵中的成对值

31

我希望为一个C和C++项目构建三个编译器版本:gcc、gcc-8和clang(用于C编译器),应分别使用g++、g++-8和clang++作为C ++编译器。

这是3个总配置。 我不想使用所有C和C ++编译器版本的“产品”,即没有gcc / g ++ -8等。

我怎样才能指定一个包含这三个配置的矩阵,每个配置都设置两个变量?

目前我正在使用以下内容(注意指定了2个操作系统,因此总共有6个配置):

    strategy:
      matrix:
        os: [ubuntu-16.04, ubuntu-latest]
        cpp_compiler: [g++, g++-8, clang++]
        include:
          - c_compiler: gcc
          - cpp_ompiler: g++-8
            c_compiler: gcc-8
          - cpp_compiler: clang++
            c_compiler: clang

本质上,C++编译器 (cpp_compiler) 被用作主要版本,然后以一种巧妙的方式使用 include 来基于 cpp_compiler 版本设置 c_compiler ,但必须有更好的方法...


看起来你的方法是这样做的推荐方式:https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#example-including-additional-values-into-combinations。虽然我同意这似乎有些hacky,因为它涉及相当多的重复。 - jidicula
3个回答

52

除了@jidicula的答案,将matrix存储为array外,您还可以将其存储为map,这将使工作流程更易读。

因此,以下工作流应该更美观:

# simplified

strategy:
  matrix:
    os: [ubuntu-16.04, ubuntu-latest]
    compiler: [ {cpp: g++, c: gcc}, {cpp: g++-8, c: gcc-8}, {cpp: clang++, c: clang} ]
steps:
  - name: Compile with C++ compiler
    run: ${{ matrix.compiler.cpp }} source.cpp
  - name: Compile with C compiler
    run: ${{ matrix.compiler.c }} source.c

当此工作流程被触发时,它将使用不同的矩阵并行执行6次。

1: matrix.os == ubuntu-16.04, matrix.compiler.cpp == g++, matrix.compiler.c == gcc
2: matrix.os == ubuntu-16.04, matrix.compiler.cpp == g++-8, matrix.compiler.c == gcc-8
3: matrix.os == ubuntu-16.04, matrix.compiler.cpp == clang++, matrix.compiler.c == clang
4: matrix.os == ubuntu-latest, matrix.compiler.cpp == g++, matrix.compiler.c == gcc
5: matrix.os == ubuntu-latest, matrix.compiler.cpp == g++-8, matrix.compiler.c == gcc-8
6: matrix.os == ubuntu-latest, matrix.compiler.cpp == clang++, matrix.compiler.c == clang

然而,无论是 array 还是 map,其语法目前尚未记录,虽然在某个时刻之后的语法检查器不再将其标记为错误。因此,这一切可能会在未来发生变化。


24

我刚试过了,结果发现你可以在一个构建矩阵中嵌套数组,但这是没有记录的。因此,您可以在job.matrix中创建一个编译器数组的数组。我们称之为compiler-version: compiler-version: [[g++, gcc], [g++-8, gcc-8], [clang++, clang]]。然后,您可以使用零索引访问compiler-version数组中每个元素的每个值:matrix.compiler-version[0]用于C++编译器,matrix.compiler-version[1]用于其C对应项。

您的工作流将变成:

    strategy:
      matrix:
        os: [ubuntu-16.04, ubuntu-latest]
        compiler-version: [[g++, gcc], [g++-8, gcc-8], [clang++, clang]]
    steps:
      # .... checkout steps
      - name: Compile file with C++ compiler
        env:
          COMPILER: ${{ matrix.compiler-version[0] }}
        run: |
          $COMPILER file.c
          ./a.out
      - name: Compile file with C compiler
        env:
          COMPILER: ${{ matrix.compiler-version[1] }}
        run: |
          $COMPILER file.c
          ./a.out

我已经用2个Python版本和2个Ubuntu版本构建了一个最小的矩阵示例,其中3.7配对Ubuntu-18.04,而3.8则配对Ubuntu-20.04。您可以在此处查看工作流文件以及其相应的运行此处

这种解决方案避免了在工作流文件的2个位置定义C++选项时的尴尬。虽然它没有文档记录,但我认为它是稳定的,因为GitHub Actions上下文对象是(或者至少被视为)JavaScript对象,所以我们只是将数组字面值定义为矩阵对象属性并访问它们的值。


3
一些补充:matrix的值也可以存储map。例如:val: [ { x: 'str1' }, { y: 'str2' } ],使用方法:${{ matrix.val.x }},这将使代码更易读。但是,无论是数组还是映射,Actions的语法检查器都会用红色下划线标记,并报告错误“矩阵选项必须仅包含原始值”。实际上它是有效的,只需忽略错误即可。然而,由于目前没有记录,所有这些可能会在未来发生变化。 - Sprite
有趣的是它将其标记为错误 - 我完全忘记了Web编辑器和Actions语法检查器。我完全同意这是一种冒险的方法,因为它没有记录,并且未来可能会更改。 - jidicula
1
@Sprite - 我认为你的评论是正确的答案,而且这也是我目前正在使用的。你想把它作为答案吗? - BeeOnRope
1
@Sprite - 目前语法检查器似乎没有标记矩阵条目本身,但是像 ${{ matrix.mapping.value }} 这样的后续使用会出现 "未知上下文访问" 错误的下划线。这种错误在其他情况下也很常见,例如许多 env. 上下文的用法。 - BeeOnRope

6
除了其他人的答案,要求您更改yml代码以稍微改变使用矩阵“变量”的方式之外,您可以通过使用include标签来简单实现所需结果的特定矩阵。这样做使得代码更易读,并且需要更少的工作量。
示例:
    strategy:
      matrix:
        include:
          - cpp_compiler: g++
            c_compiler: gcc,
          - cpp_compiler: g++-8
            c_compiler: gcc-8
          - cpp_compiler: clang++
            c_compiler: clang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接