Skip to content
Latchkey

CI workflow (wntrblm/nox)

The CI workflow from wntrblm/nox, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: wntrblm/nox.github/workflows/ci.ymlLicense Apache-2.0View source

What it does

This is the CI workflow from the wntrblm/nox repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: CI
on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:
    # allow manual runs on branches without a PR

env:
  FORCE_COLOR: "1"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions: {}

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        python-version:
          - "3.10"
          - "3.12"
          - "3.14"
          - "3.15"
        include:
          - os: ubuntu-22.04
            python-version: "3.11"
          - os: ubuntu-22.04
            python-version: "3.13"
          - os: macos-15-intel
            python-version: "3.12"
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up non-default Pythons
        uses: actions/setup-python@v6
        with:
          python-version: |
            3.10
            3.11
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Set up Miniconda
        uses: conda-incubator/setup-miniconda@v4
        if: matrix.python-version == '3.14'
        with:
          channels: conda-forge
          conda-remove-defaults: true
          conda-version: '26.5.2'
          activate-environment:
      - name: Install Nox-under-test (uv)
        run:  uv pip install --system .
      - name: Run tests on ${{ matrix.os }}
        run: nox --session "tests-${{ matrix.python-version }}" -- --durations=10
      - name: Run min-version tests on ${{ matrix.os }}
        run: nox --session minimums --force-python="${{ matrix.python-version }}" -- --durations=10
      - name: Run Conda tests
        if: matrix.python-version == '3.14'
        run: nox --session "conda_tests" -- --durations=5
      - name: Save coverage report
        uses: actions/upload-artifact@v7
        with:
          name: coverage-${{ github.job }}-${{ strategy.job-index }}
          path: .coverage.*
          include-hidden-files: true
          if-no-files-found: error

  # No uv CLI exists in any MSYS2 repo (the msys `uv` package only ships the
  # uv_build backend), so the uv backend is exercised via the standalone uv
  # binary from setup-uv
  msys2:
    runs-on: windows-latest
    continue-on-error: true
    defaults:
      run:
        shell: msys2 {0}
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - uses: msys2/setup-msys2@v2.32.0
        with:
          msystem: MINGW64
          update: true
          # Inherit the runner PATH so the standalone uv (added to GITHUB_PATH
          # by setup-uv, which runs after this step) is visible to MinGW Python
          path-type: inherit
          install: >-
            mingw-w64-x86_64-python
            mingw-w64-x86_64-python-pip
            mingw-w64-x86_64-python-virtualenv
            mingw-w64-x86_64-gcc
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run: python -m pip install .
      # Force virtualenv so the session venv stays a MinGW interpreter
      # (_IS_MINGW=True). uv stays on PATH, so the uv-backend tests still
      # build real uv venvs from within MinGW
      - name: Run tests under MinGW
        run: |
          pyver=$(python -c "import sys; print('{}.{}'.format(*sys.version_info))")
          echo "MSYS2 MinGW Python: $pyver"
          python -c "import shutil; print('uv discovered at:', shutil.which('uv'))"
          nox --session "tests-$pyver" --force-venv-backend virtualenv -- --durations=10
      - name: Save coverage report
        uses: actions/upload-artifact@v7
        with:
          name: coverage-${{ github.job }}
          path: .coverage.*
          include-hidden-files: true
          if-no-files-found: error

  coverage:
    needs: [build, msys2]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run:  uv pip install --system .
      - name: Download individual coverage reports
        uses: actions/download-artifact@v8
        with:
          pattern: coverage-*
      - name: Display structure of downloaded files
        run: ls -aR
      - name: Run coverage
        run: nox --session "cover"

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"
      - name: Install Nox-under-test
        run: python -m pip install --disable-pip-version-check .
      - name: Lint
        run: nox --session "lint"

  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run:  uv pip install --system .
      - name: Docs
        run: nox --session "docs"

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: CI
on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:
    # allow manual runs on branches without a PR
 
env:
  FORCE_COLOR: "1"
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
permissions: {}
 
jobs:
  build:
    timeout-minutes: 30
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        python-version:
          - "3.10"
          - "3.12"
          - "3.14"
          - "3.15"
        include:
          - os: ubuntu-22.04
            python-version: "3.11"
          - os: ubuntu-22.04
            python-version: "3.13"
          - os: macos-15-intel
            python-version: "3.12"
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up non-default Pythons
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: |
            3.10
            3.11
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Set up Miniconda
        uses: conda-incubator/setup-miniconda@v4
        if: matrix.python-version == '3.14'
        with:
          channels: conda-forge
          conda-remove-defaults: true
          conda-version: '26.5.2'
          activate-environment:
      - name: Install Nox-under-test (uv)
        run:  uv pip install --system .
      - name: Run tests on ${{ matrix.os }}
        run: nox --session "tests-${{ matrix.python-version }}" -- --durations=10
      - name: Run min-version tests on ${{ matrix.os }}
        run: nox --session minimums --force-python="${{ matrix.python-version }}" -- --durations=10
      - name: Run Conda tests
        if: matrix.python-version == '3.14'
        run: nox --session "conda_tests" -- --durations=5
      - name: Save coverage report
        uses: actions/upload-artifact@v7
        with:
          name: coverage-${{ github.job }}-${{ strategy.job-index }}
          path: .coverage.*
          include-hidden-files: true
          if-no-files-found: error
 
  # No uv CLI exists in any MSYS2 repo (the msys `uv` package only ships the
  # uv_build backend), so the uv backend is exercised via the standalone uv
  # binary from setup-uv
  msys2:
    timeout-minutes: 30
    runs-on: windows-latest
    continue-on-error: true
    defaults:
      run:
        shell: msys2 {0}
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - uses: msys2/setup-msys2@v2.32.0
        with:
          msystem: MINGW64
          update: true
          # Inherit the runner PATH so the standalone uv (added to GITHUB_PATH
          # by setup-uv, which runs after this step) is visible to MinGW Python
          path-type: inherit
          install: >-
            mingw-w64-x86_64-python
            mingw-w64-x86_64-python-pip
            mingw-w64-x86_64-python-virtualenv
            mingw-w64-x86_64-gcc
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run: python -m pip install .
      # Force virtualenv so the session venv stays a MinGW interpreter
      # (_IS_MINGW=True). uv stays on PATH, so the uv-backend tests still
      # build real uv venvs from within MinGW
      - name: Run tests under MinGW
        run: |
          pyver=$(python -c "import sys; print('{}.{}'.format(*sys.version_info))")
          echo "MSYS2 MinGW Python: $pyver"
          python -c "import shutil; print('uv discovered at:', shutil.which('uv'))"
          nox --session "tests-$pyver" --force-venv-backend virtualenv -- --durations=10
      - name: Save coverage report
        uses: actions/upload-artifact@v7
        with:
          name: coverage-${{ github.job }}
          path: .coverage.*
          include-hidden-files: true
          if-no-files-found: error
 
  coverage:
    timeout-minutes: 30
    needs: [build, msys2]
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: "3.12"
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run:  uv pip install --system .
      - name: Download individual coverage reports
        uses: actions/download-artifact@v8
        with:
          pattern: coverage-*
      - name: Display structure of downloaded files
        run: ls -aR
      - name: Run coverage
        run: nox --session "cover"
 
  lint:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: "3.12"
      - name: Install Nox-under-test
        run: python -m pip install --disable-pip-version-check .
      - name: Lint
        run: nox --session "lint"
 
  docs:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v7.0.0
        with:
          persist-credentials: false
      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: "3.12"
      - name: Setup uv
        uses: astral-sh/setup-uv@v8.2.0
      - name: Install Nox-under-test
        run:  uv pip install --system .
      - name: Docs
        run: nox --session "docs"
 

What changed

3 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 5 jobs (16 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow