Events, Triggers, Filters, Schedules, Manual Runs, and Repository Dispatch: Configuration, Design Patterns, and Trade-Offs
Trigger design is policy design. A narrow trigger can save compute but remove visibility; a broad trigger can simplify required checks but create noisy runs. Manual and custom dispatch solve different trust problems, and schedules solve different orchestration problems from event-driven automation. This lesson turns those distinctions into explicit design choices.
Learning objectives
- Choose between trigger-level filters and job-level conditions based on visibility, required checks, and cost.
- Compare broad and narrow event subscriptions without confusing event activity with job execution.
-
Choose between
workflow_dispatch,repository_dispatch, andschedulebased on caller identity and dataflow. -
Reason about
pushversuspull_requestas different trust and revision contexts. - Document trigger decisions as governed interfaces with testable examples and rollback paths.
1. Trigger configuration is an interface contract
Every on block defines who or what may request
automation, what repository state is associated with the request,
and which events are silently ignored. That means trigger changes
deserve the same review discipline as API changes: identify callers,
accepted input shape, trust assumptions, expected side effects, and
how a breaking change will be detected.
2. Broad versus narrow triggers
| Design | Strength | Risk/trade-off | Good fit |
|---|---|---|---|
| Broad trigger | Consistent run/check visibility across changes | More runs and possible cost/noise | Required CI where every PR should show a result |
| Narrow trigger filters | Prevents irrelevant runs entirely | Can leave no run/check for unmatched changes | Independent optional automation or clearly scoped monorepo component |
Broad trigger + job if |
Run exists; expensive work can skip | More orchestration overhead; conditions need care | Required check plus selective heavy jobs |
There is no universal “optimize paths” rule. If branch protection requires a check that never appears because the workflow was filtered out, a compute optimization can become a merge-blocking reliability problem.
3. Branch filters and job conditions operate at different layers
# Trigger-level: may prevent run creation entirely
on:
push:
branches: [main]
paths: ['app/**']
# Job-level: run exists, but job can be skipped
jobs:
app-test:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
steps:
- run: echo 'test app'
Use trigger filters when the workflow itself is irrelevant. Use job conditions when the run is still valuable evidence but only some work should execute. Chapter 04 will go deeper into expression evaluation; this chapter stays focused on the selection boundary.
4. workflow_dispatch versus
repository_dispatch
| Question | workflow_dispatch |
repository_dispatch |
|---|---|---|
| Primary caller | Human or automation intentionally starting a named workflow | External system emitting a repository-level custom event |
| Input contract | Declared typed workflow inputs |
event_type + custom client_payload
|
| Ref choice | Caller can select a ref for the run after default-branch workflow presence requirement is met | Event context uses default branch ref/tip |
| Best fit | Operator-controlled maintenance/test/release request | External service says “event X happened” |
| Governance concern | Who may dispatch; input validation; selected ref | Who may call API; event-type contract; untrusted payload handling |
Do not use repository_dispatch merely because it sounds
more “API-like.” If the intent is “run this workflow with these
declared parameters,” workflow_dispatch provides a
clearer typed workflow contract.
5. Schedule versus external orchestration
Native schedules are excellent for repository-local periodic work that can tolerate GitHub Actions scheduling semantics. They are less suitable for hard real-time requirements, complex calendars spanning many systems, or workflows that must coordinate with external business state.
| Need | Prefer | Why |
|---|---|---|
| Nightly repo maintenance with minutes of timing tolerance | schedule |
Simple, versioned with workflow, no external scheduler. |
| Run after an external batch actually finishes |
repository_dispatch or purpose-built API call
|
Event expresses real completion rather than guessing clock time. |
| Cross-system calendar with strict SLA | External orchestrator | Central timing/retry/monitoring can own the contract. |
Scheduled workflows currently run from the latest default-branch commit. If your business requirement is “run version 1.4 every night even after main changes,” schedule alone does not express that immutable version policy.
6. Push versus pull request is also a trust decision
push to a protected branch generally represents code
that has already crossed repository review/merge policy. A
pull_request run may execute code proposed by a
contributor, including from a fork. Secrets and token behavior are
intentionally restricted in low-trust contexts. The trigger is
therefore not just “when”; it contributes to “who controls the code
being executed.”
pull_request_target simply to regain secrets or write
permissions. That event uses a trusted base context and requires
specialized threat modeling; Chapter 22 covers it in depth.
7. Design patterns that survive growth
-
Stable event contract: name custom
repository_dispatchevent types as versioned interfaces when external clients depend on them. - Visible required CI: prefer a broad PR trigger plus selective jobs when branch protection expects a consistent check.
-
Manual safety valve: use typed
workflow_dispatchinputs for operator-controlled retries or dry runs instead of editing workflow YAML for one-off behavior. - Clock tolerance: document that schedule time is approximate and avoid top-of-hour bursts when exact timing is unnecessary.
- Ref intent: state whether PR work should validate merge result, head SHA, or base branch and record that choice.
8. Worked decision table
| Scenario | Trigger design | Prerequisite/trust | Observable proof |
|---|---|---|---|
| Every PR must show a required CI result; docs changes need no tests | Broad pull_request; condition heavy jobs |
Untrusted PR-safe jobs only | Run exists for docs PR; heavy job skipped; required summary/check present |
| External QA service finishes a synthetic test |
repository_dispatch with named event type
|
Authorized API caller; payload treated as untrusted | Event type/payload fields + default-branch run ID |
| Maintainer wants an on-demand diagnostic on a selected branch | workflow_dispatch typed inputs |
Workflow present default branch; write-capable caller | Selected ref, typed input values, run ID |
| Weekday dependency report | schedule at off-peak minute |
Workflow on default branch; timing tolerance | Schedule string, event, default-branch SHA, actual start timestamp |
Knowledge check
When is a trigger-level path filter better than a job
if?
When the entire workflow is genuinely irrelevant for unmatched paths and you do not need a run/check for those changes.
Why is workflow_dispatch often clearer than
repository_dispatch for operator actions?
It exposes a named workflow with declared typed inputs and an explicit selected ref, matching the intent “run this workflow” rather than “emit a custom repository event.”
A nightly job must start within seconds of midnight. Is native
schedule a sufficient contract?
No. GitHub schedules can be delayed; use an external system designed for the required timing SLA if exactness matters.
Why is a PR trigger also a trust decision?
PR code can be controlled by less-trusted contributors or forks, which changes safe permissions, secrets, runner choices, and the consequences of executing proposed code.
What should you record when deliberately testing the PR head rather than the merge result?
Record the head SHA field used, the normal event merge SHA/ref, and the reason the head-only test answers the intended question.
Official references and version notes
- Events that trigger workflows — authoritative event-specific ref/SHA, default-branch, activity-type, schedule, and dispatch semantics.
- Triggering a workflow — branch/path filters, manual inputs, event configuration, and trigger examples.
-
Workflow syntax for GitHub Actions
— current
onsyntax, filter combination rules, schedule syntax, and manual input types. -
Contexts reference
— current
githubcontext fields and safe access patterns. -
Variables reference
— current meanings of
GITHUB_REF,GITHUB_SHA, event path, and run identity variables. - Troubleshooting workflows — current guidance for trigger conditions, default-branch requirements, merge-conflict behavior, and schedule delays.
- Secure use reference — current trust guidance for event-derived input and privileged workflow patterns.
- GITHUB_TOKEN concepts — current recursion behavior and low-trust workflow implications.
Version-sensitive trigger behavior was rechecked against current
primary GitHub documentation on 2026-09-09.
Executable labs use a disposable repository,
ubuntu-24.04, built-in shell steps only, and explicit
permissions: {} because no repository API mutation is
required from inside the workflow. At verification time,
workflow_dispatch, repository_dispatch,
and schedule require the workflow file to exist on
the default branch; scheduled workflows run from the latest
default-branch commit, support POSIX cron plus an optional IANA
timezone, and have a minimum five-minute interval but may be
delayed under load. GitHub is continuously delivered, so event
payload fields, limits, schedule behavior, and default-branch
rules must be rechecked before long-lived production use.
Plan/visibility differences can affect protected environments and
other later features, but the trigger-design exercises here
require only standard repository Actions functionality.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.