Files
atuin-mirror/.github/workflows/rust.yml

575 lines
19 KiB
YAML

name: Rust
on:
push:
branches: [main]
paths-ignore:
- "ui/**"
pull_request:
branches: [main]
paths-ignore:
- "ui/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
# The one full release build. Platform-specific compile errors are caught by
# unit-test's debug builds on every OS, release-profile breakage is
# platform-independent (the check job type-checks the profile everywhere),
# and release.yml builds every target for real. Windows spent ~5 min on two
# serial crates here and macOS ~3 min of scarce runner capacity for nothing.
build:
runs-on: depot-ubuntu-24.04-8
env:
# This job only proves the release profile compiles; nothing it builds is
# shipped (release.yml uses the `dist` profile, which sets lto = "fat"
# explicitly). Skip the default thin-local LTO pass on the final binary.
CARGO_PROFILE_RELEASE_LTO: "off"
# Experiment: the two crates that dominate this job (atuin, atuin-daemon)
# leave most cores idle with the default 16 codegen units; more, smaller
# units let LLVM spread them out. Drop if the timings don't improve.
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "256"
# sccache serves compiled objects from Depot's managed WebDAV cache; keep
# incremental off (sccache can't cache incremental compilations).
RUSTC_WRAPPER: sccache
CARGO_INCREMENTAL: "0"
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
# rust-cache restores a warm, bounded target/ so cargo skips unchanged
# crates; sccache (RUSTC_WRAPPER, env) then serves the crates that DO
# compile -- cold, new-branch, or changed -- from Depot's cross-branch
# WebDAV cache. rust-cache also caches ~/.cargo and cleans stale target/
# artifacts, so the disk stays bounded.
- uses: mozilla-actions/sccache-action@v0.0.9
- uses: Swatinem/rust-cache@v2
with:
key: build
- name: Run cargo build (release)
run: cargo build --workspace --locked --release
- name: sccache stats
if: ${{ always() }}
run: sccache --show-stats
# This used to use cross compilling via `cross` but it's more reliable to just
# run this on a real illumos (OmniOS) system.
test-in-vm:
name: Test in VM (illumos)
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Test on illumos
uses: vmactions/omnios-vm@317e4f8069dad8a65e1520808f1a68ef3fd20565 # v1.3.6
with:
# use the latest omnios LTS
release: "r151054-build"
envs: "CARGO_TERM_COLOR"
usesh: true
mem: 4096
copyback: false
prepare: |
pkg install pkg-config openssl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.98.0
run: |
. "$HOME/.cargo/env"
banner client
cargo build -p atuin-client --locked --release
banner server
cargo build -p atuin-server --locked --release
unit-test:
strategy:
matrix:
os: [depot-ubuntu-24.04-8, depot-macos-26, depot-windows-2025-16]
runs-on: ${{ matrix.os }}
env:
# sccache serves compiled objects from Depot's managed WebDAV cache; keep
# incremental off (sccache can't cache incremental compilations).
RUSTC_WRAPPER: sccache
CARGO_INCREMENTAL: "0"
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
- uses: taiki-e/install-action@v2
name: Install nextest
with:
tool: cargo-nextest
# rust-cache (warm target skip) + sccache (serves compiled crates from
# Depot's cross-branch cache); see the build job.
- uses: mozilla-actions/sccache-action@v0.0.9
- uses: Swatinem/rust-cache@v2
with:
key: unit-test
- name: Run cargo test
run: cargo nextest run --lib --bins
- name: sccache stats
if: ${{ always() }}
run: sccache --show-stats
- name: Show new proptest regressions
if: ${{ failure() }}
shell: bash
run: |
echo "::group::proptest regression files changed by this run"
echo "A proptest failure appends a 'cc <seed>' line to a regression file."
echo "New/changed regression files (download the artifact below to reproduce):"
git add -N -- '*proptest-regressions*' || true
git status --porcelain
git --no-pager diff
echo "::endgroup::"
- name: Upload proptest regressions
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: proptest-regressions-unit-${{ matrix.os }}
path: |
**/proptest-regressions/**
**/*.proptest-regressions
if-no-files-found: ignore
retention-days: 14
check:
strategy:
matrix:
os: [depot-ubuntu-24.04, depot-macos-26, depot-windows-2025-16]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
# rust-cache (not sccache) for check/msrv/clippy/docs: these emit metadata
# only (no link), which sccache refuses to cache, so sccache gives 0 hits
# here. rust-cache instead bounds target/ growth (it cleans stale
# artifacts before each save) and keeps these jobs warm.
- uses: Swatinem/rust-cache@v2
with:
key: check
- name: Run cargo check (all features)
run: cargo check --all-features --workspace
env:
# --all-features enables vendored-tls, which compiles OpenSSL from
# source. Type-checking doesn't need that; link against the system
# libssl where one is installed (Linux only). openssl-sys treats any
# value other than "0" as "don't vendor".
OPENSSL_NO_VENDOR: ${{ runner.os == 'Linux' && '1' || '0' }}
- name: Run cargo check (no features)
run: cargo check --no-default-features --workspace
- name: Run cargo check (sync)
run: cargo check --no-default-features --features sync --workspace
- name: Run cargo check (server)
run: cargo check -p atuin-server
- name: Run cargo check (client only)
run: cargo check --no-default-features --features client --workspace
- name: Run cargo check (release profile)
run: cargo check --workspace --locked --release
msrv:
name: MSRV (1.95.0)
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install MSRV rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.95.0
# rust-cache (see check job): sccache can't cache metadata-only builds.
- uses: Swatinem/rust-cache@v2
with:
key: msrv
# Verifies the declared MSRV (workspace.package.rust-version) still holds
# with all features enabled. --all-features isn't a strict superset (it
# skips `cfg(not(feature))` and no-default-features paths), but atuin's
# features are additive, so this catches MSRV regressions cheaply.
- name: Check MSRV (all features)
# rust-toolchain.toml pins the dev toolchain and outranks dtolnay's
# `rustup default`, so force the MSRV toolchain explicitly here.
env:
RUSTUP_TOOLCHAIN: 1.95.0
run: cargo check --locked --workspace --all-features
integration-test:
# Bumped from -8 to -16 for root-disk headroom (150 GB -> 180 GB) against the
# intermittent runner-crash ENOSPC (the runner worker died writing its diag
# log to a full root fs), plus 2x CPU (faster) and 2x RAM (larger /dev/shm
# safety margin).
runs-on: depot-ubuntu-24.04-16
services:
postgres:
image: postgres
env:
POSTGRES_USER: atuin
POSTGRES_PASSWORD: pass
POSTGRES_DB: atuin
ports:
- 5432:5432
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
- uses: taiki-e/install-action@v2
name: Install nextest
with:
tool: cargo-nextest
# rust-cache (warm target skip) + sccache (serves compiled crates from
# Depot's cross-branch cache); see the build job. rust-cache cleans stale
# target/ artifacts, so it can't re-accrete the 71 GB that once crashed
# the runner with ENOSPC.
- uses: mozilla-actions/sccache-action@v0.0.9
- uses: Swatinem/rust-cache@v2
with:
key: integration-test
- name: Report disk space (after cache restore)
# Telemetry for the intermittent "No space left on device" runner crash.
# The one confirmed ENOSPC (run 35642513172) killed the runner worker as
# it wrote its own diag log to the ROOT fs (/home/runner/*), leaving no
# job log -- so record free space per mount here, where it survives in
# the step log, plus the restored cache size (the run-to-run variable).
continue-on-error: true
run: |
df -h
df -h /dev/shm
timeout 30 du -sh ~/.cargo/registry ~/.cargo/git target 2>/dev/null || true
- name: Run cargo test
# E2e tests have a separate job with shell dependencies.
run: |
# Background disk sampler: the confirmed crash killed the runner worker
# mid-test, so an after-the-fact step can't capture the fill. This
# streams free space to the live step log every 2 s; the last line
# before a crash tells us which mount hit 0 (root / vs /dev/shm).
( while true; do echo "[diskwatch] $(df -P / /dev/shm | awk 'NR>1{print $6"="$4"KB-free"}' | tr '\n' ' ')"; sleep 2; done ) &
watcher=$!
trap 'kill "$watcher" 2>/dev/null || true' EXIT
cargo nextest run --test '*' -E 'not binary(/e2e_.*/)'
env:
ATUIN_DB_URI: postgres://atuin:pass@localhost:5432/atuin
# Test databases live in tempdirs. With 8 tests writing SQLite WALs
# at once the runner disk stalls for seconds and unrelated tests miss
# their 5 s pool-open timeout; tmpfs takes fsync out of the picture.
TMPDIR: /dev/shm
# sccache: wrap rustc + disable incremental (sccache cannot cache
# incremental compilation). Endpoint/auth for Depot Cache come from
# the runner's pre-injected SCCACHE_WEBDAV_* env.
RUSTC_WRAPPER: sccache
CARGO_INCREMENTAL: "0"
- name: sccache stats (hit rate)
if: ${{ always() }}
run: sccache --show-stats
- name: Show new proptest regressions
if: ${{ failure() }}
shell: bash
run: |
echo "::group::proptest regression files changed by this run"
echo "A proptest failure appends a 'cc <seed>' line to a regression file."
echo "New/changed regression files (download the artifact below to reproduce):"
git add -N -- '*proptest-regressions*' || true
git status --porcelain
git --no-pager diff
echo "::endgroup::"
- name: Upload proptest regressions
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: proptest-regressions-integration
path: |
**/proptest-regressions/**
**/*.proptest-regressions
if-no-files-found: ignore
retention-days: 14
e2e:
name: e2e (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [depot-ubuntu-24.04, depot-macos-26]
runs-on: ${{ matrix.os }}
env:
# sccache serves compiled objects from Depot's managed WebDAV cache; keep
# incremental off (sccache can't cache incremental compilations).
RUSTC_WRAPPER: sccache
CARGO_INCREMENTAL: "0"
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install shells (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update -qq && sudo apt-get install -y -qq zsh fish
- name: Install shells (macOS)
if: runner.os == 'macOS'
run: brew install bash fish
- name: Select Homebrew Bash (macOS)
if: runner.os == 'macOS'
run: |
echo "ATUIN_E2E_BASH=$(brew --prefix bash)/bin/bash" >> "$GITHUB_ENV"
- name: Install ble.sh
run: |
mkdir -p "$HOME/.local/share"
curl -fsSL https://github.com/akinomyoga/ble.sh/releases/download/v0.4.0-devel3/ble-0.4.0-devel3.tar.xz | tar xJ -C "$HOME/.local/share"
mv "$HOME/.local/share/ble-0.4.0-devel3" "$HOME/.local/share/blesh"
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
- uses: taiki-e/install-action@v2
name: Install nextest
with:
tool: cargo-nextest
# rust-cache (warm target skip) + sccache (serves compiled crates from
# Depot's cross-branch cache); see the build job.
- uses: mozilla-actions/sccache-action@v0.0.9
- uses: Swatinem/rust-cache@v2
with:
key: e2e
- name: Run fresh-install and PTY e2e tests
run: cargo nextest run -p atuin --test 'e2e_*'
env:
ATUIN_E2E_REQUIRE_SHELLS: "1"
- name: sccache stats
if: ${{ always() }}
run: sccache --show-stats
clippy:
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install latest rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
components: clippy
# rust-cache (see check job): sccache can't cache clippy's metadata builds.
- uses: Swatinem/rust-cache@v2
with:
key: clippy
- name: Run clippy
run: cargo clippy -- -D warnings
- name: Run clippy (tests)
run: cargo clippy --tests -- -D warnings
docs:
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL dev libraries (Linux)
if: runner.os == 'Linux'
uses: awalsh128/cache-apt-pkgs-action@v1.6.3
with:
packages: libssl-dev pkg-config
version: 1.0
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
# rust-cache (see check job): sccache doesn't wrap rustdoc.
- uses: Swatinem/rust-cache@v2
with:
key: doc
- name: Run cargo doc
run: cargo doc --document-private-items --no-deps --workspace
env:
RUSTDOCFLAGS: -D warnings
format:
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install nightly rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
components: rustfmt
- name: Format
run: cargo +nightly fmt -- --check
deny:
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check
# atuin-common is a library crate; enforce (crate-scoped) that it never
# (re)adds eyre or anyhow. Config: crates/atuin-common/deny.toml
- uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: crates/atuin-common/Cargo.toml
command: check bans
# atuin-history is a library crate; enforce (crate-scoped) that it never
# (re)adds eyre or anyhow. Config: crates/atuin-history/deny.toml
- uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: crates/atuin-history/Cargo.toml
command: check bans
# atuin-domain is a library crate; enforce (crate-scoped) that it never
# (re)adds eyre or anyhow. Config: crates/atuin-domain/deny.toml
- uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: crates/atuin-domain/Cargo.toml
command: check bans
# atuin-pty-proxy is a library crate; enforce (crate-scoped) that it
# never (re)adds eyre or anyhow. Config: crates/atuin-pty-proxy/deny.toml
- uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: crates/atuin-pty-proxy/Cargo.toml
command: check bans
package:
runs-on: depot-ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.98.0
# rust-cache (see check job): bounds target/ growth for the verify build.
- uses: Swatinem/rust-cache@v2
with:
key: package
- name: Build packaged tarballs
run: |
rm -rf ~/.cargo/registry/{cache,src}/*/atuin*
rm -rf target/package
rm -rf target/{debug,release}/libatuin*.rlib
rm -rf target/{debug,release}/deps/libatuin*
rm -rf target/{debug,release}/.fingerprint/atuin*
cargo package --workspace