GitHub Actions: CI/CD Workflows From First Run to Secure Deployments · GitHub Actions Workflows: Triggers, CI and Matrices

Triggers and Filters: Choosing When Workflows Run

Control which pushes, pull requests, schedules and manual runs start a workflow, using branch, tag and path filters.

Create a free account to save this page, take notes and track your progress. Sign in

What you'll build

A workflow that runs tests on pushes to main, on pull requests, nightly, and on demand, while ignoring changes that only touch documentation.

The idea

Running every workflow on every event wastes minutes and clutters pull requests, so on: supports filters:

  • push / pull_request with branches, tags and paths (and their -ignore forms).
  • schedule with a cron expression, always evaluated in UTC.
  • workflow_dispatch adds a Run workflow button and can define typed inputs.
  • release, issues, workflow_call and many more.

Filters combine with AND: a push must match the branch filter and the path filter. For pull requests, branches refers to the target branch. Paths use glob patterns such as src/** and !docs/**.

The code

Push, pull request, schedule and manual triggers
name: CI
on:
  push:
    branches: [main]
    paths-ignore:
      - "docs/**"
      - "**.md"
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 3 * * *"          # every night at 03:00 UTC
  workflow_dispatch:
    inputs:
      debug:
        description: Print extra diagnostics
        type: boolean
        default: false

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run the tests
        run: echo "Running tests (debug=${{ inputs.debug }})"

Output

actionlint: no problems found
workflow: CI
triggers: push (branches: main), pull_request (branches: main), schedule (cron '0 3 * * *'), workflow_dispatch
jobs, in the order they run:
  test: runs on ubuntu-latest | 2 step(s)

Run this on your computer — see “Get Started” for setup.

Common mistakes

  • Using paths and paths-ignore together for the same event. GitHub allows only one of them per event; use ! patterns inside paths instead.
  • Thinking schedule uses your time zone. It is UTC, and it only runs from the default branch.
  • Required checks skipped by path filters. If a required status check never runs because of a path filter, the pull request waits forever. Use a lightweight always-running job for required checks.
  • Expecting pull_request to run for a branch conflict. A pull request with merge conflicts does not start pull_request workflows.

Key points

  • on: selects events; branches, tags and paths filter them.
  • Cron schedules are UTC and run on the default branch.
  • workflow_dispatch gives a manual button and typed inputs.
  • Filters on one event are combined with AND. Further reading: GitHub Docs.

Practice questions

A push to a feature branch changes only `README.md`. Does the workflow above run?

Answer

No. The push trigger is limited to the main branch, and Markdown files are ignored. Only pushes to main that change something other than docs or Markdown start it.

Why can a path filter block a pull request from merging?

Answer

If a required status check's workflow is skipped by a path filter, the check never reports a result and stays pending, so the pull request can't satisfy the branch protection rule.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?