user19089852
user19089852

Reputation: 281

Schedule Trigger Github Action workflow with Input parameters

I want to run my Github workflow two ways:

  1. Manually by user
  2. Cron job

Now, everything was running fine until I added input parameters. After that, the cron job is running but not picking default value.

Here is my yaml:

name: WebDriverIO Automation
on:
  workflow_dispatch:
    inputs:
        typeOfTesting:
          type: choice
          description: Select Type of Test
          default: 'stage-test-local-All'
          required: true
          options: 
          - stage-test-local-All
          - stage-test
          - stage-test-local-Sanity
          - prod-test
    branches:
      - workingBranch
      - JSNew
  schedule:
    - cron: "*/5 * * * *"

Upvotes: 26

Views: 24895

Answers (8)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4739

I had same situation where the workflow was supposed to be executed on schedule basis, but also with an option to run manually for adhoc testing.

So below is working code to achieve same.

name: Scheduled Patrol Tests

on:
  schedule:
    - cron: 0 18 * * 1-5
  workflow_dispatch:
    inputs:
      env:
        required: false
        type: string
        default: "non-prod"
      testing_devices:
        required: false
        default: "Google Pixel 8"
        type: string
      locales:
        required: false
        default: "['en','fr']"
        type: string
        description: "List of locales for testing"

jobs:
  android-tests:
    name: Android Tests for {{matrix.language}}
    strategy:
      matrix:
        language: ${{ fromJSON(format('[{0}]', inputs.locales || "['en','it','fr','nl']")) }}
    uses: ./.github/workflows/_android_integration_tests_with_browserstack.yml
    with:
      env: {{inputs.env || 'test'}}
      testing_devices: {{inputs.testing_devices || 'Google Pixel 8' }}
      language: {{matrix.language}}
    secrets: inherit

So when its run manually, and no parameters provided, it will default to the values defined at top while defining inputs.

But when its executed in scheduled mode, the fallback will happen due to use of || operator for e.g. env will be test because of env: {{inputs.env || 'test'}}

References format function fromJson function

Other options can also be explored

Upvotes: 0

Joman68
Joman68

Reputation: 2850

inputs are available to workflows triggered by the workflow_dispatch event only (and to any workflows that are called by dispatched workflows).

When a workflow with inputs is triggered on a schedule (or on push/pull) all the input values are null. Any defaults that are set in the inputs section have no effect.

Therefore you need to set the defaults at the point where they are needed in the workflow. A convenient method for doing this uses Github expressions.

For string and choice inputs you can use the || expression operator to set the default value.

For boolean inputs that default to false you can use || expression to set the default value.

For boolean inputs that default to true you can use the contains() function to set the default value.

For example:

on:
  schedule:
    - cron: '15 0,18 * * 0-5'
  workflow_dispatch:
    inputs:
      springProfile:
        required: true
        type: choice
        options:
          - staging
          - production
      logLevel:
        required: true
        type: string
      isFalseWhenScheduled:
        required: true
        type: boolean
      isTrueWhenScheduled:
        required: true
        type: boolean



jobs:
  test:
    uses: ./.github/workflows/run-job-with-params.yml
    secrets: inherit
    with:
      springProfile: ${{ inputs.springProfile || 'staging' }}
      logLevel: ${{ inputs.logLevel || 'DEBUG' }}
      isFalseWhenScheduled: ${{ inputs.isFalseWhenScheduled || false }}
      isTrueWhenScheduled: ${{ !contains(inputs.isTrueWhenScheduled, 'false') }}

In the above example, if the workflow is triggered on schedule:

  • the springProfile parameter is set to 'staging'.
  • the logLevel parameter is set to 'DEBUG'.
  • the isFalseWhenScheduled parameter is set to false
  • the isTrueWhenScheduled parameter is set to true

If the job is triggered on workflow_dispatch: then the above parameters are set to the inputs: values.

Boolean value defaults

The contains function casts its first parameter to a string, and null is cast to the empty string ''. As mentioned, when triggered on schedule, inputs parameters are all set to null.

So:

Trigger method isTrueWhenScheduled value input value resolves to
workflow_dispatch true !contains('true', 'false') = true
workflow_dispatch false !contains('false', 'false') = false (*)
schedule null !contains('', 'false') = true

(*) This combination is what necessitates the use of contains. If contains is not used and you do ${{ inputs.isTrueWhenScheduled || true }} this will force this value to true even if it is set false in the workflow dispatch event.

And:

Trigger method isFalseWhenScheduled value input value resolves to
workflow_dispatch true true || false = true
workflow_dispatch false false || false = false
schedule null null || false = false

Upvotes: 38

GeorgesZ
GeorgesZ

Reputation: 199

Use an expression like this: ${{ toJSON(inputs) == '{}' && <defaultValue> || inputs.<inputName> }}.

WARNING: the <defaultValue> must be truthy, For boolean and number, use the string value, eg: 'true', 'false', '0', '1'.

If the default value cannot be truthy, eg: '' for an input of type string, reverse the expression, eg: ${{ toJSON(inputs) != '{}' && inputs.<inputName> || '' }}.

Upvotes: 0

oferei
oferei

Reputation: 1828

You can set an env variable with a default value:

env:
  typeOfTesting: ${{ github.event_name == 'schedule' && 'stage-test-local-All' || github.event.inputs.typeOfTesting }}

then use env.typeOfTesting instead of inputs.typeOfTesting.

Upvotes: 6

Free Ekanayaka
Free Ekanayaka

Reputation: 21

Here's another version that works with boolean inputs, and also supports setting the default to true:

name: Conditionally run a job

on:
  workflow_dispatch:
    inputs:
      should_run:
        description: "Whether the job should run"
        type: boolean
        default: true
schedule:
  - cron: '0 * * * *'

jobs:
  my-job:
    name: This job runs on schedule or if inputs.should_run is true
    runs-on: ubuntu-22.04
    if: ${{ !contains(inputs.should_run, 'false') }}
    steps:
    run: echo ok

This works as expected: the job always runs on schedule and when triggered manually it only runs if inputs.should_run is checked. That's because:

  • If the workflow is run on schedule, then inputs.should_run is null.
  • The contains function converts its argument to a string: null is converted to ''.

Upvotes: 2

Relsqui
Relsqui

Reputation: 29

Several comments have mentioned that other answers don't work for boolean inputs, so here's one that does.

name: Read a boolean input in a scheduled job

on:
  schedule:
    - cron: '0 * * * *'
  workflow_dispatch:
    inputs:
      human:
        description: Did a human start this workflow?
        type: boolean
        default: true

jobs:
  report-boolean:
    name: Report boolean state
    runs-on: ubuntu-latest
    env:
      BOOLEAN_STATE: ${{ !!(inputs.human) }}
    steps:
      - name: Output boolean
        run: echo "'${BOOLEAN_STATE}'"

Results:

  • I dispatch the workflow and leave the input box checked -> 'true'
  • I dispatch the workflow and uncheck the box -> 'false'
  • The schedule fires -> 'false'

If you want the variable to be true for the scheduled job, use one exclamation mark instead of two (${{ !inputs.whatever }}).

Upvotes: -2

ryanbmarx
ryanbmarx

Reputation: 23

Another option is to set a separate workflow that uses a curl POST to trigger the desired workflow via dispatch. That way you could set up a payload with whatever variables/context you need. It's less than ideal to have two workflows for one job, but it gives you access to the full set of inputs.

Upvotes: 0

user19089852
user19089852

Reputation: 281

Below code worked

name: WebDriverIO Automation
on:
  workflow_dispatch:
    inputs:
        typeOfTesting:
          type: choice
          description: Select Type of Test
          default: 'stage-test-local-All'
          required: true
          options: 
          - stage-test-local-All
          - stage-test
          - stage-test-local-Sanity
          - prod-test
    branches:
      - workingBranch
  schedule:
    - cron: "*/5 * * * *"

...
..
..
   - name: Test
        run: |
          if [ ${{ github.event.inputs.typeOfTesting }} != "" ]; then
            npm run ${{ github.event.inputs.typeOfTesting }} 
          else 
              npm run stage-test-local-All 
          fi

Upvotes: 0

Related Questions