1. CI Stage Overview
- Source Control Trigger: Every push or pull request starts the pipeline.
- Environment Setup: Create isolated Python environment, install dependencies.
- Static Analysis / Formatting: Run
rufforflake8,black, andisort. - Unit & Integration Tests: Execute
pytest(with coverage reporting). - Build Artifacts: Package Python code into wheels/containers.
- Report & Feedback: Publish results (badges, PR annotations) and block merges on failures.
Illustrate each stage with a swimlane diagram showing automated progression and feedback loops to developers.
2. Python Tooling Stack
- Environment:
pyenv,venv, ortoxto guarantee reproducible runs. - Linting:
ruff,flake8,pylintcatch style and bug risks. - Formatting:
blackensures consistent code style. - Type Checking:
mypyenforces type annotations, helpful for large teams. - Testing:
pytestwith plugins (pytest-cov,pytest-xdistfor parallelism). - Packaging:
buildorpoetry buildcreate wheel/sdist artifacts. - Security:
bandit,pip-auditand dependency pinning viapip-tools.
Compare alternatives (e.g., nox vs tox) and discuss when each fits.
3. Sample Repository Structure
sample_python_app/
├── app/
│ ├── __init__.py
│ └── api.py
├── tests/
│ └── test_api.py
├── pyproject.toml
├── tox.ini
├── requirements.txt
└── .github/workflows/ci.yml
Discuss how separating app and tests encourages modular design; pyproject.toml centralizes metadata.
4. Example: pyproject.toml
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "sample-python-app"
version = "0.1.0"
description = "Teaching app for CI/CD workflows"
requires-python = ">=3.11"
dependencies = [
"fastapi",
"uvicorn",
]
[tool.black]
line-length = 88
[tool.pytest.ini_options]
minversion = "7.0"
addopts = "-ra -q --cov=app --cov-report=xml"
testpaths = ["tests"]
Walk through how metadata powers packaging, while tool sections encode CI defaults.
5. Example: tox.ini
[tox]
envlist = lint,py311
isolated_build = true
[testenv]
deps = -r requirements.txt
commands =
pytest
[testenv:lint]
deps =
ruff
black
mypy
commands =
ruff check app tests
black --check app tests
mypy app
Explain how tox orchestrates multiple environments locally and in CI, providing parity with developer workflows.
6. Example: GitHub Actions CI Workflow
name: CI
on:
pull_request:
push:
branches: [ main ]
jobs:
lint-test-build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Static analysis
run: tox -e lint
- name: Test suite
run: tox -e py311
- name: Build artifacts
run: python -m build
- name: Upload wheel
uses: actions/upload-artifact@v4
with:
name: dist-wheels
path: dist/*.whl
Break down each step, emphasizing caching and matrix builds for compatibility.
7. Metrics and Observability in CI
- Track build duration and queue time to spot scaling issues.
- Monitor flaky test rate; quarantine or fix quickly.
- Surface coverage trends and lint violations to dashboards.
- Integrate PR annotations (GitHub checks, Reviewdog, Danger) for faster feedback.
8. Classroom Exercises
- Lab: Students fork the sample repo, add a failing test, observe pipeline failure, then fix.
- Challenge: Configure caching in GitHub Actions to speed up dependency installs.
- Extension: Add
pip-auditto the pipeline and remediate a vulnerable dependency.
9. Instructor Tips
- Demonstrate failing vs passing run screens via recorded demo if live pipeline isn’t available.
- Reinforce best practice of keeping pipelines under 10 minutes for fast feedback.
- Encourage students to run
toxlocally before pushing to mimic CI behavior.