[GitHub Actions] Rest in Peace, Manual Deployment — GitHub Actions Has Arrived - 3. How to Run GitHub Actions. Events
[GitHub Actions] Rest in Peace, Manual Deployment — GitHub Actions Has Arrived - 3. How to Run GitHub Actions. Events
To use a CI/CD pipeline, you need an appropriate point at which to trigger it.
It shouldn't run every single time there's a code change — code that's still under development or hasn't been fully verified could end up going through the pipeline.
So it's necessary to determine the appropriate trigger point depending on the environment, and that's where GitHub Actions' Events come in.
Events let you specify various script trigger events — when a branch, tag, or file change is detected, when a specific time arrives, and so on. Depending on the configuration, a wide variety of events can be applied.
This post covers what each event does, how to use it, and examples.
Let's look at the commonly used events in GitHub Actions. You can run a script whenever a change is detected at the desired time, in the desired place.
Triggering uses on, and the desired event is described under that keyword.
You can check the types of triggers at GitHub Docs' Events that trigger workflows.
Here's how to trigger an event for a simple single action.
YAML
# Run an event when a push happens on: push ## Run an event when a PR action happens on: pull_request
Specify the target event as shown above. This lets you run GitHub Actions at the point you want, such as when a commit is pushed to a branch, or when a PR is opened.
Here's how to trigger events for simple multiple actions.
YAML
# Run an event on push or PR actions on: [ push, pull_request ]
Specify the desired events in array form.
Some events offer an activity types option. This breaks down the possible behaviors of an event further, and can be used when you want GitHub Actions to run only on a specific activity within a specific event.
YAML
# Run an event when a PR is created, edited, or closed on: pull_request: types: - opened - edited - closed
For example, the PR event pull_request can have various activities such as opened (PR created), edited (PR edited), closed (PR closed), and so on.
You can trigger GitHub Actions only for a specific activity among these, such as PR creation. If, as in the earlier example, you don't specify any activity for pull_request, it runs on every activity.
Check GitHub Docs - Pull Request for all activity types of pull_request.
You can apply filters to an event to filter its behavior. Filter types include various items such as branch name, tag name, and files.
Multiple filters can be applied, and glob patterns can be used. For example, release/** matches any branch name starting with release/.
You can apply a filter to specific branches so events only run on the branches you want.
The script below includes only the specified branches as trigger targets.
YAML
# Run an event when pushing to a target branch on: push: branches: - main - features/231024 - 'release/**'
The branches that qualify as event targets are as follows.
- The main branch
- The features/231024 branch
- Every branch starting with release/
- release/development
- release/test
- release/development/231024
The script below excludes only the specified branches from trigger targets.
YAML
# Run an event when pushing to a branch that isn't a target branch on: push: branches-ignore: - test - 'feature/**-temp' # You can also express this using the glob pattern's negation operator ! on: push: branches: - '!test' - '!feature/**-temp
The branches excluded from event targets are as follows.
- The test branch
- Every branch starting with feature/ and ending with -temp
- feature/alpha-test-temp
- feature/textarea-temp
- feature/java/code-temp
A ! prefix on a string means negation (NOT) in a glob pattern.
You can mix include/exclude branch filters as shown below.
YAML
# When the branch matches the condition below on: push: branches: - 'release/**' - '!release/**-test' # The filter above is equivalent to the one below. on: push: branches: - 'release/**' branches-ignore: - 'release/**-test'
The branches that qualify as event targets are as follows.
- Every branch starting with release/ that doesn't end with -test
As shown in the two scripts above, you can either use ! in a glob pattern to express it all at once, or mix branches and branches-ignore. Pick whichever is more convenient for you.
GitHub lets you manage configuration by creating tags. In addition to branches, you can also apply filters to tags to run events.
Tag filters use tags and tags-ignore, and work very similarly to branch filters.
The script below includes only the specified tags as trigger targets.
YAML
# Run an event when pushing to a target tag on: push: tags: - v1.0.2 - 'v2*'
The tags that qualify as event targets are as follows.
- The v1.0.2 tag
- Tags starting with v2
- v2.1.0
- v2.3.1-alpha
The script below excludes only the specified tags from trigger targets.
YAML
# Run an event when pushing to a tag that isn't a target tag on: push: tags-ignore: - v1.0.0 - 'v0*' - 'v**-alpha' # You can also express this using the glob pattern's negation operator ! on: push: tags: - '!v1.0.0' - '!v0*' - '!v**-alpha'
The branches excluded from event targets are as follows.
- The v1.0.0 tag
- Every tag starting with v0
- v2.1.0
- v2.3.1-alpha
- Every tag starting with v and ending with -alpha
- v3.0.1-alpha
- v1.0.5-a460b53c-alpha
The script below excludes only the specified tags from trigger targets.
YAML
# When the tag matches the condition below on: push: tags: - 'v*' - '!v**-test' # The filter above is equivalent to the one below. on: push: tags: - 'v*' tags-ignore: - 'v**-test'
The tags that qualify as event targets are as follows.
- Every tag starting with v
- Every tag starting with v that doesn't end with -test
In addition to Git branches or tags, you can also detect file additions/deletions in the source code path, or changes to a specific file, and run an event.
Similar to branch and tag filters, this uses the paths and paths-ignore keywords.
The script below includes only the specified paths as trigger targets.
YAML
# When pushing to a target path on: push: paths: - version.json - '**.tsx' - 'build/docs/**'
The paths that qualify as event targets are as follows.
- The version.json file
- Every tsx file
- src/apps/App.tsx
- src/components/Header.tsx
- template.tsx
- Every folder/file under the build/docs folder
- build/docs/index.html
- build/docs/images/favicon.ico
- build/docs/css/index.css
The script below excludes only the specified paths from trigger targets.
YAML
# Run an event when pushing to a path that isn't a target path on: push: paths-ignore: - hash.txt - 'test/**' - '**.md' # You can also express this using the glob pattern's negation operator ! on: push: paths: - '!hash.txt' - '!test/**' - '!**.md'
The paths excluded from event targets are as follows.
- The hash.txt file
- Every folder/file under the test folder
- test/index.json
- test/api-test.java
- test/assets/thumb.png
- Every md file
- README.md
- src/code/index.md
The script below excludes only the specified paths from trigger targets.
YAML
# When the path matches the condition below on: push: paths: - 'src/**' - '!src/generated/**' # The filter above is equivalent to the one below. on: push: paths: - 'src/**' paths-ignore: - 'src/generated/**'
The tags that qualify as event targets are as follows.
- Every folder/file under src that isn't under src/generated
All the filters mentioned above only trigger an event when a specific action occurs on a specific element. This is a passive structure that only runs when the user does something to the repository.
Fortunately, GitHub Actions lets you use crontab to run an event on a specified schedule even without any change to the repository.
YAML
on: schedule: # Run the event at 00:00 every Monday through Friday - cron: '0 0 * * 1-5'
This uses the cron keyword. The schedule above runs the event at 00:00 every day from Monday(1) through Friday(5).
Here's a brief overview of crontab configuration.
TXT
* * * * * minute (0-59) hour (0-23) day (1-31) month (1-12) day of week (0-7)
Everything else is intuitive, but the day of week is a bit ambiguous, so here it is.
| Day of week | Number |
|---|---|
| Sunday | 0 |
| Monday | 1 |
| Tuesday | 2 |
| Wednesday | 3 |
| Thursday | 4 |
| Friday | 5 |
| Saturday | 6 |
| Sunday | 7 |
You can also use commas (,), dashes (-), and slashes (/), for example like this.
BASH
# Run the event at 00:00, 06:00, 12:00, and 18:00 every day 0 0,6,12,18 * * * # Run the event on the hour, every hour, Monday through Friday 0 * * * 1-5 # Run the event every 3 hours, every day 0 */3 * * * # In March, June, September, December, run the event every 3 hours, Monday through Friday 0 */3 * 3,6,9,12 1-5
You can combine these elements and operators to specify complex schedules as well.
Use this as a basis for writing your crontab expression. Since this document isn't about crontab specifically, I'll leave it here.
We've looked at various event filters so far. Every one of them either requires doing something to a specific element, or waiting until a specific time. In other words, if you want to run an event whenever you want, you'd have to push even a meaningless commit just to trigger it.
If you or your environment are sensitive about Git history, that would be quite awkward.
Fortunately, GitHub Actions provides the workflow_dispatch keyword, which lets a user manually run it whenever they want. It even lets you specify input or select fields so you can directly enter the values you want!
The simplest form looks like this.
YAML
on: workflow_dispatch:
You can run it via the Run workflow button in the repository's Actions tab.
🖼️ How to run it
- Go to the repository's Actions tab.
- Click the target script from the left sidebar.
- Click Run workflow, select the branch you want to run it on, and run it.
- If input or select options are configured, they're added to that tab.
As mentioned earlier, you can take desired values as input and use them in the script. These fields can also have required set, letting you configure required values that must be entered when running it.
Use the inputs keyword, specify a variable name for each component, then set its options. When used in a script, you can call it by that variable name.
You can accept select-style input. You can choose one of a set of specified values.
YAML
workflow_dispatch: inputs: choice_component: description: 'Select a value' required: true default: 'level1' type: choice options: - level1 - level2 - level3
The name of the component above is choice_component.
| Tag | Content |
|---|---|
| description | Component title |
| required | Whether it's required |
| default | Default value |
| type | Component type |
| options | Array of selectable options |
You can accept checkbox-style input. You can select a value to enter a true or false value.
YAML
workflow_dispatch: inputs: check_component: description: 'True or False' required: true default: true type: boolean
The name of the component above is check_component.
| Tag | Content |
|---|---|
| description | Component title |
| required | Whether it's required |
| default | Default value |
| type | Component type |
You can accept input-style input. Both string and number are types where you enter an arbitrary value directly.
Not sure if this is intentional, but even when specifying the number type, string input is possible, and the string is displayed correctly in the script too. It's fine to consider them essentially no different.
This post uses string as the example; the number type can be used the same way.
YAML
workflow_dispatch: inputs: text_component: description: 'Enter a value here' required: true default: '' type: string
The name of the component above is text_component.
| Tag | Content |
|---|---|
| description | Component title |
| required | Whether it's required |
| default | Default value |
| type | Component type |
We haven't covered this yet, but you can call the values entered in the actual workflow like this.
YAML
- name: Run a multi-line script run: | echo ${{ inputs.choice_component }} echo ${{ inputs.check_component }} echo ${{ inputs.text_component }}
BASH
level1 true text
You can call it in a script using ${{ inputs.variable_name }}.
I originally intended to cover the usage of the entire script, but since Events and filters ended up taking more content than expected, I decided to just cover this part and move on.
As the content kept growing, it got quite tedious...
Most of this content is based on GitHub's official documentation. Refer to the two links below for more details.
Events triggering workflows document
As I was writing, the order felt off, so I moved this post to chapter 3, and moved the explanation of GitHub Actions' structure to chapter 2.