Skip to content
Latchkey

CI workflow (python-jsonschema/jsonschema)

The CI workflow from python-jsonschema/jsonschema, explained and optimized by Latchkey.

C

CI health: C - fair

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

Grade your own workflow free or run it on Latchkey →
Source: python-jsonschema/jsonschema.github/workflows/ci.ymlLicense MITView source

What it does

This is the CI workflow from the python-jsonschema/jsonschema repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

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

The workflow

workflow (.yml)
name: CI

on:
  push:
    branches-ignore:
      - "wip*"
    tags:
      - "v*"
  pull_request:
  schedule:
    # Daily at 3:21
    - cron: "21 3 * * *"
  workflow_dispatch:

permissions: {}

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  list:
    name: List nox sessions
    runs-on: ubuntu-latest
    outputs:
      noxenvs: ${{ steps.noxenvs-matrix.outputs.noxenvs }}
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          persist-credentials: false
      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]
      - id: noxenvs-matrix
        run: |
          echo >>$GITHUB_OUTPUT noxenvs=$(
            uvx nox --list-sessions --json | jq '[.[].session]'
          )

  ci:
    name: Test
    needs: list
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
        noxenv: ${{ fromJson(needs.list.outputs.noxenvs) }}
        posargs: [""]
        include:
          - os: ubuntu-latest
            noxenv: "tests-3.14(format)"
            posargs: coverage github
          - os: ubuntu-latest
            noxenv: "tests-3.14(no-extras)"
            posargs: coverage github
        exclude:
          - os: macos-latest
            noxenv: "docs(dirhtml)"
          - os: macos-latest
            noxenv: "docs(doctest)"
          - os: macos-latest
            noxenv: "docs(linkcheck)"
          - os: macos-latest
            noxenv: "docs(man)"
          - os: macos-latest
            noxenv: "docs(spelling)"
          - os: macos-latest
            noxenv: "docs(style)"
          - os: windows-latest
            noxenv: "docs(dirhtml)"
          - os: windows-latest
            noxenv: "docs(doctest)"
          - os: windows-latest
            noxenv: "docs(linkcheck)"
          - os: windows-latest
            noxenv: "docs(spelling)"
          - os: windows-latest
            noxenv: "docs(style)"
          - os: windows-latest
            noxenv: "tests-3.14(no-extras)"
          - os: windows-latest
            noxenv: "tests-3.14(format)"
          - os: windows-latest
            noxenv: "tests-3.14(format-nongpl)"
          - os: windows-latest
            noxenv: "tests-3.14t(no-extras)"
          - os: windows-latest
            noxenv: "tests-3.14t(format)"
          - os: windows-latest
            noxenv: "tests-3.14t(format-nongpl)"

    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          persist-credentials: false
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y libenchant-2-dev
        if: runner.os == 'Linux' && startsWith(matrix.noxenv, 'docs')
      - name: Install dependencies
        run: brew install enchant
        if: runner.os == 'macOS' && startsWith(matrix.noxenv, 'docs')
      - name: Set up Python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
        with:
          python-version: |
            3.10
            3.11
            3.12
            3.13
            3.14
            3.14t
            pypy-3.11-v7.3.22
          allow-prereleases: true
      - name: Enable UTF-8 on Windows
        run: echo "PYTHONUTF8=1" >> $env:GITHUB_ENV
        if: runner.os == 'Windows' && startsWith(matrix.noxenv, 'tests')

      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]

      - name: Run nox
        run: uvx nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }} # zizmor: ignore[template-injection]

  packaging:
    name: Build and publish
    needs: ci
    runs-on: ubuntu-latest
    environment:
      name: PyPI
      url: https://pypi.org/p/jsonschema

    permissions:
      contents: write  # for creating GitHub releases via `gh release create`
      id-token: write  # for trusted publishing to PyPI

    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]

      - name: Build our distributions
        run: uv run --frozen --with 'build[uv]' -m build --installer=uv

      - name: Publish to PyPI
        if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
        uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b
      - name: Create a GitHub Release
        if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
        env:
          GH_TOKEN: ${{ github.token }}
        run: gh release create "${GITHUB_REF_NAME}" dist/* --generate-notes

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-ignore:
      - "wip*"
    tags:
      - "v*"
  pull_request:
  schedule:
    # Daily at 3:21
    - cron: "21 3 * * *"
  workflow_dispatch:
 
permissions: {}
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
 
jobs:
  list:
    timeout-minutes: 30
    name: List nox sessions
    runs-on: latchkey-small
    outputs:
      noxenvs: ${{ steps.noxenvs-matrix.outputs.noxenvs }}
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          persist-credentials: false
      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]
      - id: noxenvs-matrix
        run: |
          echo >>$GITHUB_OUTPUT noxenvs=$(
            uvx nox --list-sessions --json | jq '[.[].session]'
          )
 
  ci:
    timeout-minutes: 30
    name: Test
    needs: list
    runs-on: ${{ matrix.os }}
 
    strategy:
      fail-fast: false
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]
        noxenv: ${{ fromJson(needs.list.outputs.noxenvs) }}
        posargs: [""]
        include:
          - os: ubuntu-latest
            noxenv: "tests-3.14(format)"
            posargs: coverage github
          - os: ubuntu-latest
            noxenv: "tests-3.14(no-extras)"
            posargs: coverage github
        exclude:
          - os: macos-latest
            noxenv: "docs(dirhtml)"
          - os: macos-latest
            noxenv: "docs(doctest)"
          - os: macos-latest
            noxenv: "docs(linkcheck)"
          - os: macos-latest
            noxenv: "docs(man)"
          - os: macos-latest
            noxenv: "docs(spelling)"
          - os: macos-latest
            noxenv: "docs(style)"
          - os: windows-latest
            noxenv: "docs(dirhtml)"
          - os: windows-latest
            noxenv: "docs(doctest)"
          - os: windows-latest
            noxenv: "docs(linkcheck)"
          - os: windows-latest
            noxenv: "docs(spelling)"
          - os: windows-latest
            noxenv: "docs(style)"
          - os: windows-latest
            noxenv: "tests-3.14(no-extras)"
          - os: windows-latest
            noxenv: "tests-3.14(format)"
          - os: windows-latest
            noxenv: "tests-3.14(format-nongpl)"
          - os: windows-latest
            noxenv: "tests-3.14t(no-extras)"
          - os: windows-latest
            noxenv: "tests-3.14t(format)"
          - os: windows-latest
            noxenv: "tests-3.14t(format-nongpl)"
 
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          persist-credentials: false
      - name: Install dependencies
        run: sudo apt-get update && sudo apt-get install -y libenchant-2-dev
        if: runner.os == 'Linux' && startsWith(matrix.noxenv, 'docs')
      - name: Install dependencies
        run: brew install enchant
        if: runner.os == 'macOS' && startsWith(matrix.noxenv, 'docs')
      - name: Set up Python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
        with:
          cache: 'pip'
          python-version: |
            3.10
            3.11
            3.12
            3.13
            3.14
            3.14t
            pypy-3.11-v7.3.22
          allow-prereleases: true
      - name: Enable UTF-8 on Windows
        run: echo "PYTHONUTF8=1" >> $env:GITHUB_ENV
        if: runner.os == 'Windows' && startsWith(matrix.noxenv, 'tests')
 
      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]
 
      - name: Run nox
        run: uvx nox -s "${{ matrix.noxenv }}" -- ${{ matrix.posargs }} # zizmor: ignore[template-injection]
 
  packaging:
    timeout-minutes: 30
    name: Build and publish
    needs: ci
    runs-on: latchkey-small
    environment:
      name: PyPI
      url: https://pypi.org/p/jsonschema
 
    permissions:
      contents: write  # for creating GitHub releases via `gh release create`
      id-token: write  # for trusted publishing to PyPI
 
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Set up uv
        uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39
        with:
          enable-cache: ${{ github.ref_type != 'tag' }} # zizmor: ignore[cache-poisoning]
 
      - name: Build our distributions
        run: uv run --frozen --with 'build[uv]' -m build --installer=uv
 
      - name: Publish to PyPI
        if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
        uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b
      - name: Create a GitHub Release
        if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
        env:
          GH_TOKEN: ${{ github.token }}
        run: gh release create "${GITHUB_REF_NAME}" dist/* --generate-notes
 

What changed

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 3 jobs (5 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