# CI/CD Automatically run tests, linting, and deployment on every push — catch problems before they reach users. ## Tools | Platform | Trigger | Self-hosted runner | |---|---|---| | GitHub Actions | push, PR, schedule | yes | | GitLab CI | push, MR, schedule | yes | | Gitea Actions | push, PR | yes | | Jenkins | any (webhook/poll) | yes | CI/CD is a platform-level choice, not a language one. The pipeline calls your existing `invoke`/`make` tasks. ## Key Concepts - **CI (Continuous Integration)** — run tests on every commit; fail fast - **CD (Continuous Delivery/Deployment)** — automatically ship passing builds - **Pipeline as code** — the config lives in the repo (`*.yml`), versioned alongside the code - **Local CI first** — Docker-based local runs before pushing; remote CI is the final net, not the primary feedback loop ## GitHub Actions — Minimal Python Pipeline ```yaml # .github/workflows/ci.yml name: CI on: [push, 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 uv && uv pip install --system -e ".[dev]" - run: ruff check . - run: mypy . - run: pytest ``` ## GitLab CI — Equivalent ```yaml # .gitlab-ci.yml image: python:3.12-slim test: script: - pip install uv && uv pip install -e ".[dev]" - ruff check . - mypy . - pytest ``` ## Tips - Keep pipelines fast — slow CI gets ignored - Cache dependency installs (e.g. `actions/cache` on `~/.cache/uv`) - Use matrix builds to test across Python/Node versions when it matters