CI with GitHub Actions · DevOps: Containers, CI and Kubernetes
How do teams test and deploy every change automatically?
Course contentsWhy you need it
Continuous integration (CI) runs the tests on every push and pull request, so a broken change is caught in minutes, not by a customer. Continuous delivery (CD) then deploys what passed. GitHub Actions is a common way to set this up, and its YAML files are something you'll read and edit in almost every project.
The intuition
A workflow lives in .github/workflows/ci.yml:
name: CI
on: # when it runs
push:
branches: [main]
pull_request:
jobs:
test: # a job runs on a fresh machine
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # a ready-made action
- run: pytest # a shell command
deploy:
needs: test # only after test succeeds
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
env:
TOKEN: ${{ secrets.DEPLOY_TOKEN }}- Jobs run in parallel unless
needssays one must wait for another. If a needed job fails, the waiting job is skipped. - Steps in a job run in order.
usesruns an action;runruns a command. - Secrets are stored in the repository settings and read with
${{ secrets.NAME }}. They are hidden in logs. Never write a token into the file itself: everyone who can read the repository can read it.
Definition
CI / CD
Continuous integration: test every change automatically. Continuous delivery/deployment: release what passed automatically.
Job
A list of steps that runs on its own fresh machine. Jobs run in parallel unless linked with needs.
Secret
A value stored in the repository settings and given to workflows as ${{ secrets.NAME }}, hidden from logs.
Examples
Test, then deploy
Run it in the lessonRun it to see the triggers and the job order.
name: CI
on:
push:
branches: [main]
pull_request:
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
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
env:
TOKEN: ${{ secrets.DEPLOY_TOKEN }}- L2Runs on pushes to main and on every pull request.
- L10Each job starts on an empty machine: first get the code.
- L13with: passes settings to an action. Quote versions so 3.10 doesn't become 3.1.
- L17deploy waits for test, and is skipped if test fails.
- L18Pull requests test, but only main deploys.
- L24The token comes from the repository's secret settings, not from this file.
Common mistakes
Deploying without needs
Without needs: test, deploy runs at the same time as the tests and ships even if they fail.
Tokens in the workflow file
Anyone who can read the repository (and its history, forever) can use it. Put it in secrets and rotate any token that was ever committed.
Unpinned versions
uses: some/action@main can change under you. Pin a version tag, and quote numbers like "3.10" in YAML.
Quick quiz
1. Two jobs, `lint` and `test`, have no `needs`. How do they run?
Show the answer
Answer: A
Jobs are parallel by default; needs creates the order.
2. Where should a deploy token go?
Show the answer
Answer: A
Secrets are encrypted, hidden in logs and not part of the code.
Practice
3 exercises in three steps: predict what a program prints, change a program to meet a new requirement, then write one from scratch. Your code runs in the browser and is checked the moment you submit.
- PredictWhich job runs when?
How do these five jobs run?
- ModifyA safer pipeline
Two problems:
deployruns even whentestfails, and the deploy token is written into the file. Makedeploywait fortest, and pass the token from the secretDEPLOY_TOKENas an environment variableTOKENinstead (the script reads$TOKEN, so the run line becomes just./deploy.sh). - WriteCI for a Node project
Write a workflow named
CIthat runs on pull requests and on pushes to main, with two jobs onubuntu-latest:test: check out the code (actions/checkout@v4), set up Node (actions/setup-node@v4withnode-version: "20"), then runnpm ciandnpm testbuild: only aftertest; check out the code, runnpm ci, thennpm run build
Practise this lesson
Open the interactive lesson to edit and run these examples and solve the exercises with instant feedback. Free to start, no sign-up.
Interactive lessons open in order. If you have not done the earlier ones yet, you start at the course map.
Terms in this lesson
| Term | Chinese | Definition |
|---|---|---|
| CI/CD | 持续集成/持续交付 | Test every change automatically, and release what passes. |
| GitHub Actions | GitHub Actions | GitHub's CI/CD service, configured with YAML workflows. |
| Secret (CI) | 密钥(CI) | A protected value given to workflows, hidden in logs. |