GitHub Actions Triggers and Events
Every GitHub Actions workflow begins with a trigger, declared under the on: key in the workflow YAML file. A trigger is simply the condition under which GitHub decides to schedule a workflow run: a push to a branch, a pull request being opened, a tag being created, an issue being labeled, a cron schedule ticking over, or a human clicking a button. Understanding triggers deeply matters because the wrong trigger configuration is one of the most common causes of pipelines that either never run when they should, or run far too often and waste CI minutes. GitHub Actions supports dozens of webhook event types mirroring nearly everything that can happen inside a repository, plus a handful of trigger types that have nothing to do with repository activity at all.
Cricket analogy: A third umpire only reviews a decision when a specific condition is met — a batsman's referral, a run-out appeal, or a boundary check — and if that trigger criteria is set wrong, correct decisions never get reviewed, or every ball gets needlessly sent upstairs wasting time.
Webhook Events: push and pull_request
The two triggers you will use constantly are push and pull_request. A push event fires whenever commits land on a branch or tag that matches your filters, which makes it the natural trigger for build-and-deploy pipelines on protected branches like main. A pull_request event fires on actions like opening, synchronizing (new commits pushed to the PR branch), or reopening a PR, which makes it the natural trigger for validation pipelines — lint, test, security scan — that must pass before merge. A subtlety worth internalizing: workflows triggered by pull_request from a fork run with a read-only token and without access to repository secrets by default, a deliberate security boundary that prevents an untrusted fork from exfiltrating your secrets through a modified workflow file.
Cricket analogy: A team's 'match day' protocol only activates for an actual scheduled fixture on the main tour itinerary (like push to main), while a 'trial match' protocol activates for any invited team's practice game before it joins the official calendar (like pull_request) — and a visiting club's trial match gets no access to the home team's private strategy playbook, only a generic scouting report.
Raw event types are rarely specific enough on their own, so you can narrow a push or pull_request trigger with branches, branches-ignore, tags, tags-ignore, and paths / paths-ignore filters, evaluated as glob patterns. Path filters are especially valuable in monorepos: a workflow that only needs to run when files under backend/** change should filter on that path so an unrelated frontend commit does not burn CI minutes rebuilding a service that never changed. Note that paths filters apply only to push and pull_request events — they are silently ignored on other trigger types such as schedule.
Cricket analogy: A scouting department doesn't review every ball bowled in every net session — they filter specifically for deliveries in the death overs against left-arm pace, ignoring irrelevant drills, much like filtering a push trigger down to only commits touching backend/** so an unrelated frontend tweak doesn't burn analyst time.
Scheduled and manual triggers
The schedule trigger uses standard five-field POSIX cron syntax evaluated in UTC, letting you run nightly builds, weekly dependency audits, or periodic cleanup jobs independent of any code change. Scheduled workflows only run from the default branch and GitHub may delay them slightly during periods of high load, so schedule triggers should not be relied on for second-level precision. The workflow_dispatch trigger adds a manual 'Run workflow' button in the GitHub UI (and a matching API/CLI call), and it supports typed inputs — strings, booleans, choice lists — so operators can parameterize an ad hoc run, for example choosing which environment to deploy to without editing the workflow file.
Cricket analogy: A ground's automatic sprinkler system runs on a fixed nightly cron schedule regardless of that day's match result, and just as groundstaff know it might run a few minutes late during a power dip, no one relies on second-level precision — separately, the curator can hit a manual 'prepare pitch now' button with dropdown choices for pitch type to parameterize an ad hoc preparation.
name: CI
on:
push:
branches: [main]
paths:
- 'backend/**'
- '.github/workflows/ci.yml'
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
schedule:
- cron: '30 2 * * 1-5' # 02:30 UTC, Monday-Friday
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
type: choice
options: [staging, production]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run test suite
run: npm testThink of on: as a switchboard rather than a single wire: a single workflow file can legally listen for five or six unrelated event types at once, and GitHub evaluates each one independently. A push and a manually dispatched run of the same workflow can be in flight simultaneously, each with its own run ID, logs, and status check.
A common pitfall is forgetting that pull_request_target (unlike pull_request) runs in the context of the base branch and does have access to secrets — it exists for cases like commenting on PRs from forks, but using it carelessly to check out and execute untrusted fork code is a well-documented supply-chain vulnerability. Never mix pull_request_target with a checkout of the PR's head ref followed by a run step unless you fully understand the exposure. Every trigger also delivers a JSON event payload inspectable via the github.event context (e.g. github.event.pull_request.number), which combined with github.event_name lets a single workflow branch its behavior depending on which trigger fired it.
- Triggers are declared under
on:and can combine multiple unrelated event types in one workflow. pushandpull_requestare the two most common triggers; PRs from forks run with restricted, secret-free tokens by default.branches,tags, andpathsfilters narrow when push/pull_request workflows actually run;pathsfilters are ignored on non-push/PR events.scheduleuses UTC cron syntax and only fires from the default branch; timing is not guaranteed to the minute.workflow_dispatchenables manual, parameterized runs via typedinputsfrom the UI, CLI, or API.pull_request_targetgrants secret access and a base-branch context — treat it as a security-sensitive trigger, never checkout-and-run untrusted fork code with it.
Practice what you learned
1. Which trigger fires a workflow using the base repository's context and secrets even when the pull request comes from a fork?
2. What syntax does the `schedule` trigger use to define run times?
3. A workflow filters `push` events with `paths: ['backend/**']`. What happens on a `workflow_dispatch` run of the same workflow?
4. Which context object would you inspect inside a job to read the PR number that triggered the run?
5. Why do forked-repository pull requests run with a read-only, secret-free GITHUB_TOKEN by default?
Was this page helpful?
You May Also Like
GitHub Actions Workflow Basics
GitHub Actions workflows are YAML files in .github/workflows that define when a pipeline runs, what jobs it contains, and what steps each job executes.
Jobs, Steps, and Runners
Jobs are independent units of work that run on isolated runners, steps are the ordered commands within a job, and runners are the actual machines that execute them.
Reusable Workflows and Composite Actions
Compare GitHub Actions' two mechanisms for eliminating duplicated pipeline logic — reusable workflows called with `uses:` at the job level, and composite actions bundling multiple steps.
Pipeline Security Basics
CI/CD pipelines are a high-value attack surface with broad access to source, secrets, and production, so securing them requires trusted inputs, isolated execution, and verified artifacts.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsDocker & Kubernetes Study Notes
YAML · 40 topics