GitHub Actions can be triggered by a surprisingly diverse set of events, not just the obvious push to a branch.

Let’s see this in action. Imagine you have a workflow file named .github/workflows/build.yml.

name: Build and Test

on:
  push:
    branches:
      - main
      - 'release/**'
    tags:
      - 'v*'
  pull_request:
    branches:
      - main
  workflow_dispatch: # Allows manual triggering
    inputs:
      environment:
        description: 'Environment to build for'
        required: true
        default: 'staging'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

This workflow is configured to run on three primary event types: push, pull_request, and workflow_dispatch.

The push event is the most common. Here, we’re specifically telling it to run when code is pushed to the main branch, or any branch that starts with release/ (like release/v1.0). We’re also triggering on tags that start with v (e.g., v1.2.3). This is perfect for deploying production releases.

The pull_request event is crucial for CI/CD. This workflow will execute whenever a pull request targeting the main branch is opened, synchronized (new commits pushed), or reopened. This allows you to run tests and checks before merging code, catching issues early.

The workflow_dispatch event is a bit of a hidden gem. It enables manual triggering of your workflows directly from the GitHub UI. You can even define inputs for these manual runs, like specifying an environment to deploy to. This is incredibly useful for ad-hoc deployments or re-running a workflow with different parameters.

Beyond these, GitHub Actions can be triggered by a host of other events. You can trigger on issue_comment (e.g., if someone comments /deploy on an issue), schedule (cron jobs for nightly builds), release (when a new GitHub release is published), and many more. Each event has specific webhook payloads and context you can access within your workflow.

The on: key in your workflow file is where you define these triggers. You can specify multiple events, and even add conditions to individual event triggers. For instance, you might only want a push to main to trigger a deployment, while a push to a feature branch only triggers tests.

The actions/checkout@v3 action is almost always the first step. It checks out your repository’s code so subsequent steps can interact with it. The uses: actions/setup-node@v3 is an example of a pre-built action that configures your runtime environment.

When a pull_request event triggers the workflow, the github.event.pull_request context is populated with details about the PR, such as the head and base branches, the author, and titles. For a push event, you get github.event.ref and github.event.before/github.event.after to understand the commit range.

The specific mechanics of how these events translate into workflow runs involve GitHub’s webhook system. When an event occurs in your repository, GitHub sends a webhook notification to its Actions runner infrastructure. This infrastructure then interprets the event, matches it against your workflow trigger configurations, and schedules a job run on an appropriate runner.

One detail that often trips people up is how tag creation is handled. Pushing a new tag that matches a pattern in your on: push: tags: configuration will trigger the workflow. However, creating a release through the GitHub UI also creates a tag, and this release event is distinct from a simple push to a tag. If you want to trigger specifically on published releases (which implies a tag has been created and a release description filled out), you’d add release: to your on: block, not rely solely on push: tags:.

The next logical step after mastering basic event triggers is understanding how to conditionally run jobs or steps within a workflow based on the event context.

Want structured learning?

Take the full Github-actions course →