Course outline · 0% complete

0/29 lessons0%

Course overview →

GitHub Actions, decoded line by line

lesson 7-2 · ~12 min · 20/29

Your first workflow file

GitHub's built-in CI is GitHub Actions, enabled by committing a YAML file, the same format as compose in lesson 5-1, under .github/workflows/ in the repo. That is the entire setup, with no server to install.

name: ci
on:
  push:
    branches: [main]
  pull_request:
KeyMeaning
name: cithe label shown in the repo's Actions tab
on:the events that trigger this workflow
push: branches: [main]every push to main
pull_request:every pull request

When a trigger fires, GitHub boots a fresh virtual machine called a runner and executes the jobs on it.

A fresh machine on every run is the point. There is no leftover state and no works-on-my-runner, which solves the lesson 1-1 problem by brute force.

Jobs and steps

The rest of the file:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements.txt
      - run: pytest
KeyMeaning
jobs:one or more jobs, each on its own runner
runs-on: ubuntu-latestwhich kind of runner VM to use
steps:commands executed top to bottom
uses:a reusable action from the marketplace
with:parameters for an action
run:a plain shell command

Each step stops the job if it exits non-zero, exactly as lesson 7-1 described. actions/checkout@v4 is the essential one, cloning the repo onto the runner, and without it the runner is an empty machine.

That is the whole vocabulary: events, jobs, steps, uses for shared actions, and run for shell.

Why checkout comes first

- uses: actions/checkout@v4 is almost always the first step because the runner starts as an empty fresh machine, and checkout clones the repository onto it.

Every run gets a brand-new runner VM with no trace of the project on it, and checkout performs the git clone.

Step orderOutcome
checkout, then pytestworks
pytest, then checkoutfails, there are no files yet

Any step that needs the code, which is nearly all of them, must come after it. The failure mode when it is forgotten is confusing, because the error looks like a missing test file rather than a missing repository.

Where workflow files live

Workflow files live in .github/workflows/.

It is a hidden folder at the repo root, starting with a dot, with two levels: .github, then a folder named after what these files define. Any .yml file committed there becomes a workflow.

PathRole
.github/workflows/ci.ymla workflow
.github/workflows/release.ymlanother, independent workflow

This means CI configuration is version-controlled and code-reviewed like everything else, and a broken pipeline can be fixed with git revert. It also means a pull request can change the pipeline that tests it, which is worth remembering when reviewing.

A trigger filtered to one branch

With on: push: branches: [main], a push to a feature branch called new-login does not run the workflow. The trigger is filtered to pushes on main only.

The on: block is a filter, and push events on other branches do not match branches: [main].

EventMatches the filter
push to mainyes
push to new-loginno
pull request from new-loginonly if pull_request is listed

Teams usually add pull_request as a second trigger, as in this lesson's example, so feature branches still get tested through their pull requests. Without it, problems are only found after a merge, which defeats the purpose.