Andrei Rînea
Andrei Rînea

Reputation: 20800

Parameterize `runs-on` value for GitHub action

I have this GitHub workflow that I need to parameterize on which runners runs. So in the YAML file I tried:

# ... 
jobs: 
  process:
    name: Process
    runs-on: ${{ secrets.GH_RUNNER_TAG }}
# ...

However, I get this error:

The workflow is not valid. .github/workflows/action.yml (Line: 12, Col: 14): Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.GH_RUNNER_TAG

Is the secrets injection not available for this element? Is there some other alternative? The value does not need to be a secret but I need to have it in one place and not edit hundreds of YAML files everytime the runner tag would change...


EDIT1: I've tried, as GuiFalourd suggested, to create an environment variable at the workflow level which would hold the secret:

env:
  RUNNER_LABEL: ${{ secrets.GH_RUNNER_TAG }}

jobs:
  analyze:
    name: Analyze
    runs-on: $RUNNER_LABEL

And it doesn't work. The action gets stuck. I tried using:

$RUNNER_LABEL -> gets stuck "$RUNNER_LABEL" -> gets stuck, too ${{ env.RUNNER_LABEL }} -> action does not start, outputs error:

The workflow is not valid. .github/workflows/action.yml (Line: 14, Col: 14): Unrecognized named-value: 'env'. Located at position 1 within expression: env.RUNNER_LABEL

Furthermore, I've checked that the env var is properly assigned, by placing a valid, hard-coded value for runs-on and setting first step as:

steps:
  - name: Test
    run: echo "$RUNNER_LABEL"

which produces "***" - proof that a secret has been output and redacted automatically by GitHub.

Upvotes: 8

Views: 7368

Answers (3)

saranicole
saranicole

Reputation: 2483

Found an alternative without using parameterized workflows. This works while using vars directly as documented in the example does not.

  1. In your workflow, create a prerequisite job that takes a workflow input on a hosted runner and sets the runner name as its output.
  2. Use the output from the prerequisite job to set the runner name on subsequent jobs.

The final workflow will look something like this:

name: Example Workflow

on:
  workflow_dispatch:
    inputs:
      runner:
        required: false
        description: 'Runner name'
        default: 'dev-runner'

jobs:
  prereq:
    runs-on: ubuntu-latest
    steps:
      - name: Provision step # at least one step is required in a job
        run: |
          echo "Provisioning ${{ github.event.inputs.runner }}"
    outputs:
      runner: ${{ github.event.inputs.runner }}
  actualjob:
    needs: prereq
    runs-on: ${{ needs.prereq.outputs.runner }}
    steps:
      - name: Ta-da
        run: echo "success!"

Upvotes: 5

koss
koss

Reputation: 147

Try this :

env:
  RUNNER_LABEL: ${{ secrets.GH_RUNNER_TAG }}

jobs:
  analyze:
    name: Analyze
    runs-on: ${{ env.RUNNER_LABEL }}

Upvotes: -1

Mostafa Hussein
Mostafa Hussein

Reputation: 11970

This is achievable using Reusable Workflow by configuring the "called" workflow to accept inputs from the caller.

The main pipeline which we can name it as "process" will use a shared codebase/pipeline lets call it "common" which can accept inputs, one of these inputs can be the runs-on value.

For example

# common.yml
name: parameterized job
on:
  workflow_call:
    inputs:
      runner:
        required: true
        type: string
jobs:
  common:
    name: Common
    runs-on: ${{ inputs.runner }}
    steps:
      - run: echo "Hello World"
# process.yml
name: process
on:
  push:

jobs:
  process:
    uses: username/repo/.github/workflows/common.yml@branch
    with:
      runner: machine_with_specific_label # using ${{ env.MY_RUNNER_LABEL }} is possible as well


Upvotes: 5

Related Questions