name: CI
on:
pull_request:
push:
branches:
- main
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system dependencies
run: sudo apt-get install -y libdbus-1-dev
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2
- name: Lint
run: cargo clippy --all-targets --all-features -- -D warnings
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system dependencies
run: sudo apt-get install -y libdbus-1-dev bubblewrap
- name: Allow bwrap unprivileged user namespaces
run: |
echo 'abi <abi/4.0>,' | sudo tee /etc/apparmor.d/bwrap
echo 'include <tunables/global>' | sudo tee -a /etc/apparmor.d/bwrap
echo 'profile bwrap /usr/bin/bwrap flags=(unconfined) {' | sudo tee -a /etc/apparmor.d/bwrap
echo ' userns,' | sudo tee -a /etc/apparmor.d/bwrap
echo '}' | sudo tee -a /etc/apparmor.d/bwrap
sudo apparmor_parser -r /etc/apparmor.d/bwrap
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2
- name: Run tests
run: cargo test --all-targets --all-features
publish-dry-run:
name: Publish Dry Run
if: ${{ !startsWith(github.head_ref, 'release-please--') }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system dependencies
run: sudo apt-get install -y libdbus-1-dev
- name: Install toolchain
uses: dtolnay/rust-toolchain@stable
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2
- name: Validate crates.io package
shell: bash
run: |
set -euo pipefail
# Publish in dependency order matching release.yml.
# - Skip crates that already exist on crates.io (idempotent).
# - Skip crates whose workspace dependencies haven't been
# published yet (valid for newly-added protocol crates before
# their first release).
CRATES=(
earl-core
earl-protocol-http
earl-protocol-grpc
earl-protocol-bash
earl-protocol-sql
earl-protocol-browser
earl
)
for crate in "${CRATES[@]}"; do
echo "Dry-run for $crate..."
output=$(cargo publish --dry-run --locked --no-verify -p "$crate" 2>&1) && echo "$output" || {
if echo "$output" | grep -q "already exists on crates.io index"; then
echo "$crate already on crates.io, skipping."
elif echo "$output" | grep -q "no matching package named"; then
echo "$crate has unpublished workspace dependencies, skipping."
else
echo "$output" >&2
exit 1
fi
}
done