CI workflow (python-jsonschema/jsonschema)
The CI workflow from python-jsonschema/jsonschema, explained and optimized by Latchkey.
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.
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
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
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
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:
- Dependency installs
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.