1. GitHub Actions: Your First Workflow
GitHub Actions runs scripts automatically in response to repo events — pushes,
pull requests, schedules and more. A workflow is a YAML file in
.github/workflows/; each one defines when it runs and what jobs to
execute:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm ci
- run: npm test
Commit and push this file, and GitHub picks it up automatically — check the
"Actions" tab on the repo to watch it run. uses: steps run a
reusable published action (like actions/checkout, which fetches your
repo's code onto the runner); run: steps execute a plain shell
command.
2. Workflow Triggers, Jobs & Matrix Builds
Workflows can respond to far more than pushes — issues, releases, a schedule, or a manual button click:
on:
schedule:
- cron: "0 3 * * *" # 3 AM UTC, every day
workflow_dispatch: # adds a manual "Run workflow" button
A matrix build runs the same job multiple times with different variables — the standard way to test against several language or OS versions in parallel:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
# This spins up THREE parallel jobs -- one per Node version.
3. Branch Protection & Required Checks
A workflow that merely runs isn't enough — it needs to actually block a
bad merge. In the repo's Settings → Branches → Branch protection
rules, add a rule for main:
- Require a pull request before merging — no more direct pushes to
main. - Require status checks to pass before merging — select your CI job (e.g.
test) by name; GitHub greys out the merge button until it succeeds. - Require approvals — at least one reviewer must approve before merge is allowed.
- Require branches to be up to date before merging — forces a rebase/merge with
mainfirst, so the tested code is actually what gets merged.
Everything from Weeks 1–4 — commits, branches, PRs, CI — only actually protects main once a branch protection rule makes the checks mandatory. Without it, a passing or failing check is just informational and can be merged past.
4. Releases, Tags & Changelogs
A GitHub Release wraps a tag (from Week 4) with release notes and optional built artifacts, giving users a clear "this is version X" page to look at:
git tag -a v1.0.0 -m "First stable release"
git push origin v1.0.0
gh release create v1.0.0 --title "v1.0.0" --generate-notes
# --generate-notes auto-builds a changelog from merged PRs since the last release
gh is the GitHub CLI — it wraps common GitHub
actions (PRs, issues, releases) as terminal commands, useful for scripting things
this course has otherwise done through the web UI. It's worth installing
alongside Git itself.
5. Capstone: Ship a CI Pipeline for a Real Repo
Bring every piece of this course together on one real repository — this is the project the whole 5 weeks has been building toward.
Automate and protect a small project, end to end
Use any small project (or start a fresh one) — a few dozen lines of code with a couple of automated tests is enough.
Requirements:
- Push the project to a new public GitHub repo with a clear README.
- Add a GitHub Actions workflow that installs dependencies and runs the tests on every push and pull request.
- Enable branch protection on
main: require a PR, require your CI job to pass, and require at least one review approval (self-approval is fine solo). - Open a feature branch with an intentionally failing test, push it, and open a PR — confirm the merge button is blocked by the failing check.
- Fix the test, push the fix to the same branch, and confirm the check turns green and the PR becomes mergeable.
- Merge the PR, then tag the resulting commit as
v1.0.0and publish a GitHub Release from it.
Branch → commit → push → PR → CI check → review → merge → tag → release. Every course elsewhere on this site assumes this loop as background knowledge — you've now actually built it once, end to end, yourself.
6. Bonus Exercise
Add a matrix build and a manual trigger
Extend your capstone workflow beyond the minimum requirements.
Requirements:
- Add
workflow_dispatchto your workflow'son:block so it can also be triggered manually from the Actions tab. - Add a
strategy.matrixthat runs your test job against at least two different runtime versions. - Confirm in the Actions tab that the matrix produces separate, parallel job runs.
7. Knowledge Check
Four quick questions. Expand each to check your answer.
Q1
Where do GitHub Actions workflow files live, and what format are they written in?
Where do GitHub Actions workflow files live, and what format are they written in?
In .github/workflows/ at the repo root, as YAML files. GitHub automatically discovers and runs any workflow file it finds there once it's committed and pushed — no separate registration step is needed.
Q2
A CI check is failing on a PR, but there's no branch protection rule set up. Can the PR still be merged?
A CI check is failing on a PR, but there's no branch protection rule set up. Can the PR still be merged?
Yes. A workflow running and reporting pass/fail is purely informational unless a branch protection rule explicitly marks that check as required. Without that rule, the merge button stays available regardless of whether checks are red or green.
Q3
What does a matrix build actually do?
What does a matrix build actually do?
It runs the same job multiple times in parallel, once per combination of values listed under strategy.matrix — commonly different language/runtime versions or operating systems — so you get separate pass/fail results for each combination instead of testing against only one environment.
Q4
What's the relationship between a Git tag and a GitHub Release?
What's the relationship between a Git tag and a GitHub Release?
A tag is a plain Git object marking a specific commit with a fixed name (e.g. v1.0.0) — it exists at the Git level with or without GitHub. A GitHub Release wraps a tag with a human-facing page: release notes, a changelog, and optional downloadable build artifacts, all built on top of that tag.