GitHub Actions basics
Automate anything with workflows: events trigger jobs on runners, and jobs run steps that call commands and reusable actions.
- Read and write a workflow file: events, jobs, runners and steps
- Choose triggers - push, pull_request, schedule, workflow_dispatch - and filter by branch and path
- Use marketplace actions with
uses, run commands withrun, and read expressions and logs
Dungeon Dash has a problem: people forget to run the tests, and broken code keeps landing on main. GitHub Actions fixes that by running automation for you whenever something happens in the repository.
A workflow is a YAML file in .github/workflows/. It has:
on- the events that trigger it: a push, a pull request, a schedule, a manual button...jobs- one or more jobs. Each runs on a fresh virtual machine, a runner (ubuntu-latest,windows-latest,macos-latest).steps- each job’s steps run in order: either a shell command (run) or a reusable action (uses).
1name: Tests
2
3on:
4 push:
5 branches: [main]
6 pull_request:
7
8jobs:
9 test:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v4 # get the repository's code
13 - uses: actions/setup-python@v5 # install Python
14 with:
15 python-version: "3.12"
16 - run: pip install -r requirements.txt
17 - run: pytest
18 - name: Say hello
19 run: echo "Tested ${{ github.repository }} at ${{ github.sha }}"Read it top to bottom: on every push to main and on every pull request, start an Ubuntu machine, check out the code, set up Python, install dependencies, and run the tests. If any step exits with an error, the job fails - and the pull request shows a red ✗.
uses: owner/repo@versionruns an action someone published (thousands are on the GitHub Marketplace).actions/checkoutis in nearly every workflow, because the runner starts empty.with:passes inputs to an action.${{ ... }}is an expression, filled in by GitHub before the step runs. Contexts likegithub(the event, repository, ref, actor...),env,secrets,matrixandrunnerhold the values.
Choosing triggers
| Event | Fires when | Typical use |
|---|---|---|
push | commits are pushed (filter with branches, tags, paths) | CI on main, deploys |
pull_request | a PR is opened, updated or reopened | CI on proposed changes |
schedule | on a cron timetable (in UTC) | nightly builds, stale-issue cleanup |
workflow_dispatch | someone clicks Run workflow (with optional inputs) | manual deploys and tools |
release | a release is published | building and uploading packages |
issues, issue_comment | issue activity | triage bots |
Branch and path filters use globs: * matches anything except /, and ** matches anything including / - so **/*.md matches Markdown files in any folder, including the top level. With paths-ignore, a push that only touches ignored paths (like documentation) skips the workflow.
1on:
2 push:
3 branches: [main, "release/**"]
4 paths-ignore: ["docs/**", "**/*.md"]
5 schedule:
6 - cron: "0 3 * * 1" # 03:00 UTC every Monday
7 workflow_dispatch:
8 inputs:
9 level:
10 description: "Which level to benchmark"
11 default: "1"Try it
Will the workflow run?
Using the filtered triggers above, decide whether each event starts the workflow.
“Push to main changing src/hero.py”
“Push to feature/co-op changing src/net.py”
“Push to release/1.5 changing src/save.py”
“Push to main changing only docs/guide.md and README.md”
“Push to main changing README.md and src/menu.py”
“Monday 03:00 UTC”
“Someone clicks Run workflow in the Actions tab”
Every run appears in the Actions tab with a log for each step - the first place to look when something fails. You can re-run failed jobs, and download logs and artifacts.
Actions minutes are free for public repositories; private repositories get a monthly allowance. Projects that need special hardware can register their own self-hosted runners.
Key takeaways
Workflows live in .github/workflows/*.yml:
onevents triggerjobs, which runstepson runners.runexecutes shell commands;usesruns a published action, configured withwith.${{ }}expressions read contexts like github, secrets and matrix.Filter triggers by branch and path with globs; logs for every step are in the Actions tab.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: automate GitHub chores with Python
Real GitHub work involves lots of small automation: matching CODEOWNERS, expanding build matrices, bumping versions, reading the API. Write those helpers in Python and run them against sample inputs - locally in your browser, with no GitHub account needed.
Will it trigger?
Implement a simplified trigger check. The input has the workflow’s filters, ---, then events. Filter lines look like push: main release/** (an event and its branch globs) and paths-ignore: docs/** **/*.md. Each event line is EVENT BRANCH FILE....
Print push main: runs or push main: skipped (reason) with reason event, branch or paths: the event must be listed, the branch must match one of its globs (* matches anything but /, ** anything including /, and **/ zero or more folders), and at least one changed file must not match a paths-ignore glob.
- Dungeon Dash triggers
- Single star
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Lint a workflow
The input is a workflow as JSON (the same structure as the YAML). Check it and print each problem on its own line, in this order, or no problems:
workflow: missing "on"if there’s noonkey- for each job, in order:
JOB: missing runs-on;JOB: needs unknown job X; and for each step (numbered from 1)JOB step N: has both uses and runorJOB step N: needs uses or run
- Several problems
- Clean
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…