A fail-fast quality gate
Change check_lint to return True, "clean" and run again: every check passes and the exit code becomes 0.
Checks that depend on people remembering them get forgotten. A pre-commit hook runs formatting and linting before every commit, and a GitHub Actions workflow runs tests, lint and type checks on every push, on several Python versions, before code can merge.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write a .pre-commit-config.yaml that runs the Ruff lint and format hooks plus the standard trailing-whitespace hook, and parse it with PyYAML to print the hook ids.
Write a workflow jobs section as a Python string with a test job and a matrix of two operating systems and two Python versions, and print how many jobs the matrix produces.
Write a function run_pipeline(checks) that runs named checks in order, stops at the first failure and returns the exit code.
Explain it without notes
What is a pre-commit hook, and why is it not enough on its own?
Walk through a GitHub Actions workflow for a Python project.
What is a build matrix and when do you use it?
Why should CI tests for an AI application not call the real model?
How do you make CI results mandatory for merging?
Expected output
[PASS] format: all files already formatted
[FAIL] lint: main.py:4: F401 'os' imported but unused
fail fast: stopping, later checks are skipped
skipped: ['types', 'tests']
exit code: 1