Manual Triggers and Inputs
A plain workflow_dispatch button is useful, but a button with fields next to it is where manual triggers actually start pulling their weight. Instead of a workflow that always does the same fixed thing, inputs let the person clicking “Run workflow” decide things at run time — which environment to deploy to, whether to skip tests, what version to roll back to. This is what turns a static automation script into an actual tool.
Defining Inputs
Inputs are declared under workflow_dispatch.inputs, each with a type, an optional description, a default, and whether it’s required.
name: Manual Inputs Demo
on:
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
type: choice
options:
- staging
- production
default: staging
skip-tests:
description: 'Skip the test suite'
type: boolean
default: false
release-notes:
description: 'Short release note'
type: string
required: false
jobs:
announce:
runs-on: ubuntu-latest
steps:
- run: |
echo "Deploying to: ${{ inputs.environment }}"
echo "Skip tests: ${{ inputs.skip-tests }}"
echo "Notes: ${{ inputs.release-notes }}"Let’s take a small portion to learn to read:
...
inputs:
environment:
description: 'Target environment'
type: choice
options:
- staging
- production
default: staging- The input is given
environmentas it’s uniquie identifier (give it any). environmentaccepts inputs of type (kind of data type)choicewhere user will be provided twooptionsto choose from namelystagingandprodductionwhiledefaulting tostaging.descriptionis just a description for reference or to understand what this input is for.
Set it up:
mkdir gha-inputs-demo && cd gha-inputs-demo
git init
mkdir -p .github/workflows
cat > .github/workflows/manual-inputs.yml << 'EOF'
name: Manual Inputs Demo
on:
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
type: choice
options:
- staging
- production
default: staging
skip-tests:
description: 'Skip the test suite'
type: boolean
default: false
release-notes:
description: 'Short release note'
type: string
required: false
jobs:
announce:
runs-on: ubuntu-latest
steps:
- run: |
echo "Deploying to: ${{ inputs.environment }}"
echo "Skip tests: ${{ inputs.skip-tests }}"
echo "Notes: ${{ inputs.release-notes }}"
EOF
git add .
git commit -m "Add manual inputs demo workflow"
git branch -M mainPush this to GitHub and open the “Run workflow” panel — instead of a bare button, you’ll now see a dropdown for environment, a checkbox for skip-tests, and a free-text box for release-notes. This UI is generated entirely from the YAML; you never touch anything but the workflow file to define it.
Input Types
| Type | UI Element | Notes |
|---|---|---|
string | Text box | Default type if omitted |
boolean | Checkbox | Accessed as true/false string in expressions |
choice | Dropdown | Requires an options list; value is always one of those strings |
environment | Dropdown of configured GitHub Environments | Ties into environment protection rules and secrets |
Note
Even boolean and choice inputs are passed through as strings when the workflow actually runs — there’s no true boolean type at execution time. ${{ inputs.skip-tests }} evaluates to the literal string "true" or "false", which matters if you’re doing strict comparisons later.
Using Inputs In Conditionals
Inputs become genuinely useful once they control workflow behavior, not just get echoed.
jobs:
test:
if: ${{ inputs.skip-tests == false }}
runs-on: ubuntu-latest
steps:
- run: echo "Running tests..."
deploy:
needs: test
if: ${{ always() && !failure() }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to ${{ inputs.environment }}"This job-level if skips the entire test job when the checkbox is ticked. The full mechanics of if: conditionals and expressions get their own dedicated treatment shortly — for now, notice how naturally an input flows straight into a decision about what runs. Don’t try yet because it might confuse you, we will look into if after few chapters.
Required Inputs
Marking an input required: true without a default forces the person triggering the workflow to supply a value before it can run — the “Run workflow” button stays disabled until every required field is filled.
inputs:
version:
description: 'Version to roll back to'
type: string
required: trueUse this for anything genuinely dangerous to leave blank — a rollback target, a destructive cleanup scope — where a silently-applied default could cause real damage.
Triggering With Inputs From The CLI
The GitHub UI isn’t the only way to fire workflow_dispatch. The gh CLI and the REST API can trigger it too, passing inputs as key-value pairs — this is how other automation (a chatbot, a separate pipeline, a cron job outside GitHub) can kick off a workflow programmatically.
gh workflow run manual-inputs.yml \
-f environment=production \
-f skip-tests=false \
-f release-notes="Hotfix for login bug"This requires the gh CLI to be authenticated against your repository — install and log in with gh auth login if you haven’t already.
How Real DevOps Engineers Use This
Manual-trigger inputs are the backbone of self-service deploy tooling. Instead of engineers running deploy scripts from their laptop with locally-stored AWS credentials, teams expose a workflow_dispatch workflow with an environment choice input and a version string input, restrict who can trigger it using repository permissions, and let people deploy through a controlled, logged, auditable UI instead of an SSH session. Every run shows up in the Actions history with exactly who triggered it and what values they chose — which is a meaningfully better audit trail than “someone ran a script somewhere.”
The environment input type specifically is worth calling out: when it’s tied to a configured GitHub Environment (not just a choice dropdown of the string “production”), it can enforce required reviewers before a job proceeds — meaning a workflow_dispatch targeting production can require a second person to approve the run before it executes. That’s a real safety mechanism, not just cosmetic.
Clean up:
cd .. && rm -rf gha-inputs-demoTip
If you find yourself duplicating almost-identical workflows for staging and production, inputs are usually the fix — one workflow, one environment choice input, and conditionals or an input-driven variable deciding the target instead of two nearly-copy-pasted files.