Tests workflow (pmbarrett314/curses-menu)
The Tests workflow from pmbarrett314/curses-menu, explained and optimized by Latchkey.
CI health: F - at risk
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Tests workflow from the pmbarrett314/curses-menu 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
on:
push:
branches: [master, develop]
tags:
- '*'
pull_request:
workflow_dispatch:
name: Tests
env:
PYTHONWARNINGS: all
TERM: xterm-256color
jobs:
pre-commit:
name: Various quality checks with pre-commit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ vars.MAIN_PYTHON }}
- uses: pre-commit/action@v3.0.1
env:
SKIP: "mypy,ruff"
ruff:
name: Lint with ruff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: ${{ vars.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install ${{ vars.MAIN_PYTHON }}
- name: Ruff Lint
run: uv run ruff check .
- name: Ruff Format
run: uv run ruff format .
mypy:
name: Type check with mypy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: ${{ vars.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install ${{ vars.MAIN_PYTHON }}
- run: uv run mypy .
initial-test:
name: Test One Version First
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: ${{ vars.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install ${{ vars.MAIN_PYTHON }}
- name: Install the project
run: uv sync --all-extras --dev
- run: uv run pytest
name: Run tests
- run: uv run coverage lcov
name: Generate coverage report for this run
- name: Upload coverage report for this run to coveralls
uses: coverallsapp/github-action@main
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: .cov/coverage.lcov
parallel: true
test:
name: Pytest via uv
needs:
- pre-commit
- ruff
- mypy
- initial-test
strategy:
matrix:
python-version: ["3.12", "3.11", "3.10", "3.9", "3.8", "pypy3.10", "3.13.0-rc.1", "3.14.0-alpha.0"]
os: [ubuntu-latest, macos-latest, windows-latest]
exclude:
- os: ubuntu-latest
python-version: ${{ vars.MAIN_PYTHON }}
#we already did this one
continue-on-error: ${{ contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14') || (contains(matrix.python-version, 'pypy') && matrix.os == 'windows-latest')}}
runs-on: ${{ matrix.os }}
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: ${{ vars.UV_VERSION }}
enable-cache: true
- name: Set up Python
if: ${{ ! (contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14')) }}
run: uv python install ${{ matrix.python-version }}
- uses: actions/setup-python@v5
if: ${{ (contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14')) }}
with:
python-version: ${{ matrix.python-version }}
- name: Install the project
run: uv sync --all-extras --dev
- run: uv run pytest
name: Run tests
- run: uv run coverage lcov
name: Generate coverage report for this run
- name: Upload coverage report for this run to coveralls
uses: coverallsapp/github-action@main
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: .cov/coverage.lcov
parallel: true
coveralls:
name: Finalize coveralls data
needs: test
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@main
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: .cov/coverage.lcov
parallel-finished: true
results:
if: ${{ always() }}
runs-on: ubuntu-latest
name: Status of final test results
needs: [test]
steps:
- run: |
result="${{ needs.test.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
build-and-publish:
name: Build and publish Python distributions to PyPI and TestPyPI
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags')
permissions:
id-token: write
needs:
- pre-commit
- ruff
- mypy
- test
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: ${{ vars.UV_VERSION }}
enable-cache: true
- name: Build package
run: uv build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
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.
on: push: branches: [master, develop] tags: - '*' pull_request: workflow_dispatch: name: Tests env: PYTHONWARNINGS: all TERM: xterm-256color concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: pre-commit: timeout-minutes: 30 name: Various quality checks with pre-commit runs-on: latchkey-small steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: cache: 'pip' python-version: ${{ vars.MAIN_PYTHON }} - uses: pre-commit/action@v3.0.1 env: SKIP: "mypy,ruff" ruff: timeout-minutes: 30 name: Lint with ruff runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: ${{ vars.UV_VERSION }} enable-cache: true - name: Set up Python run: uv python install ${{ vars.MAIN_PYTHON }} - name: Ruff Lint run: uv run ruff check . - name: Ruff Format run: uv run ruff format . mypy: timeout-minutes: 30 name: Type check with mypy runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: ${{ vars.UV_VERSION }} enable-cache: true - name: Set up Python run: uv python install ${{ vars.MAIN_PYTHON }} - run: uv run mypy . initial-test: timeout-minutes: 30 name: Test One Version First runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: ${{ vars.UV_VERSION }} enable-cache: true - name: Set up Python run: uv python install ${{ vars.MAIN_PYTHON }} - name: Install the project run: uv sync --all-extras --dev - run: uv run pytest name: Run tests - run: uv run coverage lcov name: Generate coverage report for this run - name: Upload coverage report for this run to coveralls uses: coverallsapp/github-action@main with: github-token: ${{ secrets.github_token }} path-to-lcov: .cov/coverage.lcov parallel: true test: timeout-minutes: 30 name: Pytest via uv needs: - pre-commit - ruff - mypy - initial-test strategy: matrix: python-version: ["3.12", "3.11", "3.10", "3.9", "3.8", "pypy3.10", "3.13.0-rc.1", "3.14.0-alpha.0"] os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: ubuntu-latest python-version: ${{ vars.MAIN_PYTHON }} #we already did this one continue-on-error: ${{ contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14') || (contains(matrix.python-version, 'pypy') && matrix.os == 'windows-latest')}} runs-on: ${{ matrix.os }} if: ${{ github.actor != 'dependabot[bot]' }} steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: ${{ vars.UV_VERSION }} enable-cache: true - name: Set up Python if: ${{ ! (contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14')) }} run: uv python install ${{ matrix.python-version }} - uses: actions/setup-python@v5 if: ${{ (contains(matrix.python-version,'3.13') || contains(matrix.python-version,'3.14')) }} with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install the project run: uv sync --all-extras --dev - run: uv run pytest name: Run tests - run: uv run coverage lcov name: Generate coverage report for this run - name: Upload coverage report for this run to coveralls uses: coverallsapp/github-action@main with: github-token: ${{ secrets.github_token }} path-to-lcov: .cov/coverage.lcov parallel: true coveralls: timeout-minutes: 30 name: Finalize coveralls data needs: test runs-on: latchkey-small steps: - name: Coveralls Finished uses: coverallsapp/github-action@main with: github-token: ${{ secrets.github_token }} path-to-lcov: .cov/coverage.lcov parallel-finished: true results: timeout-minutes: 30 if: ${{ always() }} runs-on: latchkey-small name: Status of final test results needs: [test] steps: - run: | result="${{ needs.test.result }}" if [[ $result == "success" || $result == "skipped" ]]; then exit 0 else exit 1 fi build-and-publish: timeout-minutes: 30 name: Build and publish Python distributions to PyPI and TestPyPI runs-on: latchkey-small if: startsWith(github.ref, 'refs/tags') permissions: id-token: write needs: - pre-commit - ruff - mypy - test steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: version: ${{ vars.UV_VERSION }} enable-cache: true - name: Build package run: uv build - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1
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. - Cancel superseded runs when a branch or PR gets a newer push.
- 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.
4 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.
This workflow runs 8 jobs (31 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.