Workflow Event
A workflow event is the repository activity that starts a GitHub Actions run: push, pull_request, schedule, or workflow_dispatch. How each one is declared.
A workflow event is the repository activity that starts a GitHub Actions workflow run, such as a push, activity on a pull_request, a schedule tick, or a manual workflow_dispatch. Every run is started by exactly one event, declared in the workflow's on key and readable inside a job as github.event_name.
The event decides three things at once: whether a run happens at all, which commit the run checks out, and what data the workflow can read without calling the API. Most confusion about workflows that never trigger, or trigger twice, traces back to one of those three.
Definition
An event is a signal GitHub emits when something happens in or around a repository. GitHub Actions listens for those signals and starts a workflow run when the signal matches the workflow's on key. The full list of events is published in GitHub's events reference, checked on 2026-08-13, and it covers more than thirty names ranging from push and issues to merge_group and registry_package.
Events fall into four groups by where the signal comes from.
Repository activity. Someone pushes commits, opens a pull request, publishes a release, or comments on an issue. These are the same signals GitHub sends to webhooks, and the payload shape is identical.
Time. The schedule event fires from a POSIX cron expression evaluated in UTC. The shortest interval GitHub accepts is once every five minutes, scheduled runs always take the latest commit on the default branch, and the event can be delayed during periods of high load, with the start of every hour named as a busy window.
Manual and external triggers. workflow_dispatch starts a run from the GitHub UI, the REST API, or the GitHub CLI, and it can declare typed inputs with defaults. repository_dispatch starts a run from a POST to the repository dispatch endpoint, which is how a system outside GitHub asks for a build.
Other workflows. workflow_call makes a workflow reusable by another workflow, and workflow_run starts a workflow when a named workflow finishes.
Filters narrow an event
Declaring an event subscribes a workflow to every occurrence of it. Filters cut that down, and the filters available differ by event.
| Event | What starts it | Filters it accepts |
|---|---|---|
push | commits pushed to a branch or a tag | branches, branches-ignore, tags, tags-ignore, paths, paths-ignore |
pull_request | activity on a pull request in the repository | types, branches, branches-ignore, paths, paths-ignore |
schedule | a POSIX cron expression, evaluated in UTC | none |
workflow_dispatch | a manual run from the UI, API, or CLI | none; it takes inputs instead |
workflow_call | another workflow calling this one | none; it takes inputs and secrets |
workflow_run | a named workflow completing | workflows, types, branches, branches-ignore |
release | release activity such as published | types |
repository_dispatch | a POST to the repository dispatch endpoint | types |
Activity types deserve their own note. A pull_request event has many activity types, and a workflow that lists the event with no types key runs only on opened, synchronize, and reopened. A workflow that needs to react when a pull request is labeled or closed has to say so explicitly.
Two rules that surprise people
A schedule or workflow_dispatch trigger has to be declared on the default branch before GitHub recognizes it at all. A block added only on a topic branch stays invisible in the Actions tab until that branch merges, with no error to explain why. Once the trigger exists, a scheduled run always executes the default branch's version of the file. A manual run can target any branch or tag instead, and it executes that chosen ref's version of the file.
Runs started with the built-in GITHUB_TOKEN do not start further runs. A step that pushes a commit or opens a pull request using that token emits the event, and Actions ignores it, which prevents a workflow from triggering itself in a loop.
Example
This workflow subscribes to two events with different filters. The push trigger is limited to main and ignores documentation-only changes, and the pull_request trigger covers pull requests targeting main.
name: build
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '**.md'
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "event=${{ github.event_name }} ref=${{ github.ref }}"
- run: make build
- name: Publish
if: github.event_name == 'push'
run: make publishBoth events run the same three build steps. The Publish step carries an if condition on github.event_name, so it runs on the merge to main and is skipped on every pull request run. That is the usual reason a workflow reads the event name at all.
The two events also hand the job different values. The table below lists what the github context exposes for four common events, checked on 2026-08-13.
| Context value | push to main | pull_request opened from feature/login | schedule | workflow_dispatch |
|---|---|---|---|---|
github.event_name | push | pull_request | schedule | workflow_dispatch |
github.ref | refs/heads/main | refs/pull/42/merge | default branch ref | the ref chosen for the run |
github.sha | the pushed commit | the last merge commit on the merge ref | latest commit on the default branch | head commit of the chosen ref |
github.head_ref | empty | feature/login | empty | empty |
github.base_ref | empty | main | empty | empty |
github.event | the push payload | the pull request payload | the schedule payload | the dispatch payload with inputs |
The github.sha row is the one that changes behavior. On a pull request, actions/checkout lands on a merge commit of the source branch and the target branch, so the build tests the merged result rather than the branch tip. A step that stamps a version from github.sha therefore records a commit that exists only for that run.
Adding a schedule and a manual trigger to the same file needs no change to the jobs:
on:
push:
branches: [main]
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
inputs:
suite:
description: Test suite to run
type: choice
options: [smoke, full]
default: smokeThe cron field is UTC, so 0 3 * * * is 03:00 UTC every day and shifts against local time when daylight saving changes. The workflow_dispatch inputs appear as a form in the Actions tab and are readable as github.event.inputs.suite or through the inputs context. A scheduled run leaves those inputs unset, so any step that reads them needs a default.
Related Terms
- workflow_dispatch, the manual trigger and its inputs: the input types, where a dispatch run can be started from, and the default branch rule.
- How to run GitHub Actions jobs on a schedule: cron syntax, UTC handling, and the delay behavior of scheduled runs.
- Setting up nightly builds in GitHub Actions: a schedule-driven workflow end to end, including how to keep it from running on forks.
- GitHub events reference: the full event list with payloads and activity types.
- WarpBuild cloud runners documentation: the runner labels a
runs-onkey can name once an event has started a run. - WarpBuild pricing: per minute rates by runner type.
FAQ
What is a workflow event in GitHub Actions?
A workflow event is the repository activity that starts a workflow run. Common events are a push to a branch or tag, activity on a pull request, a schedule tick from a cron expression, and a manual workflow_dispatch. The events a workflow accepts are declared in its on key, and the event that started a given run is readable at run time as github.event_name.
Can one workflow respond to more than one event?
Yes. The on key accepts a list or a mapping of several events, and each one can carry its own filters. A workflow can declare push, pull_request, schedule, and workflow_dispatch together. Every run still has exactly one triggering event, so steps that need to behave differently branch on github.event_name.
Where do I see which event started a run?
The run summary page names the event, and inside a job the value is available as github.event_name. The full webhook payload for that event sits in the github.event object, so a step can read github.event.pull_request.number or github.event.head_commit.message without calling the API.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.