How to create a dropdown in a GitHub action job - github

My job needs to receive 2 input parameter from the user.
Valid values of those parameters are defined by a separate script. These values can change (not able to hard code them) so I want to populate the list dynamically when the job is to be run. The picker should update according to the result of the script allowing the user to select and only then should the actual job be run with those values as input to the job
Question is how to provide a drop down like that

Since Nov. 2021, the input type can actually be a choice list.
GitHub Actions: Input types for manual workflows
You can now specify input types for manually triggered workflows allowing you to provide a better experience to users of your workflow.
In addition to the default string type, we now support choice, boolean, and environment.
name: Mixed inputs
on:
workflow_dispatch:
inputs:
name:
type: choice
description: Who to greet
options:
- monalisa
- cschleiden
message:
required: true
use-emoji:
type: boolean
description: Include 🎉🤣 emojis
environment:
type: environment
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Send greeting
run: echo "${{ github.event.inputs.message }} ${{ fromJSON('["", "🥳"]')[github.event.inputs.use-emoji == 'true'] }} ${{ github.event.inputs.name }}"
That would provide a dropdown.
The question remains: can you pass a list of choices as variable to your input choice field?
You should, if you can populate the inputs context, through another job (computing your list), and calling your choice job, passing the list through jobs.<job_id>.with / jobs.<job_id>.with.<input_id>

Related

GitHub actions inputs don't get printed with echo

I've been trying to set up the most basic GitHub action that can be triggered via API, and I managed to trigger it, but now I'm having trouble passing down the "inputs" and using them in the jobs...
I tried reading the documentation and all, and it should work but I'm probably missing some syntax or something...
Here's the action code:
name: Test
on:
repository_dispatch:
inputs:
body:
default: 'testdefaultvalue'
description: 'Test desc'
required: true
jobs:
print_inputs:
runs-on: ubuntu-latest
steps:
- name: Print inputs
run: echo "The inputs are ${{ inputs.body }}"
And here's the body that I'm trying to send using POST which hits and triggers this action
{"event_type": "my_event", "client_payload": {"body": "Hello, world!"}}
I keep getting only the first part of the echo, like on this screenshot
I even tried just printing out the inputs body with the default value using a different kinds of syntaxes but nothing worked. Hopefully, this is not a duplicate and someone will help me and it'll be useful for someone in the future as well!
According to repository_dispatch, you need to refer to the complete event context to get the values.
So, this should work in your case:
echo ${{ github.event.client_payload.body }}

GitHub Actions: How to view inputs for workflow_dispatch?

My idea here is to write my inputs from workflow_dispatch on each pipeline run. .
For example, in Bitbucket pipelines input parameters shown after custom -
Is there a way to do something similar for GitHub?
Although this does not directly answer your question, I'm adding it here because this is where I landed looking for the answer on how to output all my workflow inputs.
In my case I am using a workflow_dispatch trigger - YMMV if you are using a different trigger, but I suspect it would work the same way.
As with the other answer proposed, you will need to do this as a step within your job:
on:
workflow_dispatch:
inputs:
myInput:
default: "my input value"
jobs:
myJob:
steps:
- name: Output Inputs
run: echo "${{ toJSON(github.event.inputs) }}"
This will result in output you can view in your GitHub action execution output with the inputs serialized as JSON:
{
"myInput": "my input value"
}
If you have only a few simple input values (from workflow_dispatch) then you can include them in the name of the job:
on:
workflow_dispatch:
inputs:
my_value:
description: 'My input value'
required: true
default: 'foo'
type: string
jobs:
my_job:
name: "My job [my_value: ${{ github.event.inputs.my_value }}]"
runs-on: ubuntu-latest
steps:
....
This way you will be able to see the input directly in the GitHub UI.
You cannot really alter how they will be displayed on the list I'm afraid.
All you can do is to log your input variables inside action itself, like this:
jobs:
debugInputs:
runs-on: ubuntu-latest
steps:
- run: |
echo "Var1: ${{ github.event.inputs.var1 }}"
echo "Var2: ${{ github.event.inputs.var2 }}"
If you want to see them in summary, you can use a notice or warning message mark:
I was looking for something similar and landed on logging + writing to the Job Summary.
I created a small action that can easily be used as a first step in your workflow, since I found myself need

How do I pass the job name into a github action's input?

jobs:
my-name:
name: "My Name"
...
steps:
- name: Slack Notification
uses: my-action
with:
slack-msg: ${{ jobs.${{ env.GITHUB_JOB }}.name }}
I want that slack-msg to evaluate to "My Name". I'm using my-action in multiple jobs, and I always want to pass in the job name, but I don't know how to do that. When I tried the above, the job literally didn't run and I don't know how to troubleshoot why: the github workflow log for my-name literally doesn't exist.
How do I pass job-name into an input parameter?
As nested expression are not supported you can use a trick like below to obtaint the matrix job name.
jobs:
test:
env:
# to expose matrix job name to steps, which is not possible with expansions
JOB_NAME: ${{ matrix.name || format('{0} ({1})', matrix.tox-target, matrix.os) }}
name: ${{ matrix.name || format('{0} ({1})', matrix.tox-target, matrix.os) }}
Note that you cannot really access the matrix name, but you can ensure you save the same name into an environment variable and use that.

Passing object as a variable to Github action

How can I pass an additional object type variable?
When I try to do this in the yaml file a get an error:
Invalid type found: one of string , number , boolean were expected but an array was found
on: pull_request_review
name: Label approved pull requests
jobs:
labelWhenApproved:
name: Label when approved
runs-on: ubuntu-latest
steps:
- name: Label when approved
uses: ***
env:
APPROVALS:
- value: "1"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ADD_LABEL: "approved"
REMOVE_LABEL: "awaiting%20review"
The env: section allows you to pass Environment Variables to the actions. The environment variables are key - value. You cannot pass objects.
From GitHub docs:
A map of environment variables
In some cases you can "stringify" a whole object and pass it as an environment variable using toJSON(), but the action itself should "know" how to handle it (e.g to parse the object from the string)
Example how to pass all secrets to an actions:
env:
SECRETS: '${{ toJSON(secrets) }}'
Note: There can be env in different levels in the workflows - you can have them on "global", on a job, or on step (in your case it is a step)
This is a bit of an old question and you've probably found some sort of workaround, but here is an option for you. This is what we do when we need to pass an object into a string input:
env:
APPROVALS: |
- value: "1"
The | converts the next block into a multi-line string. Everything until the next outdentation is a string.
What this means is that your action *** must then use a yaml parser to convert from the string to an object.

How can I invoke a YAML pipeline that has both variables and runtime parameters?

I have a scenario where I need to have both:
runtime parameters, so that the pipeline can be triggered manually from the UI, where users triggering it can choose from a predefined set of options (defined in YAML)
variables, so that the pipeline can be invoked via REST APIs
Regarding runtime parameters, I was able to create the following sample pipeline:
parameters:
- name: image
displayName: Pool Image
type: string
default: ubuntu-latest
values:
- windows-latest
- ubuntu-latest
trigger: none
stages:
- stage: A
jobs:
- job: A
steps:
- pwsh: |
echo "This should be triggering against image: $MY_IMAGE_NAME"
env:
MY_IMAGE_NAME: ${{ parameters.image }}
When I run it, I can see the dropdown list where I can choose the image name and it is reflected in the output message of the PowerShell script.
Regarding variables, I have defined one called "image" here (notice the value is empty):
The idea now is to invoke the pipeline from REST APIs and have the image name replaced by the value coming from the variable:
{
"definition": {
"id": 1
},
"sourceBranch": "master",
"parameters": "{\"image\": \"windows-latest\" }"
}
In order to make the step print the value I'm passing here, I need to correct the environment variable in some way. I thought it would be sufficient to write something like:
env:
MY_IMAGE_NAME: ${{ coalesce(variables.image, parameters.image) }}
That's because I want to give the priority to the variables, then to parameters, so that in case none is specified, I always have a default value the pipeline can use.
However, this approach doesn't work, probably because we're dealing with different expansion times for variables, but I don't really know what I should be writing instead (if there is a viable option, of course).
What I also tried is:
env:
MY_IMAGE_NAME: ${{ coalesce($(image), parameters.image) }}
MY_IMAGE_NAME: ${{ coalesce('$(image)', parameters.image) }}
MY_IMAGE_NAME: $[ coalesce(variables.image, parameters.image) ]
MY_IMAGE_NAME: $[ coalesce($(image), parameters.image) ]
None of those are working, so I suspect this may not be feasible at all.
There is a workaround that I'm currently thinking of, which is to create two different pipelines so that those can be invoked independently, but while this is quite easy for me to accomplish, given I'm using a lot of templates, I don't find it the right way to proceed, so I'm open to any suggestion.
I tested and found you might need to define a variable and assign the parameter's value to it (eg. Mimage: ${{parameters.image}}). And define another variable(eg. Vimage) and assign $[coalesce(variables.image, variables.Vimage)] to it. Then refer to $(Vimage) in the env field of powershell task. Please check out below yaml.
parameters:
- name: image
displayName: Pool Image
type: string
default: ubuntu-latest
values:
- windows-latest
- ubuntu-latest
trigger: none
stages:
- stage: A
jobs:
- job: A
variables:
Mimage: ${{parameters.image}}
Vimage: $[coalesce(variables.image, variables.Mimage)]
steps:
- pwsh: |
echo "This should be triggering against image: $env:MY_IMAGE_NAME"
env:
MY_IMAGE_NAME: $(Vimage)
Env field of powershell task is usually for mapping secret variables. You can directly refer to $(Vimage) in the powershell script: echo "This should be triggering against image: $(Vimage).
Note: To queue a build via REST API with provided parameters, you need to check Let users override this value when running this pipeline to make the varilabe to be settable at queue time.
Update:
You can try passing the variables to the parameters of the template to make the parameters for template dynamic. Please check below simple yaml.
jobs:
- template: template.yaml
parameters:
MTimage: ${{parameters.image}}
VTimage: $(Vimage)
template.yaml:
parameters:
MTimage:
VTimage:
jobs:
- job: buildjob
steps:
- powershell: |
echo "${{parameters.VTimage}}"
echo "${{parameters.MTimage}}"