Skip to content
Français
CI/CD & Automatisation medium

GitHub Actions triggers: events and filters

35 min de lecture

Read this page in French

A workflow is useless if it does not fire at the right moment. The on key defines the events that start a workflow: a push, a pull request, a scheduled time, a manual click. Setting it well avoids useless runs, and missing ones.

What you will learn

  • Trigger a workflow on push and pull_request
  • Filter runs by branch, tag and file path
  • Schedule a workflow with schedule and cron syntax
  • Start a workflow by hand with workflow_dispatch and its inputs
  • Chain workflows with workflow_run
  • Combine several triggers in one file

The on key: what starts a workflow

Every workflow file begins with an on key listing the triggering events. GitHub watches the repository continuously: as soon as a listed event happens, it creates a run of the workflow. Without on, the workflow never fires.

A workflow can listen to a single event or several at once, each with its own filters.

push and pull_request: the everyday triggers

push and pull_request cover the vast majority of CI needs: validating the code on every push and on every proposed merge.

Reacting to pushes

The push event fires the workflow when commits land on the repository. The branches filter narrows it to the branches you care about:

on:
push:
branches:
- main

Without a branches filter, the workflow runs on every branch, including short-lived working branches, which burns minutes for nothing.

Reacting to pull requests

The pull_request event fires the workflow on pull requests targeting your repository. The types filter states which activities count:

on:
pull_request:
types: [opened, synchronize, reopened]

By default, pull_request already reacts to opened, synchronize and reopened; there is no need to repeat them unless you want to add or remove one. The most useful types beyond the default are labeled, closed and ready_for_review.

Filtering: branches, tags and paths

Filters avoid useless runs. There are three axes: the branch, the tag, and the file path that changed.

on:
push:
branches:
- main
- 'release/**'
paths:
- 'src/**'
- 'package.json'

The paths filter is valuable: it only starts the workflow when a relevant file has changed. There is no point rerunning the whole CI for a typo in a Markdown file. The inverse form, paths-ignore, excludes instead of including:

on:
push:
paths-ignore:
- 'docs/**'
- '**.md'

To react to the publication of a version, filter on tags:

on:
push:
tags:
- 'v*'

schedule: running a workflow periodically

The schedule event fires a workflow at regular intervals, through a cron expression. It is the tool for recurring tasks: a nightly security audit, a cleanup, a weekly report.

on:
schedule:
- cron: '0 6 * * 1' # Every Monday at 06:00 UTC

The five cron fields are minute, hour, day of month, month, and day of week. Two traps come up often:

  • the time is always in UTC, not your local timezone;
  • a scheduled workflow only runs from the repository's default branch.

GitHub does not run schedule events to the second: under load, the trigger can drift by several minutes.

workflow_dispatch: the manual trigger

The workflow_dispatch event adds a "Run workflow" button to the Actions tab. It is the trigger for deliberate operations: a deployment, a restore, an on-demand generation.

It accepts inputs, parameters the operator fills in at launch:

name: Manual deployment
on:
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
type: choice
options:
- staging
- production
version:
description: 'Version to deploy (tag)'
required: true
type: string
permissions: {}
jobs:
deploy:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: Check out the code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Deploy
env:
ENVIRONMENT: ${{ inputs.environment }}
VERSION: ${{ inputs.version }}
run: ./deploy.sh "$ENVIRONMENT" "$VERSION"

The type: choice enforces a closed list of values, so the operator cannot get it wrong. Inputs are read through the inputs context, passed here through an env: block: interpolating ${{ }} directly into a run: would open a command injection.

workflow_run: chaining workflows

The workflow_run event fires a workflow after another one finishes. It separates responsibilities, for example a build workflow, then a deployment workflow that consumes only the artifact produced.

on:
workflow_run:
workflows: ["CI"]
types: [completed]
branches: [main]

The workflows field references the other workflow by its name, not by its file name. The triggered workflow always runs from the default branch, and reaches the first one's result through the github.event.workflow_run context.

That decoupling is also a security pattern: it lets you handle untrusted code in a first workflow without secrets, then deploy in a second one. The detail is covered in Securing pull_request_target.

pull_request_target: the trigger to handle with care

The pull_request_target event looks like pull_request, but it runs in the context of the target repository, with access to the secrets, even for a pull request coming from a fork.

While you are getting started, stay on pull_request: it is safe by default, since it does not expose secrets to forks.

Combining several triggers

One workflow can listen to several events. That is common for a CI pipeline that has to run on pushes, on pull requests, and also on demand:

on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:

Inside the workflow, the github.event_name context says which event triggered the run. That is useful to adapt the behaviour, a subject covered in Conditions and if.

Key points

  • The on key defines the events that start a workflow; without it, nothing fires.
  • push and pull_request cover everyday CI; filter push by branches to avoid useless runs.
  • The paths, branches and tags filters target the runs; never mix a form with its inverse (paths / paths-ignore).
  • schedule plans in UTC cron, and only from the default branch.
  • workflow_dispatch adds a manual trigger with typed inputs (choice, string, boolean).
  • workflow_run chains workflows; pull_request_target is powerful but dangerous, to be used knowingly.

Next steps

Is this site useful to you?

Fewer than 1% of readers support this site.

I maintain more than 700 free guides, with no ads and no tracking. Any support, even a symbolic one, helps cover hosting and keeps these resources free. Thank you for the help.

The form does not show? Open Ko-fi in a new tab.

Subscribe and follow my DevSecOps work on LinkedIn