name: CI
on:
push:
branches: [main]
tags: ["v[0-9]+.[0-9]+.[0-9]+"]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
LC_ALL: C.UTF-8
permissions:
contents: read
jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
name: clippy (deny warnings)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features -- -D warnings
audit:
name: cargo audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@v2
with:
tool: cargo-audit
- run: cargo audit
env:
RUSTUP_TOOLCHAIN: stable
deny:
name: cargo deny (licenses)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@v2
with:
tool: cargo-deny
- run: cargo deny check licenses
env:
RUSTUP_TOOLCHAIN: stable
msrv:
name: MSRV (1.85)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.85
- uses: Swatinem/rust-cache@v2
- run: cargo build --all-features
- run: cargo test --all-features
test-default:
name: test-default ${{ matrix.target }}
needs: [fmt, clippy]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, cross: true }
- { os: macos-latest, target: x86_64-apple-darwin }
- { os: macos-latest, target: aarch64-apple-darwin }
- { os: windows-latest, target: x86_64-pc-windows-msvc }
env:
LC_ALL: C.UTF-8
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Add cross-compile target to 1.85 toolchain
if: '!matrix.cross'
run: rustup target add ${{ matrix.target }} --toolchain 1.85
shell: bash
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install cross
if: matrix.cross
run: cargo install cross --locked
- name: Build
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
cross build --release --target ${{ matrix.target }} --all-features
else
cargo build --release --target ${{ matrix.target }} --all-features
fi
shell: bash
- name: Test
if: matrix.cross != true
run: cargo test --release --target ${{ matrix.target }} --all-features
test-no-default:
name: test-no-default (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --no-default-features
- run: cargo test --no-default-features --lib
- name: Dep-tree audit (SC-001)
run: |
# Assert no CLI-only deps leak into the bare-library build.
if cargo tree --no-default-features --prefix none --edges normal --no-dedupe \
| grep -E '^(clap|clap_complete|anstyle|termcolor|terminal_size)'; then
echo "::error::CLI-only dep leaked into --no-default-features build"
exit 1
fi
test-figlet-classic:
name: test-figlet-classic (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --no-default-features --features figlet-classic
- run: cargo test --no-default-features --features figlet-classic --lib
test-figlet-minimal:
name: test-figlet-minimal (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --no-default-features --features figlet-minimal
- run: cargo test --no-default-features --features figlet-minimal --lib
test-figlet-toilet-compat:
name: test-figlet-toilet-compat (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --no-default-features --features figlet-toilet-compat
- run: cargo test --no-default-features --features figlet-toilet-compat --lib
check-leaf-color:
name: check-leaf-color (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo check --no-default-features --features "cli color"
check-leaf-rainbow:
name: check-leaf-rainbow (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo check --no-default-features --features "cli rainbow"
check-leaf-terminal-width:
name: check-leaf-terminal-width (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo check --no-default-features --features "cli terminal-width"
check-leaf-completions:
name: check-leaf-completions (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo check --no-default-features --features "cli completions"
check-leaf-strict-compat:
name: check-leaf-strict-compat (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo check --no-default-features --features "cli strict-compat"
lint-convention:
name: lint-convention (linux-x86_64)
needs: [fmt, clippy]
runs-on: ubuntu-latest
steps:
- name: Checkout port
uses: actions/checkout@v4
- name: Run feature-lint
env:
UMBRELLA_PATH: ${{ github.workspace }}
PORT_PATH: ${{ github.workspace }}
run: bash tools/feature-lint/run.sh
convention-lint-self-test:
name: convention-lint-self-test
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout port
uses: actions/checkout@v4
- name: Remove figlet-classic umbrella from Cargo.toml
run: |
sed -i '/^figlet-classic\s*=/d' Cargo.toml
# Verify removal
if grep -E '^figlet-classic\s*=' Cargo.toml; then
echo "::error::figlet-classic removal failed"
exit 1
fi
- name: Invoke feature-lint and expect non-zero exit
env:
UMBRELLA_PATH: ${{ github.workspace }}
PORT_PATH: ${{ github.workspace }}
run: |
set +e
bash tools/feature-lint/run.sh 2>stderr.log
rc=$?
set -e
cat stderr.log
if [ "$rc" = "0" ]; then
echo "::error::feature-lint should have failed with exit 2 but returned 0"
exit 1
fi
if ! grep -q "required umbrella 'figlet-classic' missing" stderr.log; then
echo "::error::expected diagnostic 'required umbrella figlet-classic missing' not found"
exit 1
fi
echo "convention-lint-self-test: PASS"
publish-dry-run:
name: cargo publish --dry-run
needs:
- fmt
- clippy
- audit
- deny
- msrv
- test-default
- test-no-default
- test-figlet-classic
- test-figlet-minimal
- test-figlet-toilet-compat
- check-leaf-color
- check-leaf-rainbow
- check-leaf-terminal-width
- check-leaf-completions
- check-leaf-strict-compat
- lint-convention
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: cargo publish --dry-run --all-features