Build and Test workflow (hbldh/bleak)
The Build and Test workflow from hbldh/bleak, explained and optimized by Latchkey.
CI health: C - fair
Run this on Latchkey for self-healing, caching, and up to 58% lower cost.
Grade your own workflow free or run it on Latchkey →What it does
This is the Build and Test workflow from the hbldh/bleak 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: Build and Test
on:
push:
branches: [master, develop]
paths: ["bleak/**", "tests/**", ".github/workflows/build_and_test.yml", "pyproject.toml"]
pull_request:
paths: ["bleak/**", "tests/**", ".github/workflows/build_and_test.yml", "pyproject.toml"]
workflow_dispatch:
jobs:
build_desktop:
name: "Build and test"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["310", "311", "312", "313", "314"]
env:
FORCE_COLOR: "1"
steps:
- uses: actions/checkout@v4
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v6
with:
version: "latest"
python-version: ${{ matrix.python-version }}
- name: Test with pytest
run: uv run poe test-py${{ matrix.python-version }} --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
report_type: coverage
flags: ${{ matrix.os }}-py${{ matrix.python-version }}
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
report_type: test_results
flags: ${{ matrix.os }}-py${{ matrix.python-version }}
token: ${{ secrets.CODECOV_TOKEN }}
- name: Type checking
# We don't do this in the lint job because we have conditionals
# on both the platform and the Python version in the code, so we
# need to check each matrix combination.
run: |
uv run poe typecheck
integration_tests_bluez:
name: "BlueZ integration tests"
runs-on: "ubuntu-latest"
strategy:
fail-fast: false
matrix:
python-version: ["310", "311", "312", "313", "314"]
steps:
- uses: actions/checkout@v4
- name: Install QEMU
run: sudo apt-get update && sudo apt-get install -y qemu-system-x86 qemu-utils qemu-kvm
- name: Enable KVM group permissions
run: |
sudo chmod 666 /dev/kvm
- name: Build and boot Alpine VM
run: ./.github/alpine-vm/start-alpine-vm.sh
- name: Run pytest in VM
run: |
./.github/alpine-vm/vm-ssh.sh '
bluetoothctl --version
export UV_PROJECT_ENVIRONMENT=../.venv # We are in an mounted folder, so to speed things up put the venv outside the mount
export FORCE_COLOR=1
export CI=true
export GITHUB_ACTIONS=true
uv run poe test-py${{ matrix.python-version }} --bleak-bluez-vhci --cov-report=xml --cov-report=html:../.htmlcov --junitxml=junit.xml -o junit_family=legacy -o cache_dir=../.pytest_cache
'
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
report_type: coverage
flags: bluez-integration-py${{ matrix.python-version }}
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
report_type: test_results
flags: bluez-integration-py${{ matrix.python-version }}
token: ${{ secrets.CODECOV_TOKEN }}
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Build and Test on: push: branches: [master, develop] paths: ["bleak/**", "tests/**", ".github/workflows/build_and_test.yml", "pyproject.toml"] pull_request: paths: ["bleak/**", "tests/**", ".github/workflows/build_and_test.yml", "pyproject.toml"] workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build_desktop: timeout-minutes: 30 name: "Build and test" runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["310", "311", "312", "313", "314"] env: FORCE_COLOR: "1" steps: - uses: actions/checkout@v4 - name: Install the latest version of uv uses: astral-sh/setup-uv@v6 with: version: "latest" python-version: ${{ matrix.python-version }} - name: Test with pytest run: uv run poe test-py${{ matrix.python-version }} --cov-report=xml --junitxml=junit.xml -o junit_family=legacy - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 with: report_type: coverage flags: ${{ matrix.os }}-py${{ matrix.python-version }} token: ${{ secrets.CODECOV_TOKEN }} - name: Upload test results to Codecov if: ${{ !cancelled() }} uses: codecov/codecov-action@v5 with: report_type: test_results flags: ${{ matrix.os }}-py${{ matrix.python-version }} token: ${{ secrets.CODECOV_TOKEN }} - name: Type checking # We don't do this in the lint job because we have conditionals # on both the platform and the Python version in the code, so we # need to check each matrix combination. run: | uv run poe typecheck integration_tests_bluez: timeout-minutes: 30 name: "BlueZ integration tests" runs-on: "ubuntu-latest" strategy: fail-fast: false matrix: python-version: ["310", "311", "312", "313", "314"] steps: - uses: actions/checkout@v4 - name: Install QEMU run: sudo apt-get update && sudo apt-get install -y qemu-system-x86 qemu-utils qemu-kvm - name: Enable KVM group permissions run: | sudo chmod 666 /dev/kvm - name: Build and boot Alpine VM run: ./.github/alpine-vm/start-alpine-vm.sh - name: Run pytest in VM run: | ./.github/alpine-vm/vm-ssh.sh ' bluetoothctl --version export UV_PROJECT_ENVIRONMENT=../.venv # We are in an mounted folder, so to speed things up put the venv outside the mount export FORCE_COLOR=1 export CI=true export GITHUB_ACTIONS=true uv run poe test-py${{ matrix.python-version }} --bleak-bluez-vhci --cov-report=xml --cov-report=html:../.htmlcov --junitxml=junit.xml -o junit_family=legacy -o cache_dir=../.pytest_cache ' - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 with: report_type: coverage flags: bluez-integration-py${{ matrix.python-version }} token: ${{ secrets.CODECOV_TOKEN }} - name: Upload test results to Codecov if: ${{ !cancelled() }} uses: codecov/codecov-action@v5 with: report_type: test_results flags: bluez-integration-py${{ matrix.python-version }} token: ${{ secrets.CODECOV_TOKEN }}
What changed
- Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
2 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:
- Dependency installs
This workflow runs 2 jobs (20 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.