Running the right workflow at the right time saves minutes and keeps deploys from firing on the wrong branch.
The on key lists events, optionally with filters.
pushandpull_requestacceptbranches,tagsandpathsfilters (and-ignorevariants). Forpull_requestthe branch filter matches the target branch, sobranches: [main]means "PRs into main".pull_requesthas activitytypes; the default isopened,synchronize(new commits) andreopened.scheduletakes cron expressions in UTC, minimum every 5 minutes, and runs on the default branch only. Scheduled runs can start late under load.workflow_dispatchadds a Run workflow button (and API/CLI trigger) with optional typedinputs, read asinputs.name.- Others include
release,workflow_run(after another workflow finishes),issuesandrepository_dispatchfor external webhooks.
Glob patterns in filters use * (no slash) and ** (any depth). When both branches and paths are given, both must match.
A pull_request run checks out a temporary merge commit of the PR into the base branch, so tests see what main would look like after merging. Workflows triggered by pull requests from forks get a read-only token and no secrets, which is a deliberate safety measure.
Example
on:
push:
branches: [main, "release/**"]
paths: ["src/**", "package.json"]
pull_request:
branches: [main] # PRs targeting main
schedule:
- cron: "30 2 * * 1" # Mondays 02:30 UTC
workflow_dispatch:
inputs:
environment:
type: choice
options: [staging, production]
default: staging
jobs:
show:
runs-on: ubuntu-latest
steps:
- run: echo "event=${{ github.event_name }} env=${{ inputs.environment }}" Remember
- push/pull_request filter on branches, tags and paths
- Cron schedules are UTC and run on the default branch
- workflow_dispatch adds a manual button with typed inputs
Watch out for
- Expecting a schedule in a feature branch's workflow file to run: only the default branch's copy is used.