Skip to content

build(snap): let rust deps provide toolchain #280

build(snap): let rust deps provide toolchain

build(snap): let rust deps provide toolchain #280

Workflow file for this run

name: CI
on:
push:
branches:
- main
- "release/**"
tags:
- "v*"
pull_request:
branches:
- main
- "release/**"
workflow_dispatch:
inputs:
windows_runtime_smoke:
description: Run native Windows runtime smoke checks
required: false
default: false
type: boolean
permissions:
contents: read
env:
CARGO_INCREMENTAL: "0"
CARGO_HTTP_MULTIPLEXING: "false"
CARGO_TERM_COLOR: always
RUSTDOCFLAGS: -D warnings
TMPDIR: /tmp
RMUX_TMPDIR: /tmp
jobs:
linux-quality:
name: Linux format, lint, and docs
runs-on: ubuntu-latest
env:
RUST_MIN_STACK: "8388608"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Fetch locked dependencies
run: cargo fetch --locked
- name: Install audit tooling
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends ripgrep
- name: cargo fmt
run: cargo fmt --all -- --check
- name: cargo clippy
run: cargo clippy --workspace --all-targets --locked -- -D warnings
- name: Await-under-lock audit
run: scripts/audit-await-holding-lock.sh
- name: rustdoc with warnings denied
run: cargo doc --workspace --locked --no-deps
linux-build:
name: Linux workspace build
runs-on: ubuntu-latest
env:
RUST_MIN_STACK: "8388608"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Fetch locked dependencies
run: cargo fetch --locked
- name: cargo build
run: cargo build --workspace --locked
wasm-crypto:
name: WASM crypto build and supply-chain gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
# Pin the exact rustc that reproduces the shipped browser blob (mirrored
# in rmux-web-share PROVENANCE.json toolchain.rustc). A floating "stable"
# changes codegen and would break byte-for-byte reproducibility — the
# property rmux-web-share's verify-wasm-from-source.mjs gate enforces.
toolchain: "1.94.1"
targets: wasm32-unknown-unknown
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Fetch locked dependencies
run: cargo fetch --locked
# The browser bundle must NOT carry x25519-dalek/curve25519-dalek; the
# WebCrypto path replaces them. cargo tree -i exits non-zero when the
# package is absent, so success here means it leaked — fail closed.
- name: Assert x25519-dalek is excluded from the WASM build
run: |
if cargo tree -p rmux-web-crypto --no-default-features --features wasm --target wasm32-unknown-unknown -i x25519-dalek >/dev/null 2>&1; then
echo "::error::x25519-dalek must not enter the WASM crypto build"
exit 1
fi
echo "x25519-dalek correctly excluded from the WASM crypto build"
# Regression guard for the browser test gate: the wasm-test feature set must
# compile its test targets (tests/handshake.rs is x25519-gated out).
- name: Compile the wasm-test gate
run: cargo test -p rmux-web-crypto --no-default-features --features wasm-test --no-run --locked
- name: Install pinned wasm-pack
run: cargo install wasm-pack --version 0.13.1 --locked
# Rebuild the exact blobs rmux-web-share ships, via the canonical recipe and
# pinned toolchain, and publish them as an artifact for manual auditors. The
# authoritative byte-equality-to-shipped check is cross-repo, in
# rmux-web-share's verify-wasm-from-source.mjs (which rebuilds from this
# source at the pinned commit); here we prove the recipe still produces the
# browser primitive and expose the canonical bytes + their hashes.
- name: Build and publish the browser WASM blobs
env:
RUSTUP_TOOLCHAIN: "1.94.1"
run: |
set -euo pipefail
scripts/build-web-crypto-wasm.sh wasm
mkdir -p "$RUNNER_TEMP/wasm-pkg"
cp crates/rmux-web-crypto/pkg/rmux_web_crypto_wasm_bg.wasm \
crates/rmux-web-crypto/pkg/rmux_web_crypto_wasm.js \
"$RUNNER_TEMP/wasm-pkg/"
# The Playwright-only blob shares the recipe; build it too so a break in
# the test feature set is caught here, not in rmux-web-share CI.
scripts/build-web-crypto-wasm.sh wasm-test
{
echo "### Browser WASM crypto blob (production)"
echo ""
echo "rustc 1.94.1 · wasm-bindgen 0.2.123 · wasm-opt off"
echo ""
echo '```'
( cd "$RUNNER_TEMP/wasm-pkg" && sha256sum rmux_web_crypto_wasm_bg.wasm rmux_web_crypto_wasm.js )
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: rmux-web-crypto-wasm
path: ${{ runner.temp }}/wasm-pkg
if-no-files-found: error
linux-tests:
name: Linux tests (${{ matrix.group }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- group: core
packages: -p rmux-types -p rmux-os -p rmux-proto -p rmux-ipc -p rmux-core -p rmux-client -p rmux-render-core -p rmux-web-crypto
- group: pty-sdk
packages: -p rmux-pty -p rmux-sdk
- group: server
packages: -p rmux-server
- group: app-ui
packages: -p rmux -p ratatui-rmux -p xtask
env:
RUST_MIN_STACK: "8388608"
RUST_TEST_THREADS: "1"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ matrix.group }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ matrix.group }}-
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Fetch locked dependencies
run: cargo fetch --locked
- name: cargo test
run: cargo test --locked --no-fail-fast ${{ matrix.packages }}
linux-source-gates:
name: Linux source boundary gates
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- name: Unsafe policy gate
run: scripts/unsafe-check.sh
- name: No network scoped runtime source scan
run: scripts/no-network-in-runtime.sh
- name: Platform neutrality source scan
run: scripts/check-platform-neutrality.sh
- name: No side effects in debug assertions
run: scripts/no-debug-assert-side-effects.sh
release-review-gate:
name: Release review gate (no package)
runs-on: ubuntu-latest
env:
RUST_MIN_STACK: "8388608"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
components: clippy, rustfmt
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Fetch locked dependencies
run: cargo fetch --locked
- name: Release review gate
run: scripts/release-review-gate.sh --skip-package --target-dir target/release-review-ci
snap-package:
name: Snap package smoke
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- name: Build snap
id: snapcraft
uses: snapcore/action-build@3bdaa03e1ba6bf59a65f84a751d943d549a54e79
with:
path: .
- name: Smoke snap package
run: scripts/smoke-snap-package.sh "${{ steps.snapcraft.outputs.snap }}"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: rmux-snap-${{ github.sha }}
path: ${{ steps.snapcraft.outputs.snap }}
if-no-files-found: error
nix-flake:
name: Nix flake gate
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- name: Install Nix
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: nix flake check
run: nix flake check
- name: nix build
run: nix build .#packages.x86_64-linux.default --no-link
- name: nix run version matches Cargo.toml
run: |
set -euo pipefail
expected="$(python3 - <<'PY'
import pathlib
import tomllib
manifest = tomllib.loads(pathlib.Path("Cargo.toml").read_text())
print(manifest["workspace"]["package"]["version"])
PY
)"
actual="$(nix run . -- -V)"
if [ "$actual" != "rmux $expected" ]; then
echo "::error::expected 'rmux $expected', got '$actual'"
exit 1
fi
linux-sdk-smoke:
name: Linux SDK v1 daemon smoke
runs-on: ubuntu-latest
env:
RUST_MIN_STACK: "8388608"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: SDK v1 daemon smoke
run: scripts/smoke-sdk-v1.sh
linux-perf-smoke:
name: Linux non-final performance smoke
runs-on: ubuntu-latest
env:
RUST_MIN_STACK: "8388608"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Non-final local performance budget smoke
run: scripts/perf-bench.sh --iterations 3 --line-count 10000 --output-dir target/perf/non-final-ci --fail-on-budget
- name: Issue 34 responsiveness smoke
env:
RMUX_BIN: target/release/rmux
run: scripts/smoke-issue34-responsiveness-unix.sh
- name: RSS and FD drift smoke
env:
RMUX_BIN: target/release/rmux
run: scripts/smoke-rss-fd-drift-unix.sh
linux-dependency-audit:
name: Linux dependency audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/bin/cargo-deny
~/.cargo/git
~/.cargo/registry
key: cargo-deny-${{ runner.os }}-${{ runner.arch }}-0.19.5-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-deny-${{ runner.os }}-${{ runner.arch }}-0.19.5-
- name: Install cargo-deny
if: hashFiles('deny.toml') != ''
run: |
if ! command -v cargo-deny >/dev/null 2>&1; then
cargo install cargo-deny --version 0.19.5 --locked
fi
- name: cargo deny check
if: hashFiles('deny.toml') != ''
run: cargo deny check
platform-runtime:
name: Platform build and smoke on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- macos-15-intel
- macos-15
- windows-latest
env:
RUST_MIN_STACK: "8388608"
RUST_TEST_THREADS: "1"
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ matrix.os }}-platform-runtime-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ matrix.os }}-platform-runtime-
- name: Configure temporary paths
shell: bash
run: |
echo "TMPDIR=$RUNNER_TEMP" >> "$GITHUB_ENV"
echo "RMUX_TMPDIR=$RUNNER_TEMP" >> "$GITHUB_ENV"
- name: Fetch locked dependencies
run: cargo fetch --locked
- name: cargo build
run: cargo build --workspace --locked
- name: cargo test portable crates
if: runner.os != 'Windows'
run: cargo test --locked --no-fail-fast -p rmux-types -p rmux-os -p rmux-proto -p rmux-ipc -p rmux-core -p rmux-client
- name: cargo test macOS direct /tmp socket path
if: runner.os == 'macOS'
run: cargo test --locked -p rmux --test cli_surface socket_path_flag_can_start_directly_under_tmp -- --exact --test-threads=1
- name: cargo test workspace on Windows
if: runner.os == 'Windows'
run: cargo test --workspace --locked --no-fail-fast -- --test-threads=1
- name: rmux binary smoke
run: cargo run --package rmux --bin rmux --locked -- -V
windows-cross:
name: Cross-target Windows build check
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
targets: x86_64-pc-windows-gnu
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Install Windows GNU linker
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends gcc-mingw-w64-x86-64
- name: cargo build Windows target
run: cargo build --workspace --locked --target x86_64-pc-windows-gnu
windows-runtime-smoke:
name: Native Windows runtime smoke
if: startsWith(github.ref, 'refs/tags/v') || (github.event_name == 'workflow_dispatch' && inputs.windows_runtime_smoke)
runs-on: windows-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
with:
toolchain: stable
- name: Cache cargo
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-
cargo-${{ runner.os }}-${{ runner.arch }}-
- name: Windows hidden daemon smoke
run: cargo test --locked --test internal_daemon_windows -- --nocapture
- name: Windows named-pipe IPC smoke
run: cargo test -p rmux-ipc --locked --test named_pipe_integration -- --nocapture