GitHub Actions Tutorial — Triggers Exercises
Practice Exercises — Triggers & Events
Test your understanding of triggers, filtering, and event chaining with these hands-on exercises.
Exercise 1 — Path Filtering for a Monorepo
Task: You have a monorepo with this structure:
frontend/
backend/
docs/
shared/
Create two workflow files:
frontend-ci.yml— runsnpm testinfrontend/only whenfrontend/**orshared/**files changebackend-ci.yml— runs./gradlew testinbackend/only whenbackend/**orshared/**files change
Both should trigger on push to main and pull requests to main.
Show Solution
frontend-ci.yml:
name: Frontend CI
on:
push:
branches: [main]
paths:
- 'frontend/**'
- 'shared/**'
pull_request:
branches: [main]
paths:
- 'frontend/**'
- 'shared/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd frontend && npm ci && npm test
backend-ci.yml:
name: Backend CI
on:
push:
branches: [main]
paths:
- 'backend/**'
- 'shared/**'
pull_request:
branches: [main]
paths:
- 'backend/**'
- 'shared/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd backend && ./gradlew test
Exercise 2 — Nightly Build with Conditional Steps
Task: Create a workflow that:
- Runs on push to
mainAND on a nightly schedule (2am UTC) - Always runs unit tests
- Runs end-to-end tests only during the nightly run (not on push)
Show Solution
name: CI + Nightly
on:
push:
branches: [main]
schedule:
- cron: '0 2 * * *'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Unit tests
run: npm test
- name: E2E tests (nightly only)
if: github.event_name == 'schedule'
run: npm run test:e2e
The if: github.event_name == 'schedule' condition ensures E2E tests only run during scheduled (nightly) executions.
Exercise 3 — Release Pipeline
Task: Create a workflow that:
- Triggers when a GitHub release is published
- Prints the release tag name and release notes
- Only runs the deploy step if the release is NOT a pre-release
Show Solution
name: Release Deploy
on:
release:
types: [published]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Release info
run: |
echo "Tag: ${{ github.event.release.tag_name }}"
echo "Pre-release: ${{ github.event.release.prerelease }}"
echo "Notes: ${{ github.event.release.body }}"
- name: Deploy to production
if: github.event.release.prerelease == false
run: echo "Deploying ${{ github.event.release.tag_name }} to production"
- name: Deploy to staging
if: github.event.release.prerelease == true
run: echo "Deploying ${{ github.event.release.tag_name }} to staging"
Exercise 4 — Workflow Chain
Task: Create two workflow files:
build.yml— Triggers on push tomain, runsecho "Build complete"deploy.yml— Triggers whenbuild.ymlcompletes successfully, runsecho "Deploying..."
Make sure deploy does NOT run if build fails.
Show Solution
build.yml:
name: Build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Build complete"
deploy.yml:
name: Deploy
on:
workflow_run:
workflows: ["Build"]
types: [completed]
branches: [main]
jobs:
deploy:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- run: echo "Deploying..."
The if condition checks that Build completed successfully before deploying. The workflows: ["Build"] must match the name: in build.yml exactly.
Exercise 5 — Comprehensive Trigger Design
Task: Design the trigger configuration (just the on: section) for a workflow that:
- Runs on pushes to
mainanddevelop - Runs on pull requests targeting
main - Ignores changes to
docs/**and**.mdfiles - Can be triggered manually with a
reasoninput - Runs nightly at 3am UTC on weekdays only
Show Solution
on:
push:
branches: [main, develop]
paths-ignore:
- 'docs/**'
- '**.md'
pull_request:
branches: [main]
paths-ignore:
- 'docs/**'
- '**.md'
schedule:
- cron: '0 3 * * 1-5' # 3am UTC, Mon-Fri
workflow_dispatch:
inputs:
reason:
description: 'Reason for manual trigger'
required: false
type: string
This combines all four trigger types. The paths-ignore applies to both push and pull_request. The schedule uses 1-5 for weekdays (Mon–Fri). The manual trigger accepts an optional reason input.
← Back to: Chapter 3: Triggers
Next Chapter: Chapter 4: Jobs & Runners →