Search code examples
github-actions

Conditional use of container depending on the group it runs-on for GitHub Actions


I'm building some reusable workflows, and one of my workflows requires some specific prerequisite software to exist on the runner. I have a self-hosted runner pool I can use, and for those runners the prerequisite software is already on the runner servers. I can also use a pool of runners another group in my organization makes available, but for this other pool the runners don't have the prerequisite software, so I specify a container that will have the prerequisite software.

So I want to be able to specify a container when my workflow is running on group2, but not specify any container when it is running on group1.

Is there a way to make the container be optional in the workflow YAML definition? I don't want to duplicate the job and have conditional logic that runs one or the other just to allow one to use container and the other to not.

It seems like I can have either:

runs-on:
  group: 'group1'
steps:
...

Or

runs-on:
  group: 'group2'
container:
  image: 'myregistry.com/my-image-with-prerequisites-installed:latest'
steps:
...

But is there a way to have a single YAML file that will work for both? I want to choose the runner group as an input, and when the input group is 'group1' it uses no container, but when the input groups is 'group2' it uses a container--and without having to duplicate job configuration in the YAML.


Solution

  • I found a solution with this:

    inputs:
      runs-on:
        type: string
        description: 'JSON to be converted to the value of the "runs-on" configuration for the job.'
        required: false
        default: '{"group": "group1"}'  # '{"group": "group2"}'
      container:
        type: string
        description: 'JSON to be converted to the value of the "container" configuration for the job.  If image is null it will execute directly on the  runner.'
        required: false
        default: '{"image": null}'  # '{"image": "myregistry.com/my-image-with-prerequisites-installed:latest"}'
    jobs:
      my-job:
        runs-on: ${{ fromJson(inputs.runs-on) }}
        container: ${{ fromJSON(inputs.container) }}
    

    With that, when I set inputs to the following, it runs without a container:

    runs-on: '{"group": "group1"}'
    container: '{"image": null}'
    

    And when I set inputs to the following, it runs with a container:

    runs-on: '{"group": "group2"}'
    container: '{"image": "myregistry.com/my-image-with-prerequisites-installed:latest"}'
    

    This allows me to have a single YAML file that works correctly for both cases depending on what I choose for inputs.