Module 09 / Project 04 — CI with GitHub Actions¶
Home: README
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | — | — | Flashcards | — | — |
Focus¶
Creating a GitHub Actions workflow that lints, tests, and builds a Docker image on every push.
Why this project exists¶
Continuous Integration (CI) catches bugs before they reach production. Instead of relying on developers to remember to run tests, a CI pipeline runs them automatically on every push. If linting fails, tests fail, or the Docker build breaks, GitHub marks the commit with a red X. This project teaches you to write a GitHub Actions workflow from scratch.
Run¶
Run the app and tests locally first¶
cd projects/modules/09-docker-deployment/04-ci-github-actions
# Run the app
python app.py
# In another terminal, run tests
pytest tests/ -v
# Run the linter
ruff check .
Trigger the CI pipeline¶
The GitHub Actions workflow runs automatically when you push this code to a GitHub repository:
- Create a repository on GitHub (or use an existing one).
- Push this project's code to the repository.
- Go to the "Actions" tab on GitHub to see the pipeline run.
The pipeline runs three jobs in sequence:
If any job fails, the remaining jobs are skipped.
View results on GitHub¶
- Go to your repository on GitHub.
- Click the Actions tab.
- Click on the latest workflow run to see each job's output.
- Green checkmarks mean success. Red X marks mean failure.
Expected output¶
Local test output¶
tests/test_app.py::test_read_root PASSED
tests/test_app.py::test_health_check PASSED
tests/test_app.py::test_add PASSED
tests/test_app.py::test_add_invalid_input PASSED
tests/test_app.py::test_greet PASSED
tests/test_app.py::test_greet_uppercase PASSED
GitHub Actions¶
The Actions tab shows three jobs: "lint", "test", and "build", each with a green checkmark.
Alter it¶
- Add a new
GET /multiply/{a}/{b}endpoint and a corresponding test. Push and verify the CI passes. - Add a step to the "test" job that prints the Python version:
run: python --version. - Change the workflow to only run on pushes to the
mainbranch (modify theon.push.branchesfield).
Break it¶
- Introduce a deliberate ruff lint error: add an unused import (
import os) toapp.py. Push and watch the lint job fail. - Change the expected value in
test_addso the assertion fails. Push and watch the test job fail. Does the build job still run? - Add an invalid instruction to the Dockerfile (e.g.,
RUN nonexistent_command). Push and watch the build job fail.
Fix it¶
- Remove the unused import. The lint job should pass again.
- Restore the correct assertion. The test job should pass.
- Remove the invalid Dockerfile instruction. The build job should pass.
Explain it¶
- What triggers the CI workflow? Where is this configured?
- What does
needs: lintdo in the test job? What happens if you remove it? - Why does the workflow install Python with
actions/setup-pythoninstead of using the pre-installed version? - Why does the build job only build the Docker image without pushing it to a registry?
Mastery check¶
You can move on when you can:
- write a basic GitHub Actions workflow from scratch,
- explain the relationship between jobs, steps, and actions,
- describe what
needsdoes and how it controls execution order, - interpret the Actions tab on GitHub to diagnose a failed pipeline.
Related Concepts¶
Next¶
Continue to 05-production-config.