continuous-integration workflow (nushell/nushell)
The continuous-integration workflow from nushell/nushell, 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 continuous-integration workflow from the nushell/nushell 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:
pull_request:
push:
branches:
- main
- 'patch-release-*'
name: continuous-integration
env:
NU_LOG_LEVEL: DEBUG
CLIPPY_OPTIONS: "-D warnings"
NUSHELL_CARGO_PROFILE: ci
MAIN_OPTIONS: --workspace --exclude nu_plugin_* --all-targets
PLUGIN_OPTIONS: --package nu_plugin_* --all-targets
WASM_OPTIONS: >-
--no-default-features
--target wasm32-unknown-unknown
-p nu-cmd-base
-p nu-cmd-extra
-p nu-cmd-lang
-p nu-color-config
-p nu-command
-p nu-derive-value
-p nu-engine
-p nu-glob
-p nu-json
-p nu-parser
-p nu-path
-p nu-pretty-hex
-p nu-protocol
-p nu-std
-p nu-system
-p nu-table
-p nu-term-grid
-p nu-utils
-p nuon
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: true
jobs:
cargo:
name: "`cargo` in ${{ matrix.workspace.name }} (${{ matrix.target.name }})"
strategy:
fail-fast: true
matrix:
target:
# Pinning to Ubuntu 22.04 because building on newer Ubuntu versions causes linux-gnu
# builds to link against a too-new-for-many-Linux-installs glibc version. Consider
# revisiting this when 22.04 is closer to EOL (June 2027)
- name: Ubuntu
host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
options: MAIN_OPTIONS
steps: [fmt, clippy, build, test, doctest]
- name: Windows
host: windows-latest
target: x86_64-pc-windows-msvc
options: MAIN_OPTIONS
steps: [fmt, clippy, build, test, doctest]
- name: MacOS
host: macos-latest
target: x86_64-apple-darwin
options: MAIN_OPTIONS
steps: [fmt, clippy, build, test, doctest]
- name: Ubuntu Plugins
host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
options: PLUGIN_OPTIONS
steps: [clippy, build, test]
- name: Windows Plugins
host: windows-latest
target: x86_64-pc-windows-msvc
options: PLUGIN_OPTIONS
steps: [clippy, build, test]
- name: MacOS Plugins
host: macos-latest
target: x86_64-apple-darwin
options: PLUGIN_OPTIONS
steps: [clippy, build, test]
- name: WASM
host: ubuntu-22.04
target: wasm32-unknown-unknown
options: WASM_OPTIONS
steps: [build, check]
workspace:
- name: root
path: ./
profile: ci
skip: []
- name: nu-parser/fuzz
path: ./crates/nu-parser/fuzz
profile: dev
skip: [build, test, doctest]
- name: nu-path/fuzz
path: ./crates/nu-path/fuzz
profile: dev
skip: [build, test, doctest]
exclude:
- target: { name: WASM }
workspace: { name: nu-parser/fuzz }
- target: { name: WASM }
workspace: { name: nu-path/fuzz }
- target: { name: Ubuntu Plugins }
workspace: { name: nu-parser/fuzz }
- target: { name: Ubuntu Plugins }
workspace: { name: nu-path/fuzz }
- target: { name: Windows Plugins }
workspace: { name: nu-parser/fuzz }
- target: { name: Windows Plugins }
workspace: { name: nu-path/fuzz }
- target: { name: MacOS Plugins }
workspace: { name: nu-parser/fuzz }
- target: { name: MacOS Plugins }
workspace: { name: nu-path/fuzz }
runs-on: ${{ matrix.target.host }}
steps:
- name: Checkout Repo
uses: actions/checkout@v7
- name: Setup Rust Toolchain
run: rustup target add ${{ matrix.target.target }}
working-directory: ${{ matrix.workspace.path }}
- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
workspaces: ${{ matrix.workspace.path }} -> target
cache-all-crates: true
cache-workspace-crates: true
- name: cargo fmt
if: contains(matrix.target.steps, 'fmt') && !contains(matrix.workspace.skip, 'fmt')
working-directory: ${{ matrix.workspace.path }}
run: |
rustup component add rustfmt
cargo fmt --all --check
- name: cargo check
if: contains(matrix.target.steps, 'check') && !contains(matrix.workspace.skip, 'check')
working-directory: ${{ matrix.workspace.path }}
run: cargo check ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }}
- name: cargo clippy
if: contains(matrix.target.steps, 'clippy') && !contains(matrix.workspace.skip, 'clippy')
working-directory: ${{ matrix.workspace.path }}
run: |
rustup component add clippy
cargo clippy ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }} -- ${{ env['CLIPPY_OPTIONS'] }}
- name: cargo build
if: contains(matrix.target.steps, 'build') && !contains(matrix.workspace.skip, 'build')
working-directory: ${{ matrix.workspace.path }}
run: cargo build ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }}
- name: cargo test
if: contains(matrix.target.steps, 'test') && !contains(matrix.workspace.skip, 'test')
working-directory: ${{ matrix.workspace.path }}
run: cargo test ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }}
- name: cargo test --doc
if: contains(matrix.target.steps, 'doctest') && !contains(matrix.workspace.skip, 'doctest')
working-directory: ${{ matrix.workspace.path }}
run: cargo test --workspace --doc --profile ${{ matrix.workspace.profile }}
- name: Assert Clean Repo
run: git diff --quiet && git diff --cached --quiet
std-lib-and-python-virtualenv:
strategy:
fail-fast: true
matrix:
platform: [ubuntu-22.04, macos-latest, windows-latest]
py:
- py
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v7
- name: Setup Rust toolchain and cache
uses: actions-rust-lang/setup-rust-toolchain@v1.12.0
- name: Install Nushell
run: cargo install --path . --locked --force
- name: Upload Nushell build (Ubuntu and macOS)
uses: actions/upload-artifact@v7
if: runner.os != 'Windows'
with:
name: "nu-${{ github.event.number || github.ref_name }}-${{ matrix.platform }}"
path: "~/.cargo/bin/nu"
retention-days: 14
- name: Upload Nushell build (Windows)
uses: actions/upload-artifact@v7
if: runner.os == 'Windows'
with:
name: "nu-${{ github.event.number || github.ref_name }}-${{ matrix.platform }}"
path: 'C:\Users\runneradmin\.cargo\bin\nu.exe'
retention-days: 14
- name: Standard library tests
run: nu -c 'use crates/nu-std/testing.nu; testing run-tests --path crates/nu-std'
- name: Ensure that Cargo.toml MSRV and rust-toolchain.toml use the same version
run: nu .github/workflows/check-msrv.nu
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Install virtualenv
run: pip install virtualenv
shell: bash
- name: Test Nushell in virtualenv
run: nu scripts/test_virtualenv.nu
shell: bash
- name: Check for clean repo
shell: bash
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "there are changes";
git status --porcelain
exit 1
else
echo "no changes in working directory";
fi
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: pull_request: push: branches: - main - 'patch-release-*' name: continuous-integration env: NU_LOG_LEVEL: DEBUG CLIPPY_OPTIONS: "-D warnings" NUSHELL_CARGO_PROFILE: ci MAIN_OPTIONS: --workspace --exclude nu_plugin_* --all-targets PLUGIN_OPTIONS: --package nu_plugin_* --all-targets WASM_OPTIONS: >- --no-default-features --target wasm32-unknown-unknown -p nu-cmd-base -p nu-cmd-extra -p nu-cmd-lang -p nu-color-config -p nu-command -p nu-derive-value -p nu-engine -p nu-glob -p nu-json -p nu-parser -p nu-path -p nu-pretty-hex -p nu-protocol -p nu-std -p nu-system -p nu-table -p nu-term-grid -p nu-utils -p nuon concurrency: group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} cancel-in-progress: true jobs: cargo: timeout-minutes: 30 name: "`cargo` in ${{ matrix.workspace.name }} (${{ matrix.target.name }})" strategy: fail-fast: true matrix: target: # Pinning to Ubuntu 22.04 because building on newer Ubuntu versions causes linux-gnu # builds to link against a too-new-for-many-Linux-installs glibc version. Consider # revisiting this when 22.04 is closer to EOL (June 2027) - name: Ubuntu host: ubuntu-22.04 target: x86_64-unknown-linux-gnu options: MAIN_OPTIONS steps: [fmt, clippy, build, test, doctest] - name: Windows host: windows-latest target: x86_64-pc-windows-msvc options: MAIN_OPTIONS steps: [fmt, clippy, build, test, doctest] - name: MacOS host: macos-latest target: x86_64-apple-darwin options: MAIN_OPTIONS steps: [fmt, clippy, build, test, doctest] - name: Ubuntu Plugins host: ubuntu-22.04 target: x86_64-unknown-linux-gnu options: PLUGIN_OPTIONS steps: [clippy, build, test] - name: Windows Plugins host: windows-latest target: x86_64-pc-windows-msvc options: PLUGIN_OPTIONS steps: [clippy, build, test] - name: MacOS Plugins host: macos-latest target: x86_64-apple-darwin options: PLUGIN_OPTIONS steps: [clippy, build, test] - name: WASM host: ubuntu-22.04 target: wasm32-unknown-unknown options: WASM_OPTIONS steps: [build, check] workspace: - name: root path: ./ profile: ci skip: [] - name: nu-parser/fuzz path: ./crates/nu-parser/fuzz profile: dev skip: [build, test, doctest] - name: nu-path/fuzz path: ./crates/nu-path/fuzz profile: dev skip: [build, test, doctest] exclude: - target: { name: WASM } workspace: { name: nu-parser/fuzz } - target: { name: WASM } workspace: { name: nu-path/fuzz } - target: { name: Ubuntu Plugins } workspace: { name: nu-parser/fuzz } - target: { name: Ubuntu Plugins } workspace: { name: nu-path/fuzz } - target: { name: Windows Plugins } workspace: { name: nu-parser/fuzz } - target: { name: Windows Plugins } workspace: { name: nu-path/fuzz } - target: { name: MacOS Plugins } workspace: { name: nu-parser/fuzz } - target: { name: MacOS Plugins } workspace: { name: nu-path/fuzz } runs-on: ${{ matrix.target.host }} steps: - name: Checkout Repo uses: actions/checkout@v7 - name: Setup Rust Toolchain run: rustup target add ${{ matrix.target.target }} working-directory: ${{ matrix.workspace.path }} - name: Cache Rust uses: Swatinem/rust-cache@v2 with: workspaces: ${{ matrix.workspace.path }} -> target cache-all-crates: true cache-workspace-crates: true - name: cargo fmt if: contains(matrix.target.steps, 'fmt') && !contains(matrix.workspace.skip, 'fmt') working-directory: ${{ matrix.workspace.path }} run: | rustup component add rustfmt cargo fmt --all --check - name: cargo check if: contains(matrix.target.steps, 'check') && !contains(matrix.workspace.skip, 'check') working-directory: ${{ matrix.workspace.path }} run: cargo check ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }} - name: cargo clippy if: contains(matrix.target.steps, 'clippy') && !contains(matrix.workspace.skip, 'clippy') working-directory: ${{ matrix.workspace.path }} run: | rustup component add clippy cargo clippy ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }} -- ${{ env['CLIPPY_OPTIONS'] }} - name: cargo build if: contains(matrix.target.steps, 'build') && !contains(matrix.workspace.skip, 'build') working-directory: ${{ matrix.workspace.path }} run: cargo build ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }} - name: cargo test if: contains(matrix.target.steps, 'test') && !contains(matrix.workspace.skip, 'test') working-directory: ${{ matrix.workspace.path }} run: cargo test ${{ env[matrix.target.options] }} --profile ${{ matrix.workspace.profile }} - name: cargo test --doc if: contains(matrix.target.steps, 'doctest') && !contains(matrix.workspace.skip, 'doctest') working-directory: ${{ matrix.workspace.path }} run: cargo test --workspace --doc --profile ${{ matrix.workspace.profile }} - name: Assert Clean Repo run: git diff --quiet && git diff --cached --quiet std-lib-and-python-virtualenv: timeout-minutes: 30 strategy: fail-fast: true matrix: platform: [ubuntu-22.04, macos-latest, windows-latest] py: - py runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v7 - name: Setup Rust toolchain and cache uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 - name: Install Nushell run: cargo install --path . --locked --force - name: Upload Nushell build (Ubuntu and macOS) uses: actions/upload-artifact@v7 if: runner.os != 'Windows' with: name: "nu-${{ github.event.number || github.ref_name }}-${{ matrix.platform }}" path: "~/.cargo/bin/nu" retention-days: 14 - name: Upload Nushell build (Windows) uses: actions/upload-artifact@v7 if: runner.os == 'Windows' with: name: "nu-${{ github.event.number || github.ref_name }}-${{ matrix.platform }}" path: 'C:\Users\runneradmin\.cargo\bin\nu.exe' retention-days: 14 - name: Standard library tests run: nu -c 'use crates/nu-std/testing.nu; testing run-tests --path crates/nu-std' - name: Ensure that Cargo.toml MSRV and rust-toolchain.toml use the same version run: nu .github/workflows/check-msrv.nu - name: Setup Python uses: actions/setup-python@v6 with: cache: 'pip' python-version: "3.10" - name: Install virtualenv run: pip install virtualenv shell: bash - name: Test Nushell in virtualenv run: nu scripts/test_virtualenv.nu shell: bash - name: Check for clean repo shell: bash run: | if [ -n "$(git status --porcelain)" ]; then echo "there are changes"; git status --porcelain exit 1 else echo "no changes in working directory"; fi
What changed
- 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.
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 (24 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.