Can I use a mix of self-hosted & github-hosted runners in a single matrix job?

Can I write a build matrix that uses self-hosted runners only for certain OS’s in my build?

I.e. For a build that is to run on Windows, MacOS & Linux, can I have my linux runners as self-hosted and the Windows & MacOS ones as github-hosted, and if so, how would I do that?

Currently i’m having to duplicate my entire job steps, one for the Linux, and one for the other Matrixed builds.

Specifically, I will be having 2 builds on each OS, with JDKs 8 & 11 respectively, the linux builds will be self-hosted.

In addition to this, the 2 self-hosted runners will be further chosen by a “jdk” setting, so that if the “jdk8” label is used, the self-hosted runner holding that label will be chosen, and the same for “jdk11”.

I’ve got as far as trying this:

  MyJob: 
    name: MyJob
    runs-on: ['${{ matrix.os }}', 'jdk${{ matrix.jdk }}'] 
    strategy:
      fail-fast: false
      matrix:
        os: [self-hosted, windows-2019, macos-10.15]
        jdk: [8, 11]
    steps:
      - name: Setup java
        uses: actions/setup-java@v1
        with:
          java-version: ${{ matrix.jdk }}
        if: matrix.os != 'self-hosted'
      - name: Build environment information
        run: echo $HOSTNAME && java -version

But that doesn’t work beacuse the non-self hosted jobs won’t trigger because they don’t like the JDK label.

Update, I got this to work although it’s a bit hacky:

jobs:
  MyJob: 
    runs-on: ${{ matrix.os }} 
    strategy:
      fail-fast: false
      matrix:
        os: [[self-hosted, jdk8], [self-hosted, jdk11]]
        required: [required]
        include:
          - {os: macos-10.15, required: required, jdk: 8}
          - {os: macos-10.15, required: optional, jdk: 11}
          - {os: windows-2019, required: required, jdk: 8}
          - {os: windows-2019, required: optional, jdk: 11}
    steps:
      - run: 'echo "Matrix OS: ${{ matrix.os }}"'
      - name: Setup java
        uses: actions/setup-java@v1
        with:
          java-version: ${{ matrix.jdk }}
        if: matrix.os == 'macos-10.15' || matrix.os == 'windows-2019'
      - name: Build environment information
        run: echo $HOSTNAME && java -version && mvn --version && gradle --version

I originally hoped I could simply include the jdk property as a matrix property, and then exclude the 2 extra self-hosted jobs it would spawn (e.g. “self-hosted, jdk8 (my label), jdk8 (the matrix property)”)

However include/exclude doesn’t like “matrix.os” being an array here, so i’ve had to instead write it as i’ve done above, which is a bit more long-winded. Also I don’t like the labels it’s given the jobs, but at least it works.

${{ matrix.os }} returns “Array” when echo’d out, for the self-hosted runners now. But other than that it’s working fine, and is deploying to the correct VMs based on the “jdk8” & “jdk11” labels.

2 Likes

@johnlbergqvist,
According to your request, you also can try like as below:

jobs:
  MyJob: 
    runs-on: ${{ matrix.os }} 
    strategy:
      fail-fast: false
      matrix:
        os: [[self-hosted, jdk8], [self-hosted, jdk11], macos-10.15, windows-2019]
        required: [required]
        jdk: [8]
        include:
          - {os: macos-10.15, required: optional, jdk: 11}
          - {os: windows-2019, required: optional, jdk: 11}