name: CI
on:
push:
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Cache Rust
uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt --all --check
test:
name: Test (${{ matrix.label }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- label: linux
os: ubuntu-latest
setup: |
sudo apt-get update
sudo apt-get install -y skopeo umoci qemu-user-static
command: |
set -euo pipefail
log="$(mktemp)"
if ! sudo --preserve-env=HOME,PATH,CARGO_HOME,RUSTUP_HOME "$(command -v cargo)" test -j"$(nproc)" 2>&1 | tee "$log"; then
echo "::error::Linux cargo test failed; recent output follows"
mapfile -t tail_lines < <(tail -n 60 "$log")
printf '%s\n' "${tail_lines[@]}"
chunk_size=20
for ((start=0; start<${#tail_lines[@]}; start+=chunk_size)); do
end=$((start + chunk_size))
if (( end > ${#tail_lines[@]} )); then
end=${#tail_lines[@]}
fi
block=$(printf '%s \\n ' "${tail_lines[@]:start:end-start}")
block=${block//'%'/'%25'}
block=${block//$'\r'/'%0D'}
block=${block//$'\n'/'%0A'}
printf '::error::Linux cargo test tail [%d-%d]: %s\n' "$((start + 1))" "$end" "$block"
done
grep -E 'test .*FAILED|failures:|panicked at|error:' "$log" | tail -n 20 | while IFS= read -r line; do
printf '::error::%s\n' "$line"
done
exit 1
fi
- label: macos
os: macos-latest
setup: ""
command: cargo test
- label: windows
os: windows-latest
setup: ""
command: cargo test
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust
uses: Swatinem/rust-cache@v2
- name: Install Linux runtime dependencies
if: matrix.setup != ''
shell: bash
run: ${{ matrix.setup }}
- name: Run test suite
shell: bash
run: ${{ matrix.command }}