CI workflow (clap-rs/clap)
The CI workflow from clap-rs/clap, explained and optimized by Latchkey.
CI health: B - good
Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the clap-rs/clap 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
name: CI
permissions:
contents: read
on:
pull_request:
push:
branches:
- "*master"
env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always
CLICOLOR: 1
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
jobs:
ci:
permissions:
contents: none
name: CI
needs: [test, shell-integration, shell-integration-nu, check, ui, minimal-versions, lockfile, docs, rustfmt, clippy, cffconvert]
runs-on: ubuntu-latest
if: "always()"
steps:
- name: Failed
run: exit 1
if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')"
test:
name: Test
strategy:
matrix:
build: [linux, windows, mac, minimal, default, next]
include:
- build: linux
os: ubuntu-latest
rust: "stable"
features: "full"
- build: windows
os: windows-latest
rust: "stable"
features: "full"
- build: mac
os: macos-latest
rust: "stable"
features: "full"
- build: minimal
os: ubuntu-latest
rust: "stable"
features: "minimal"
- build: default
os: ubuntu-latest
rust: "stable"
features: "default"
- build: next
os: ubuntu-latest
rust: "stable"
features: "next"
continue-on-error: ${{ matrix.rust != 'stable' }}
runs-on: ${{ matrix.os }}
env:
# Reduce amount of data cached
CARGO_PROFILE_DEV_DEBUG: line-tables-only
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
- name: Build
run: make build-${{matrix.features}}
- name: Test
run: make test-${{matrix.features}}
- name: Test (benches)
run: make test-${{matrix.features}} ARGS='--workspace --benches'
- name: Test (ultra-minimal)
if: matrix.build == 'minimal'
run: make test-minimal ARGS='--manifest-path Cargo.toml'
- name: Test dynamic completions
run: cargo test -p clap_complete -F unstable-dynamic
shell-integration:
name: Shell Integration
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@v2
- name: Install shells
if: runner.os == 'Linux'
run: sudo apt-get install -y elvish fish zsh
- name: clap_complete
run: cargo test -p clap_complete -F unstable-dynamic -F unstable-shell-tests
shell-integration-nu:
name: Nushell Integration
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@v2
- name: clap_complete_nu
run: cargo test -p clap_complete_nushell -F unstable-shell-tests
check:
name: Check
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
build: [msrv, wasm, wasm-wasi, debug, release]
include:
- build: msrv
rust: "1.85" # MSRV
target: x86_64-unknown-linux-gnu
features: full
- build: wasm
rust: stable
target: wasm32-unknown-unknown
features: wasm
- build: wasm-wasi
rust: stable
target: wasm32-wasip2
features: wasm
- build: debug
rust: stable
target: x86_64-unknown-linux-gnu
features: debug
- build: release
rust: stable
target: x86_64-unknown-linux-gnu
features: release
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Check
run: make check-${{ matrix.features }}
env:
TOOLCHAIN_TARGET: ${{ matrix.target }}
ui:
name: UI Tests
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
features: [default, next]
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.97" # STABLE
- uses: Swatinem/rust-cache@v2
- name: UI Tests
run: make test-ui-${{ matrix.features }}
minimal-versions:
name: Minimal versions
strategy:
matrix:
os: ["ubuntu-latest"]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- name: Install nightly Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly
- name: Downgrade dependencies to minimal versions
run: cargo +nightly generate-lockfile -Z minimal-versions
- name: Compile with minimal versions
run: cargo +stable check --workspace --all-features --locked --exclude clap_complete_nushell --exclude clap_bench
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@v2
- name: "Is lockfile updated?"
run: cargo update --workspace --locked
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.97" # STABLE
- uses: Swatinem/rust-cache@v2
- name: Check documentation
env:
RUSTDOCFLAGS: -D warnings
run: make doc
rustfmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.97" # STABLE
components: rustfmt
- uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt --check
clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.97" # STABLE
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Lint (ultra-minimal)
run: make clippy-minimal ARGS='--manifest-path Cargo.toml'
- name: Lint (minimal)
run: make clippy-minimal
- name: Lint (all)
run: make clippy-full
- name: Lint (release)
run: make clippy-release
cffconvert:
name: cffconvert
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
persist-credentials: false
- name: CFF validation
uses: citation-file-format/cffconvert-github-action@2.0.0
with:
args: --validate
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI permissions: contents: read on: pull_request: push: branches: - "*master" env: RUST_BACKTRACE: 1 CARGO_TERM_COLOR: always CLICOLOR: 1 concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: ci: timeout-minutes: 30 permissions: contents: none name: CI needs: [test, shell-integration, shell-integration-nu, check, ui, minimal-versions, lockfile, docs, rustfmt, clippy, cffconvert] runs-on: latchkey-small if: "always()" steps: - name: Failed run: exit 1 if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')" test: timeout-minutes: 30 name: Test strategy: matrix: build: [linux, windows, mac, minimal, default, next] include: - build: linux os: ubuntu-latest rust: "stable" features: "full" - build: windows os: windows-latest rust: "stable" features: "full" - build: mac os: macos-latest rust: "stable" features: "full" - build: minimal os: ubuntu-latest rust: "stable" features: "minimal" - build: default os: ubuntu-latest rust: "stable" features: "default" - build: next os: ubuntu-latest rust: "stable" features: "next" continue-on-error: ${{ matrix.rust != 'stable' }} runs-on: ${{ matrix.os }} env: # Reduce amount of data cached CARGO_PROFILE_DEV_DEBUG: line-tables-only steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 - name: Build run: make build-${{matrix.features}} - name: Test run: make test-${{matrix.features}} - name: Test (benches) run: make test-${{matrix.features}} ARGS='--workspace --benches' - name: Test (ultra-minimal) if: matrix.build == 'minimal' run: make test-minimal ARGS='--manifest-path Cargo.toml' - name: Test dynamic completions run: cargo test -p clap_complete -F unstable-dynamic shell-integration: timeout-minutes: 30 name: Shell Integration runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: stable - uses: Swatinem/rust-cache@v2 - name: Install shells if: runner.os == 'Linux' run: sudo apt-get install -y elvish fish zsh - name: clap_complete run: cargo test -p clap_complete -F unstable-dynamic -F unstable-shell-tests shell-integration-nu: timeout-minutes: 30 name: Nushell Integration runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: stable - uses: Swatinem/rust-cache@v2 - name: clap_complete_nu run: cargo test -p clap_complete_nushell -F unstable-shell-tests check: timeout-minutes: 30 name: Check runs-on: latchkey-small strategy: fail-fast: false matrix: build: [msrv, wasm, wasm-wasi, debug, release] include: - build: msrv rust: "1.85" # MSRV target: x86_64-unknown-linux-gnu features: full - build: wasm rust: stable target: wasm32-unknown-unknown features: wasm - build: wasm-wasi rust: stable target: wasm32-wasip2 features: wasm - build: debug rust: stable target: x86_64-unknown-linux-gnu features: debug - build: release rust: stable target: x86_64-unknown-linux-gnu features: release steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install rust uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - uses: Swatinem/rust-cache@v2 - name: Check run: make check-${{ matrix.features }} env: TOOLCHAIN_TARGET: ${{ matrix.target }} ui: timeout-minutes: 30 name: UI Tests runs-on: latchkey-small strategy: fail-fast: false matrix: features: [default, next] steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: "1.97" # STABLE - uses: Swatinem/rust-cache@v2 - name: UI Tests run: make test-ui-${{ matrix.features }} minimal-versions: timeout-minutes: 30 name: Minimal versions strategy: matrix: os: ["ubuntu-latest"] runs-on: ${{ matrix.os }} steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install stable Rust uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Install nightly Rust uses: dtolnay/rust-toolchain@stable with: toolchain: nightly - name: Downgrade dependencies to minimal versions run: cargo +nightly generate-lockfile -Z minimal-versions - name: Compile with minimal versions run: cargo +stable check --workspace --all-features --locked --exclude clap_complete_nushell --exclude clap_bench lockfile: timeout-minutes: 30 runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: stable - uses: Swatinem/rust-cache@v2 - name: "Is lockfile updated?" run: cargo update --workspace --locked docs: timeout-minutes: 30 name: Docs runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: "1.97" # STABLE - uses: Swatinem/rust-cache@v2 - name: Check documentation env: RUSTDOCFLAGS: -D warnings run: make doc rustfmt: timeout-minutes: 30 name: rustfmt runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: "1.97" # STABLE components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting run: cargo fmt --check clippy: timeout-minutes: 30 name: clippy runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: toolchain: "1.97" # STABLE components: clippy - uses: Swatinem/rust-cache@v2 - name: Lint (ultra-minimal) run: make clippy-minimal ARGS='--manifest-path Cargo.toml' - name: Lint (minimal) run: make clippy-minimal - name: Lint (all) run: make clippy-full - name: Lint (release) run: make clippy-release cffconvert: timeout-minutes: 30 name: cffconvert runs-on: latchkey-small steps: - name: Checkout repository uses: actions/checkout@v7 with: persist-credentials: false - name: CFF validation uses: citation-file-format/cffconvert-github-action@2.0.0 with: args: --validate
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. - Add a job timeout so a hung step cannot burn hours of runner time.
3 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 12 jobs (22 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.