Execute GitHub Actions in different ways and merge input parameters with defaults.
If you finished reading my Trying GitHub Actions blog post, you might be thinking: what are all the ways I can run the same workflow? This blog post is the answer.
Let's say you can to run a GitHub Actions workflow:
on each pushed commit(s)
periodically (every day for example)
by manually calling it from the GitHub Actions page
by making an API call to GitHub API
My example is very simple. I just want to greet the user.
# run the workflow for different events # on every commit # and every morning # and when we trigger the workflow manually # and when we dispatch an event on: push: workflow_dispatch: schedule: # UTC time -cron:'0 7 * * *' repository_dispatch: types: [on-greeting] jobs: greet: runs-on:ubuntu-20.04 steps: -name:Greeting run:echo"Hello to you 1 times"
# run the workflow for different events # on every commit # and every morning # and when we trigger the workflow manually # and when we dispatch an event on: push: workflow_dispatch: inputs: n: description:Magicnumber type:number default:0 required:false greeting: description:Agreetingmessage type:string default:'' required:false schedule: # UTC time -cron:'0 7 * * *' repository_dispatch: types: [on-greeting] jobs: greet: runs-on:ubuntu-20.04 steps: -name:Greeting run:echo"${{ github.event.inputs.greeting }} to you ${{ github.event.inputs.n }} times"
When the user triggers the flow, they can enter the input parameters
Hmm, what about other events? How can we provide the default greeting and number of times for the push event, for example?
Default values
Let's put the default values into the workflow's env object
# run the workflow for different events # on every commit # and every morning # and when we trigger the workflow manually # and when we dispatch an event on: push: workflow_dispatch: inputs: n: description:Magicnumber type:number default:0 required:false greeting: description:Agreetingmessage type:string default:'' required:false schedule: # UTC time -cron:'0 7 * * *' repository_dispatch: types: [on-greeting] jobs: greet: runs-on:ubuntu-20.04 steps: -name:Greeting run:echo"${{ github.event.inputs.greeting || env.greeting }} to you ${{ github.event.inputs.n | env.n }} times"
This is better. Now the push and schedule workflows will use the default parameters.
The dispatch event API call
But what about repository_dispatch? We can trigger this workflow via an API call and pass parameters like this:
Tip: I used to wrap a similar command to trigger CircleCI workflows in my CLI tool trigger-circleci-pipeline. For GitHub Actions the API calls seems to be simple enough to use CURL and any request library to not require a separate plugin.
To use the client_payload we need to include it in the echo command too
# run the workflow for different events # on every commit # and every morning # and when we trigger the workflow manually # and when we dispatch an event on: push: workflow_dispatch: inputs: n: description:Magicnumber type:number default:0 required:false greeting: description:Agreetingmessage type:string default:'' required:false schedule: # UTC time -cron:'0 7 * * *' repository_dispatch: types: [on-greeting] jobs: greet: runs-on:ubuntu-20.04 steps: -name:Greeting run:| echo "${{ github.event.inputs.greeting || github.event.client_payload.greeting || env.n }} \ to you ${{ github.event.inputs.n || github.event.client_payload.n || env.n }} times"
Ughh it is getting ugly.
Merge inputs with defaults
Let's have a separate workflow step to merge all inputs with defaults. I will pass the merged values through the environment variables. We can output the variables into $GITHUB_ENV file to pass them to the next steps.
# run the workflow for different events # on every commit # and every morning # and when we trigger the workflow manually # and when we dispatch an event on: push: workflow_dispatch: inputs: n: description:Magicnumber type:number default:0 required:false greeting: description:Agreetingmessage type:string default:'' required:false schedule: # UTC time -cron:'0 7 * * *' repository_dispatch: types: [on-greeting] jobs: greet: runs-on:ubuntu-20.04 steps: -name:Setmergedvariables run:| echo "GREETING=${{ github.event.inputs.greeting || github.event.client_payload.greeting || env.greeting }}" >> $GITHUB_ENV echo "N=${{ github.event.inputs.n || github.event.client_payload.n || env.n }}" >> $GITHUB_ENV -name:Printworkflow_dispatchinputs run:echo"${{ toJson(github.event.inputs) }}"
-name:Greeting run:echo"$GREETING to you $N times"
Now we are cooking! If we trigger the workflow manually, we get the expected results
If we simply push the code to the remote origin, we get the default parameters
Dispatching an API call
Finally, every morning UTC time shows the following defaults
Tip: you can get the event's name and type to distinguish between the 4 workflow triggers
1 2 3
steps: -run:echo"event name is:"${{github.event_name}} -run:echo"event type is:"${{github.event.action}}
Update 1: pass an environment variable
When making a dispatch call, if you want to pass an environment variable, use an expression syntax inside the single quotes
1 2 3 4
# 🚨 does NOT work -d '{"event_type":"on-greeting","client_payload":{"branch":"$GITHUB_HEAD_REF"}}' # ✅ does work -d '{"event_type":"on-greeting","client_payload":{"branch":"${{ github.head_ref }}"}}'