Skip to content
Latchkey

CI workflow (hyperium/hyper)

The CI workflow from hyperium/hyper, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: hyperium/hyper.github/workflows/CI.ymlLicense MITView source

What it does

This is the CI workflow from the hyperium/hyper 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: CI
on:
  pull_request:
  push:
    branches:
      - master

env:
  RUST_BACKTRACE: 1

permissions:
  contents: read # to fetch code (actions/checkout)

jobs:
  ci-pass:
    name: CI is green
    runs-on: ubuntu-latest
    needs:
      - style
      - lint
      - test
      - msrv
      - miri
      - features
      - ffi
      - ffi-header
      - ffi-cargo-c
      - doc
      - check-external-types
      - udeps
      - minimal-versions
      - semver
    steps:
      - run: exit 0

  style:
    name: Check Style
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt

      - name: cargo fmt --check
        run: |
          if ! rustfmt --check --edition 2021 $(git ls-files '*.rs'); then
            printf "Please run \`rustfmt --edition 2021 \$(git ls-files '*.rs')\` to fix rustfmt errors.\nSee docs/CODE_STYLE.md for more details.\n" >&2
            exit 1
          fi

  lint:
    name: Linter
    #needs: [style]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      # not --all-targets, lints can't seem to tell integrations tests are tests
      - name: Clippy
        run: cargo clippy --features full -- -D warnings

  test:
    name: Test ${{ matrix.rust }} on ${{ matrix.os }}
    needs: [style]
    strategy:
      matrix:
        rust:
          - stable
          - beta
          - nightly

        os:
          - ubuntu-latest
          - windows-latest
          - macOS-latest

        include:
          - rust: stable
            features: "--features full"
          - rust: beta
            features: "--features full"
          - rust: nightly
            features: "--features full,nightly"
            benches: true

    runs-on: ${{ matrix.os }}

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust (${{ matrix.rust }})
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}

      - uses: Swatinem/rust-cache@v2

      - name: Test
        run: cargo test ${{ matrix.features }}

      - name: Test all benches
        if: matrix.benches
        run: cargo test --benches ${{ matrix.features }}

  msrv:
    name: Check MSRV
    needs: [style]

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable

      - name: Resolve MSRV aware dependencies
        run: cargo update
        env:
          CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback

      - name: Get MSRV from package metadata
        id: msrv
        run: echo "version=$(yq '.package.rust-version' Cargo.toml)" >> $GITHUB_OUTPUT

      - name: Install Rust (${{ steps.msrv.outputs.version }})
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ steps.msrv.outputs.version }}

      - uses: Swatinem/rust-cache@v2

      - name: Check
        run: cargo check --features full

  miri:
    name: Test with Miri
    needs: [style]
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: miri

      - uses: Swatinem/rust-cache@v2

      - name: Test
        # Can't enable tcp feature since Miri does not support the tokio runtime
        run: MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test --features http1,http2,client,server,nightly

  features:
    name: features
    needs: [style]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install cargo-hack
        uses: taiki-e/install-action@cargo-hack

      - uses: Swatinem/rust-cache@v2

      - name: check --feature-powerset
        run: cargo hack --no-dev-deps check --feature-powerset --depth 2 --skip ffi,tracing
        env:
          RUSTFLAGS: "-D dead_code -D unused_imports"

      - name: check --feature-powerset with tracing feature
        run: cargo hack --no-dev-deps check --feature-powerset --depth 2 --features tracing --skip ffi
        env:
          RUSTFLAGS: "--cfg hyper_unstable_tracing -D dead_code -D unused_imports"

  ffi:
    name: Test C API (FFI)
    needs: [style]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Build FFI
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo rustc --features client,http1,http2,ffi --crate-type cdylib

      - name: Make Examples
        run: cd capi/examples && make client

      - name: Run FFI unit tests
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo test --features client,http1,http2,ffi --lib

  ffi-header:
    name: Verify hyper.h is up to date
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install cbindgen
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cbindgen

      - name: Install cargo-expand
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cargo-expand

      - uses: Swatinem/rust-cache@v2

      - name: Build FFI
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo build --features client,http1,http2,ffi

      - name: Ensure that hyper.h is up to date
        run: ./capi/gen_header.sh --verify

  ffi-cargo-c:
    name: Test cargo-c support (FFI)
    needs: [style]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Install cargo-c
        env:
          LINK: https://github.com/lu-zero/cargo-c/releases/latest/download
          CARGO_C_FILE: cargo-c-x86_64-unknown-linux-musl.tar.gz
        run: |
          curl -L $LINK/$CARGO_C_FILE | tar xz -C ~/.cargo/bin

      - name: Build with cargo-c
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo cbuild --features client,http1,http2,ffi

  doc:
    name: Build docs
    needs: [style, test]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly

      - uses: Swatinem/rust-cache@v2

      - name: cargo doc
        run: cargo rustdoc --features full,ffi -- --cfg docsrs --cfg hyper_unstable_ffi -D rustdoc::broken-intra-doc-links

  check-external-types:
    name: Check exposed types
    needs: [style, test]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-10-18 # Compatible version for cargo-check-external-types

      - name: Install cargo-check-external-types
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cargo-check-external-types@0.4.0

      - uses: Swatinem/rust-cache@v2

      - name: check-external-types
        run: cargo check-external-types --config .github/workflows/external-types.toml

  udeps:
    needs: [style]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly

      - name: Install cargo-udeps
        uses: taiki-e/install-action@cargo-udeps

      - uses: Swatinem/rust-cache@v2

      - name: Check unused dependencies on default features
        run: cargo udeps

      - name: Check unused dependencies on full features
        run: cargo udeps --features full

  minimal-versions:
    runs-on: ubuntu-latest
    needs: [style]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@cargo-hack
      - uses: taiki-e/install-action@cargo-minimal-versions
      - uses: Swatinem/rust-cache@v2
      - run: cargo minimal-versions check
      - run: cargo minimal-versions check --features full

  semver:
    name: semver
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Check semver
        uses: obi1kenobi/cargo-semver-checks-action@v2
        with:
          feature-group: only-explicit-features
          features: full
          release-type: minor

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: CI
on:
  pull_request:
  push:
    branches:
      - master
 
env:
  RUST_BACKTRACE: 1
 
permissions:
  contents: read # to fetch code (actions/checkout)
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  ci-pass:
    timeout-minutes: 30
    name: CI is green
    runs-on: latchkey-small
    needs:
      - style
      - lint
      - test
      - msrv
      - miri
      - features
      - ffi
      - ffi-header
      - ffi-cargo-c
      - doc
      - check-external-types
      - udeps
      - minimal-versions
      - semver
    steps:
      - run: exit 0
 
  style:
    timeout-minutes: 30
    name: Check Style
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
 
      - name: cargo fmt --check
        run: |
          if ! rustfmt --check --edition 2021 $(git ls-files '*.rs'); then
            printf "Please run \`rustfmt --edition 2021 \$(git ls-files '*.rs')\` to fix rustfmt errors.\nSee docs/CODE_STYLE.md for more details.\n" >&2
            exit 1
          fi
 
  lint:
    timeout-minutes: 30
    name: Linter
    #needs: [style]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
 
      - uses: Swatinem/rust-cache@v2
 
      # not --all-targets, lints can't seem to tell integrations tests are tests
      - name: Clippy
        run: cargo clippy --features full -- -D warnings
 
  test:
    timeout-minutes: 30
    name: Test ${{ matrix.rust }} on ${{ matrix.os }}
    needs: [style]
    strategy:
      matrix:
        rust:
          - stable
          - beta
          - nightly
 
        os:
          - ubuntu-latest
          - windows-latest
          - macOS-latest
 
        include:
          - rust: stable
            features: "--features full"
          - rust: beta
            features: "--features full"
          - rust: nightly
            features: "--features full,nightly"
            benches: true
 
    runs-on: ${{ matrix.os }}
 
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust (${{ matrix.rust }})
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Test
        run: cargo test ${{ matrix.features }}
 
      - name: Test all benches
        if: matrix.benches
        run: cargo test --benches ${{ matrix.features }}
 
  msrv:
    timeout-minutes: 30
    name: Check MSRV
    needs: [style]
 
    runs-on: latchkey-small
 
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - uses: dtolnay/rust-toolchain@stable
 
      - name: Resolve MSRV aware dependencies
        run: cargo update
        env:
          CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback
 
      - name: Get MSRV from package metadata
        id: msrv
        run: echo "version=$(yq '.package.rust-version' Cargo.toml)" >> $GITHUB_OUTPUT
 
      - name: Install Rust (${{ steps.msrv.outputs.version }})
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ steps.msrv.outputs.version }}
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Check
        run: cargo check --features full
 
  miri:
    timeout-minutes: 30
    name: Test with Miri
    needs: [style]
    runs-on: latchkey-small
 
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: miri
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Test
        # Can't enable tcp feature since Miri does not support the tokio runtime
        run: MIRIFLAGS="-Zmiri-disable-isolation" cargo miri test --features http1,http2,client,server,nightly
 
  features:
    timeout-minutes: 30
    name: features
    needs: [style]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
 
      - name: Install cargo-hack
        uses: taiki-e/install-action@cargo-hack
 
      - uses: Swatinem/rust-cache@v2
 
      - name: check --feature-powerset
        run: cargo hack --no-dev-deps check --feature-powerset --depth 2 --skip ffi,tracing
        env:
          RUSTFLAGS: "-D dead_code -D unused_imports"
 
      - name: check --feature-powerset with tracing feature
        run: cargo hack --no-dev-deps check --feature-powerset --depth 2 --features tracing --skip ffi
        env:
          RUSTFLAGS: "--cfg hyper_unstable_tracing -D dead_code -D unused_imports"
 
  ffi:
    timeout-minutes: 30
    name: Test C API (FFI)
    needs: [style]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Build FFI
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo rustc --features client,http1,http2,ffi --crate-type cdylib
 
      - name: Make Examples
        run: cd capi/examples && make client
 
      - name: Run FFI unit tests
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo test --features client,http1,http2,ffi --lib
 
  ffi-header:
    timeout-minutes: 30
    name: Verify hyper.h is up to date
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
 
      - name: Install cbindgen
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cbindgen
 
      - name: Install cargo-expand
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cargo-expand
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Build FFI
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo build --features client,http1,http2,ffi
 
      - name: Ensure that hyper.h is up to date
        run: ./capi/gen_header.sh --verify
 
  ffi-cargo-c:
    timeout-minutes: 30
    name: Test cargo-c support (FFI)
    needs: [style]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Install cargo-c
        env:
          LINK: https://github.com/lu-zero/cargo-c/releases/latest/download
          CARGO_C_FILE: cargo-c-x86_64-unknown-linux-musl.tar.gz
        run: |
          curl -L $LINK/$CARGO_C_FILE | tar xz -C ~/.cargo/bin
 
      - name: Build with cargo-c
        env:
          RUSTFLAGS: --cfg hyper_unstable_ffi
        run: cargo cbuild --features client,http1,http2,ffi
 
  doc:
    timeout-minutes: 30
    name: Build docs
    needs: [style, test]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly
 
      - uses: Swatinem/rust-cache@v2
 
      - name: cargo doc
        run: cargo rustdoc --features full,ffi -- --cfg docsrs --cfg hyper_unstable_ffi -D rustdoc::broken-intra-doc-links
 
  check-external-types:
    timeout-minutes: 30
    name: Check exposed types
    needs: [style, test]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: nightly-2025-10-18 # Compatible version for cargo-check-external-types
 
      - name: Install cargo-check-external-types
        uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cargo-check-external-types@0.4.0
 
      - uses: Swatinem/rust-cache@v2
 
      - name: check-external-types
        run: cargo check-external-types --config .github/workflows/external-types.toml
 
  udeps:
    timeout-minutes: 30
    needs: [style]
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v6
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@nightly
 
      - name: Install cargo-udeps
        uses: taiki-e/install-action@cargo-udeps
 
      - uses: Swatinem/rust-cache@v2
 
      - name: Check unused dependencies on default features
        run: cargo udeps
 
      - name: Check unused dependencies on full features
        run: cargo udeps --features full
 
  minimal-versions:
    timeout-minutes: 30
    runs-on: latchkey-small
    needs: [style]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@nightly
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@cargo-hack
      - uses: taiki-e/install-action@cargo-minimal-versions
      - uses: Swatinem/rust-cache@v2
      - run: cargo minimal-versions check
      - run: cargo minimal-versions check --features full
 
  semver:
    timeout-minutes: 30
    name: semver
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - name: Check semver
        uses: obi1kenobi/cargo-semver-checks-action@v2
        with:
          feature-group: only-explicit-features
          features: full
          release-type: minor
 

What changed

5 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 15 jobs (23 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