Help
cancel
Showing results for 
Search instead for 
Did you mean: 
Pilot Lvl 1
Message 1 of 4

matrix include

From:

https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-g...

 

1. You can add additional configuration options to a build matrix job that already exists.

 

2. You cannot use include to add new jobs to a build matrix

 

From my perspective, #1 is helpful, but if I have a choice between #1 and !#2, I'd prefer !#2.  

 

One can get around it, but often it requires either an additional workflow file, or a large number of excludes.  Neither is particularly dry.

 

Two examples:

 

Ruby gems (especially compiled gems) often test on multiple versions of Ruby, and often on Ubuntu, macOS, & Windows.  There are publically available builds of Ruby master, but not for all OS's, and some require additional software installation.  With other CI systems, one could simple add another job via include.  This cannot be done due to #2.

 

Also, starting with Ruby 2.6, JIT is available.  With other CI, one could have 2.6 in the matrix, and add an additional JIT job via include.  IOW, one job without JIT, one job with.  Again, can't easily be done...

3 Replies
Pilot Lvl 1
Message 2 of 4

Re: matrix include

Since a change allowing one to add to the matrix using 'include' would be a breaking change, maybe add the functionality using a name like 'additions'?

Copilot Lvl 2
Message 3 of 4

Re: matrix include

The current include/exclude behavior is symmetric. It is reasonable for me. But it is different meaning from travis-ci's include. travis-ci's include is very usuful for me. If GithubActions add the new feature that behaves as travis-ci's include, it's nice. I propose the feature name `add:` or `append:`. I choose verb because `include:` and `exclude:` are verb.

Highlighted
Pilot Lvl 2
Message 4 of 4

Re: matrix include

How about ignoring includes and writing matrix as a list?

 

This is my old matrix for compiling application as 32 and 64 bit on linux (with gcc/clang) and windows (with VS2017/VS2019):

  strategy:
   matrix:
    os:       [ubuntu-latest, windows-2016, windows-2019]
    platform: [x32, x64]
    compiler: [gnu, clang, cl]
    exclude:

    # linux - cl
    - os: ubuntu-latest
      platform: x32
      compiler: cl
    - os: ubuntu-latest
      platform: x64
      compiler: cl

    # windows-2016 - gnu
    - os: windows-2016
      platform: x32
      compiler: gnu
    - os: windows-2016
      platform: x64
      compiler: gnu

    # windows-2016 - clang
    - os: windows-2016
      platform: x32
      compiler: clang
    - os: windows-2016
      platform: x64
      compiler: clang

    # windows-2019 - gnu
    - os: windows-2019
      platform: x32
      compiler: gnu
    - os: windows-2019
      platform: x64
      compiler: gnu

    # windows-2019 - clang
    - os: windows-2019
      platform: x32
      compiler: clang
    - os: windows-2019
      platform: x64
      compiler: clang

Other than what's above, there was quite few ifs around to select proper compiler. And as you can guess, it was horrible.

 

And here is current matrix:

  strategy:
   matrix:
    cfg:
    - { os: ubuntu-latest, name: GNU,    cc: gcc,   cxx: g++,     platform: x32, redefine: Build/ReDefine }
    - { os: ubuntu-latest, name: GNU,    cc: gcc,   cxx: g++,     platform: x64, redefine: Build/ReDefine }
    - { os: ubuntu-latest, name: Clang,  cc: clang, cxx: clang++, platform: x32, redefine: Build/ReDefine }
    - { os: ubuntu-latest, name: Clang,  cc: clang, cxx: clang++, platform: x64, redefine: Build/ReDefine }
    - { os: windows-2016,  name: VS2017, cc: cl,    cxx: cl,      platform: x32, redefine: Build/Release/ReDefine.exe }
    - { os: windows-2016,  name: VS2017, cc: cl,    cxx: cl,      platform: x64, redefine: Build/Release/ReDefine.exe }
    - { os: windows-2019,  name: VS2019, cc: cl,    cxx: cl,      platform: x32, redefine: Build/Release/ReDefine.exe }
    - { os: windows-2019,  name: VS2019, cc: cl,    cxx: cl,      platform: x64, redefine: Build/Release/ReDefine.exe }

 

They both do same thing and compile everything like described above. There's even a space to add job name and platform-specific path to compiled program. And most importantly, it's much easier to read.

 

So yeah, nothing stops you from including configuration for steps inside matrix:

strategy:
 matrix:
  cfg:
  - { os: ubuntu-latest,  install-thing: yes, other-thing-version: 13.37 }
- { os: ubuntu-latest, install-thing: no }
- { os: windows-latest, install-thing: yes, other-thing-version: 12.07 } steps: - run: sudo apt install thing other-thing-${{ matrix.cfg.other-thing-version }} if: runner.os == 'Linux' && matrix.cfg.install-thing == 'yes'
- run: choco install thing other-thing-${{ matrix.cfg.other-thing-version }}
if: runner.os == 'Windows' && matrix.cfg.install-thing == 'yes'

 

Nothing stops you from packing several steps into one either:

- run:   |
         if [ "$RUNNER_OS" == "Linux" ] && [ "${{ matrix.cfg.install-thing }}" == "yes" ]; then
            sudo apt install thing
sudo apt install other-thing-${{ matrix.cfg.other-thing-version }}
elif [ "$RUNNER_OS" == "Windows" ] && [ "${{ matrix.cfg.install-thing }}" == "yes" ]; then
choco install thing
choco install other-thing-${{ matrix.cfg.other-thing-version }}
fi
some_other_application --available --on --all --platforms
shell: bash

 

Sure, matrix won't be as elegant as it is in documentation examples, steps most likely will be longer too...

But instead of fighting with includes (which probably won't change so close to end of beta anyway), or writing exclude sonets, spotted problems with build preparations have a chance to be solved inside steps, with just few ifs and ${{ }} (well... maybe more than just few...) as you can apply all kinds of crazy logic in there. And from your description of Ruby setup, it seems you need that :)