Run matrix job on macos and on ubuntu in container

Let’s consider the following workflow:

name: On push

    branches: master

          - ubuntu-18.04
          - macos-10.14
    runs-on: ${{ matrix.os }}
    container: linuxbrew/brew
      - name: brew config
        run: |
          brew config

Currently the macos job will fail because: “##[error]File not found: ‘docker’”.

What I would want to see is: the macos job would run on macos VM and ubuntu job would run in container.

I know I can workaround this by making 2 separate jobs but I would need to repeat myself and would rather avoid that, granted that this workflow is simple and I can do it easily but it is just an example.


I definitely understand the motivation here.  I’m not sure that just ignoring the container key on macOS runs will necessarily be the solution, but we’ll look at how to simplify this for you so that it’s more DRY.


Just wanted to say this would be very helpful for us as well. Is there anyway currently we can write the yaml so that the container field is included conditionally, only for the linux builds? That would basically solve the issue for us I think.


Yes, the solution here would be for GitHub Actions to allow something like:

  image: debian:stable
  if: matrix.os == ubuntu-latest

for example.

This problem is compounded by the fact that Yaml anchors are not supported - further forcing us to duplicate CI specification code.

1 Like

@pmatos I like your suggestion! It’s concise, clear, explicit, and consistent. @ethomson what do you think?

For the record, I have exactly the same problem and would really enjoy a solution, like what @pmatos suggests!

@ethomson any update on this?

Hi all,
I tried a solution with a matrix job, but ending with a “a step cannot have both the uses and run keys” unfortunately.

The idea was to build this kind of matrix:

  - os: debian
    runnner: ubuntu-latest
    uses: docker://
  - os: redhat
    runnner: ubuntu-latest
    uses: docker://
  - os: suse
    runnner: ubuntu-latest
    uses: docker://
  - os: mac
    runnner: macos-10.14

Working on this implementation:

  runs-on: ubuntu-latest
    matrix: ${{ steps.set_vars.outputs.matrix }}
    - uses: actions/checkout@v2
    - id: set_vars
      run: |
        json_array="{\"include\":$(ls -d docker/* | cut -f2 -d'/' | jq --arg repo "docker://${{ github.repository }}/" --arg tag ":latest" -s -R -c 'split("\n") | to_entries | map( {"os": (.value), "runner": (if .value == "mac" then "macos-10.14" else "ubuntu-latest" end), "uses": (if .value == "mac" then "" else ($repo+.value+$tag) end) })'[:-1])}"
        echo "::set-output name=matrix::$( echo "$json_array" )"

  runs-on: ${{ matrix.runner }}
  needs: global_vars
  continue-on-error: true
    fail-fast: false
    matrix: ${{ fromJson(needs.global_vars.outputs.matrix) }}
    - name: "Running localen-builder for '${{ matrix.os }}'"
      uses: ${{ matrix.uses }}
      run: any_command

The way you build the matrix json depends on your specific needs.

But I couldn’t make it work.
Any news on this @ethomson

I have the same problem.

@ethomson Any update?

This practically not being supported forces anyone who needs to support executing items both in and outside containers to copy and paste all of their jobs, which is silly.

Either adding support for an if keyword to the container keyword or adding support for Yaml Anchors, as @pmatos wrote, would solve this issue for me.

Solving might also help. At least you wont have to copy all of your steps from job to job, as you could wrap all of your steps inside a composite action, but that feels like a bit of a band-aid.

Thank you.