CI with GitHub Actions
The Node CI workflow you already know
Section titled “The Node CI workflow you already know”If you have set up GitHub Actions for a TypeScript project, the pattern is: checkout → setup-node → install → lint → type-check → test. Python CI follows the exact same four-step logic, with Python-specific action names and tool invocations.
Side-by-side: Node vs Python CI workflow
Section titled “Side-by-side: Node vs Python CI workflow”# .github/workflows/ci.yml (Node / TypeScript)name: CI
on: push: branches: [main, dev] pull_request: branches: [main]
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Node uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- name: Install dependencies run: npm ci
- name: Lint run: npx eslint src/ --max-warnings 0
- name: Type check run: npx tsc --noEmit
- name: Test run: npx jest --coverage# .github/workflows/ci.yml (Python)name: CI
on: push: branches: [main, dev] pull_request: branches: [main]
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Python uses: actions/setup-python@v5 with: python-version: '3.12' cache: 'pip'
- name: Install dependencies run: pip install -r requirements.txt
- name: Lint & format check (ruff) run: | ruff check . ruff format --check .
- name: Type check (mypy) run: mypy src/ --strict
- name: Test (pytest) run: pytest --tb=short -qThe full production Python CI workflow
Section titled “The full production Python CI workflow”Here is a more complete workflow with caching, coverage reporting, and matrix testing across multiple Python versions:
name: CI
on: push: branches: [main, dev] pull_request: branches: [main]
jobs: quality: name: Lint & Type Check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' cache: 'pip'
- name: Install dev dependencies run: | pip install --upgrade pip pip install -r requirements-dev.txt
- name: Lint with ruff run: ruff check . --output-format=github
- name: Check formatting with ruff run: ruff format --check .
- name: Type check with mypy run: mypy src/ --strict
test: name: Test (Python ${{ matrix.python-version }}) runs-on: ubuntu-latest strategy: matrix: python-version: ['3.11', '3.12']
steps: - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip'
- name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt pip install -r requirements-dev.txt
- name: Run tests with coverage run: pytest --cov=src --cov-report=xml --cov-fail-under=80 -v
- name: Upload coverage to Codecov uses: codecov/codecov-action@v4 with: file: ./coverage.xmlUsing uv for faster CI
Section titled “Using uv for faster CI”Replacing pip with uv in CI cuts install time from 30–90 seconds to 2–5 seconds on most projects:
- name: Install uv uses: astral-sh/setup-uv@v3 with: version: "latest"
- name: Install dependencies with uv run: uv sync --frozen # equivalent to npm ci — exact lockfile installPlayground note: GitHub Actions YAML files define workflows that run on GitHub’s servers — they cannot be demonstrated in a browser playground. Commit the
.github/workflows/ci.ymlfile to your repository and push to see it run.