Triggers
The on: block answers one question: what starts this
workflow? Pick the event that matches the job.
The big four
on: push
Every push to any branch. The default workhorse — run the tests, always.
on:
pull_request:
branches: [main]
When a PR targets main (opened, updated, reopened). This is the
gatekeeper pattern — see Pull Request
Workflows.
on:
schedule:
- cron: "0 9 * * *"
On a timer — cron syntax, in UTC. 0 9 * * * is 9:00 AM UTC
daily. For nightly builds, dependency checks, price watches, the
"is the site still up?" probe.
on: workflow_dispatch
A manual "Run workflow" button in the Actions tab. Add inputs for parameters:
on:
workflow_dispatch:
inputs:
environment:
description: "Where to deploy"
required: true
default: "staging"
Check (validated): all four parse as valid trigger blocks.
Combining and filtering
on:
push:
branches: [main]
paths:
- "src/**"
Only pushes to main that touch src/. Docs-only edits skip the
test run — paths filtering saves real CI minutes.
on:
pull_request:
types: [opened, synchronize, reopened]
React only to specific PR activity. (The defaults already cover
the sane cases; reach for types when the defaults do something
you don't want.)
Tags and releases
on:
push:
tags: ["v*"]
Runs when you push a tag like v1.2.3 — the classic "cut a
release" trigger. Pair with a deploy job and tagging becomes
shipping (see Deployments).
The trigger cheat sheet
| I want... | Use |
|---|---|
| Test every change | on: push |
| Gatekeep merges | on: pull_request |
| Nightly/scheduled work | on: schedule (cron, UTC!) |
| Manual runs with options | on: workflow_dispatch |
| Ship on version tags | on: push: tags: ["v*"] |
| Skip docs-only churn | paths: filter |
Careful: scheduled workflows on a quiet repo get disabled after 60 days of no activity — GitHub pauses the cron. A push wakes it back up.
Next: Jobs, Steps, and Runners