The standard way of running a workflow on several operating systems is using a matrix:
jobs:
package:
strategy:
matrix:
os: [ubuntu, macos, windows]
runs-on: ${{ matrix.os }}-latest
In some cases, it's useful to run the workflow on only one of the operating systems, for example, when debugging or when only one of them changed and there's no need to run the other two. How can only one of them be run?
One solution is to comment out the elements you don't need, but this is a very local and fragile solution.
Another could be creating 4 different workflows (one for each system + one for all), but this is cumbersome and gets complicated when you have a chain of workflows such as build
-> package
-> deploy
that now needs 4 variants each.
I tried using the choice
input to be able to select the systems,
on:
workflow_dispatch:
inputs:
os:
type: choice
options:
- windows
- macos
- ubuntu
- ubuntu, macos, windows
required: true
jobs:
package:
strategy:
matrix:
os: "${{ github.event.inputs.os }}"
runs-on: ${{ matrix.os }}-latest
which works for the single system choice, but not for the multiple one because it's taken as a single string "ubuntu, macos, windows"
.
I also tried to use a boolean
inputs to select any combination I need:
on:
workflow_dispatch:
inputs:
ubuntu:
required: true
type: boolean
macos:
required: true
type: boolean
windows:
required: true
type: boolean
but I'm not sure how to combine them into a matrix. I could do
...
jobs:
ubuntu:
if: ${{ inputs.ubuntu }}
runs-on: ubuntu-latest
steps: ...
macos:
if: ${{ inputs.macos}}
runs-on: macos-latest
steps: ...
windows:
if: ${{ inputs.windows}}
runs-on: windows-latest
steps: ...
Is there a way I'm "supposed" to use to achieve this functionality? Consider also that these workflows can be reusable (run the build
-> package
-> deploy
sequence on a single OS or all), so the OS inputs can be also received from calling workflows.
Based on Azeem's answer, I shortened the inputs
and matrix
handling to omit the "latest" suffix, and added it only in the runs-on
key where it is strictly needed. This way ${{ matrix.os }}
resolves to just the plain OS name (ubuntu
), which can be used elsewhere.
I also added the reusable workflow workflow_call
inputs so the workflow can be called with the same type of input:
name: package
on:
workflow_dispatch:
inputs:
os:
description: "Operating System"
required: true
type: choice
options:
- '["ubuntu", "macos", "windows"]'
- '["windows"]'
- '["macos"]'
- '["ubuntu"]'
workflow_call:
inputs:
os:
required: true
type: string
jobs:
package:
strategy:
matrix:
os: ${{ fromJson(inputs.os) }}
runs-on: ${{ matrix.os }}-latest
...
name: release
on:
workflow_dispatch:
inputs:
os:
description: "Operating System"
required: true
type: choice
options:
- '["ubuntu", "macos", "windows"]'
- '["windows"]'
- '["macos"]'
- '["ubuntu"]'
jobs:
package:
uses: ./.github/workflows/package.yml
with:
os: ${{ inputs.os }} # pass the expected string format to `package`
release:
...