Skip to content
Latchkey

Build and Test workflow (hbldh/bleak)

The Build and Test workflow from hbldh/bleak, explained and optimized by Latchkey.

C

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 →
Source: hbldh/bleak.github/workflows/build_and_test.ymlLicense MITView source

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

workflow (.yml)
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

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:

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.

Actions used in this workflow