The following is a guide/cheatsheet on all the different flavors you can configure your GitHub Actions workflows to trigger on certain actions.
https://michaelcurrin.github.io/dev-cheatsheets/cheatsheets/ci-cd/github-actions/triggers.html
To set up a trigger for an event, we use the
on
field and one or more events.
See also GitHub’s docs - Events that trigger workflows.
Ordinary commits vs releases
Some advice:
- In general, if you have test, lint, and build steps, you will probably want to run them everytime. i.e. On all pushes to the main branch and on all PRs.
- If there is anything related to a deploy (like building a site) or a release (like bundling and uploading a JS/Python/Ruby package), you probably only want to run against the main branch (for production) and no other branches (as those are for development). And you could even restrict to only run against a tag or release created on the main branch, and not just any commit to the main branch.
Trigger on a commit
On push to any branch
This will build on the main branch and any feature branch, even without a PR.
on: push
On pull request
Trigger only with pull requests. See docs.
This will build on a feature branch, only if it has PR. So this gives more control, so you if a branch is work-in-progress and not ready for a PR, no runs happen.
Commits
This triggers every time you either push a commit to the feature branch or edit it on GitHub UI.
on: pull_request
on:
pull_request:
Limit to Pull Requests which target main
branch. This is safer and recommended, as you avoid triggering on PRs between feature branches other than the main one (in case you ever do that in a minority of cases).
on:
pull_request:
branches: main
PR events
Available event types are listed in the doc linked above.
Note: By default, a workflow only runs when a pull_request’s activity type is
opened
,synchronize
, orreopened
. To trigger workflows for more activity types, use the types keyword.
Add a trigger for when a PR is assigned.
on:
pull_request:
types: [assigned, opened, synchronize, reopened]
Restrict to when a PR against the main branch is merged. There is no merged
option, so use closed
. This closed event I think might be triggered when you close without merging.
This is similar to listening to push
event on master
, but it requires a PR to exist and does not pick up on just any commit to master
.
on:
pull_request:
branches: main
types: closed
On push or Pull Request to any branch
on: [push, pull_request]
Or
on:
- push
- pull_request
Or
on:
push:
pull_request:
On push to main or aPull Request to main
Runs on a PR again main but won’t run on a PR between two branches that both aren’t the main branch.
This is probably what you need for most use-cases and can copy as paste.
on:
push:
branches: main
pull_request:
branches: main
Or, more verbose using an array:
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
Or multi-line array:
on:
push:
branches:
- main
pull_request:
branches:
- main
Trigger on a schedule
Use the on.schedule parameter.
Check your syntax using crontab.guru site.
Here with a sample value to run at midnight daily.
on:
schedule:
- cron: "0 0 * * *"
Be sure to quote the value, in to prevent YAML expansion of globstars which would cause an error.
Include or ignore
From On push pull request paths in the docs.
Ignore a branch or tag
Note that if you use a rule from another section to include pushes to master and PRs to master, you won’t have to ignore automated commits to gh-pages
.
on:
push:
branches-ignore:
- foo
Ignore path
Trigger on any path except the ignored paths.
on:
push:
paths-ignore:
- "dir-name/**"
- "file.txt"
Or maybe just dir0name
without the stars?
Include path
Trigger only on changes in given paths. Note you don’t need **
- a single *
is enough to work at multiple levels.
Examples:
on:
push:
paths:
- "*.js"
- "*.css"
on:
push:
paths:
- src
Ignore markdown changes
Triggered on a commit or push to your main branch or any branch with a Pull Request. Ignore changes to markdown files at all levels (such as README.md
and in docs
).
main.yml
on: push: branches: main paths-ignore: - "*.md" pull_request: branches: main paths-ignore: - "*.md"
Ignore doc changes
More explicit - trigger on markdown changes but not doc-related changes.
Similar to above but still watches for changes in markdown files outside the docs directory. Such as if you have a static site with markdown content in the root of the repo.
main.yml
on: push: branches: main paths-ignore: - "docs/**" - README.md pull_request: branches: main paths-ignore: - "docs/**" - README.md
Trigger on tag
Specify a tag rule under on.push.tags
.
Use a regex pattern - this must be set.
on:
push:
tags:
- 'v*'
You can make a advanced rule that only triggers on v1
and up or excludes -alpha
releases, if that matters to you.
Trigger on a push to main
or a tag.
on:
push:
branches:
- main
tags:
Trigger on a push to main
and a tag.
on:
push:
branches:
- main
tags:
jobs:
build-deploy:
if: startsWith(github.ref, 'refs/tags/')
steps:
# ...
There is no on.tag
or on.tags
option, but there is on.release
- see below.
Trigger on a release
Trigger your workflow when you create a release under Releases section of your repo - note that a release is not the same as a tag.
From the docs:
Note: The release event is not triggered for draft releases.
So presumably it is safe to use created
. Perhaps that only runs once, while a release could be published, unpublished and published (I’ve seen a release unpublished, i.e. moved to drafts, by deleting its tag).
on:
release:
types: created
Here is one I found which covers more events.
on:
release:
types: [published, created, edited]
Types available:
published
unpublished
created
edited
deleted
prereleased
released
Trigger on a GH Pages build
on:
page_build:
Note that even if you use GA to build your static site to the gh-pages
branch, if GH Pages is enabled then GH will also do an additional build of that branch. But since it just contains assets and HTML and no Jekyll config, the build will be super simple. This flow of Jekyll doing two builds is seamless and so you won’t even notice it but the point here is that the page build trigger can still be useful.
Multiple triggers in one workflow
Add multiple triggers. Here we run on push to master, PR to master and on a nightly cron job.
on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: "0 0 * * *"
Depending on how you set up the jobs section, you can have them depend on each other or run in parallel.
You can add “checks” in your branch rules so that a PR can only merge to master after all checks pass
Multiple workflow files
You might split out to two workflow files such as one with a push trigger and app testing job and another with a release trigger and page build job, as below. To only build the site when creating a tag. This means you build less frequently but more safely and deliberately from a tag. This is especially useful if there are multiple people working on your project and comitting merging to master.
build.yml
on: push: branches: - master pull_request: branches: - master jobs: build: # Installs # Linting and unit tests. # Build the app or static site so any errors come up, but don't persist the result.
deploy.yml
release: types: - created jobs: deploy: # Build static site or docs site or publish to NPM etc. # ...
Manual triggers
See Manual events in the docs.
There are two formats available.
See also inputs docs in the docs.
Workflow dispatch
Trigger a workflow on a button click.
To trigger specific workflows in a repository, use the
workflow_dispatch event
.
If you set up this option, then you’ll get a button on the Actions tab to click and so run the workflow directly. Without a commit needed and without having to wait for a cron trigger.
You can even specify text inputs so that you get prompted to fill those in and have them used in the job.
Syntax:
on: workflow_dispatch
Or
on:
workflow_dispatch:
inputs:
my-title:
description: # ...
required: # true or false
default: # ...
# ...
The default is the value that is shown in the pop-up.
Basic trigger and job example:
main.yml
name: Manually triggered workflow on: workflow_dispatch: inputs: name: description: 'Person to greet' required: true default: 'Mona the Octocat' home: description: 'location' required: false default: 'The Octoverse' perform_deploy: required: true type: boolean jobs: say-hello: runs-on: ubuntu-latest steps: - name: Greet run: | echo "Hello, ${{ inputs.name }}!" echo "- in ${{ inputs.home }}!" - name: Deploy if: ${{ inputs.perform_deploy }} run: ./build.sh
An example suggested by GH Actions, when making new workflow file.
main.yml
name: Manual workflow on: workflow_dispatch: inputs: name: # Friendly description to show in the UI instead of 'name' description: 'Person to greet' required: true default: 'World' jobs: greet: runs-on: ubuntu-latest steps: - name: Send greeting run: echo "Hello ${{ inputs.name }}"
Repo dispatch
To trigger more than one workflow in a repository and create custom events and event types, use the
repository_dispatch
event.
on:
repository_dispatch:
types: [opened, deleted]