Skip to content
Latchkey

Pytest unit/integration workflow (stravalib/stravalib)

The Pytest unit/integration workflow from stravalib/stravalib, explained and optimized by Latchkey.

D

CI health: D - needs work

Run this on Latchkey for self-healing, caching, and up to 58% lower cost.

Grade your own workflow free or run it on Latchkey →
Source: stravalib/stravalib.github/workflows/build-test.ymlLicense Apache-2.0View source

What it does

This is the Pytest unit/integration workflow from the stravalib/stravalib 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: Pytest unit/integration

on:
  pull_request:
  push:
    branches:
      - main

# Use bash by default in all jobs
defaults:
  run:
    shell: bash

permissions: {}

jobs:
  build-test:
    name: Test Run (${{ matrix.python-version }}, ${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: ["ubuntu-latest", "macos-latest", "windows-latest"]
        python-version: ["3.11", "3.12", "3.13", "3.14"]

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          # fetch more than the last single commit to help scm generate proper version
          fetch-depth: 20
          persist-credentials: false
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          python-version: ${{ matrix.python-version }}

      - name: Set Variables
        id: set_variables
        shell: bash
        run: |
          echo "PY=$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_OUTPUT
          echo "PIP_CACHE=$(pip cache dir)" >> $GITHUB_OUTPUT
      - name: Cache dependencies
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ${{ steps.set_variables.outputs.PIP_CACHE }}
          key: ${{ runner.os }}-pip-${{ steps.set_variables.outputs.PY }}
      - name: Install uv
        uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install nox
      - name: List installed packages
        run: pip list
      # Need tags for setuptools_scm to provide a proper version
      - name: Fetch git tags
        run: git fetch origin 'refs/tags/*:refs/tags/*'
        # For now i made a separate tests run so we can see each version
        # build via github actions. There may be a better way to do this.
      - name: Run tests with pytest & nox
        run: |
          nox -s tests-${{ matrix.python-version }}
      - name: Upload coverage to Codecov
        if: ${{ matrix.os == 'ubuntu-latest' &&  matrix.python-version == '3.11'}}
        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          verbose: true
          files: ./coverage.xml

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: Pytest unit/integration
 
on:
  pull_request:
  push:
    branches:
      - main
 
# Use bash by default in all jobs
defaults:
  run:
    shell: bash
 
permissions: {}
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build-test:
    timeout-minutes: 30
    name: Test Run (${{ matrix.python-version }}, ${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: ["ubuntu-latest", "macos-latest", "windows-latest"]
        python-version: ["3.11", "3.12", "3.13", "3.14"]
 
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          # fetch more than the last single commit to help scm generate proper version
          fetch-depth: 20
          persist-credentials: false
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
        with:
          cache: 'pip'
          python-version: ${{ matrix.python-version }}
 
      - name: Set Variables
        id: set_variables
        shell: bash
        run: |
          echo "PY=$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_OUTPUT
          echo "PIP_CACHE=$(pip cache dir)" >> $GITHUB_OUTPUT
      - name: Cache dependencies
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: ${{ steps.set_variables.outputs.PIP_CACHE }}
          key: ${{ runner.os }}-pip-${{ steps.set_variables.outputs.PY }}
      - name: Install uv
        uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install nox
      - name: List installed packages
        run: pip list
      # Need tags for setuptools_scm to provide a proper version
      - name: Fetch git tags
        run: git fetch origin 'refs/tags/*:refs/tags/*'
        # For now i made a separate tests run so we can see each version
        # build via github actions. There may be a better way to do this.
      - name: Run tests with pytest & nox
        run: |
          nox -s tests-${{ matrix.python-version }}
      - name: Upload coverage to Codecov
        if: ${{ matrix.os == 'ubuntu-latest' &&  matrix.python-version == '3.11'}}
        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          verbose: true
          files: ./coverage.xml
 

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 1 job (12 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