name: CI
on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]
jobs:
test:
name: test-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Clone sibling rust-fs-core
run: git clone --depth 1 --branch v0.2.5 https://github.com/antimatter-studios/rust-fs-core.git ../rust-fs-core
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install qemu (for test-disk generator)
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq qemu-system-x86 libarchive-tools
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Cache alpine VM assets
uses: actions/cache@v4
with:
path: test-disks/.vm-cache
key: vm-cache-alpine-3.21.4
- name: Generate test disks
run: bash test-disks/build-ext4-feature-images.sh
- run: cargo fmt --check
- run: cargo clippy --locked --all-targets -- -D warnings
- run: cargo test --locked --release
- name: Check aarch64-linux (c_char is unsigned there)
run: |
rustup target add aarch64-unknown-linux-gnu
cargo check --locked --all-targets --target aarch64-unknown-linux-gnu
validate-mkfs-bin:
name: validate mkfs_ext4 (fsck.ext4 strict)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Clone sibling rust-fs-core
run: git clone --depth 1 --branch v0.2.5 https://github.com/antimatter-studios/rust-fs-core.git ../rust-fs-core
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install e2fsprogs
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq e2fsprogs
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-mkfs-${{ hashFiles('**/Cargo.lock') }}
- name: Build mkfs_ext4
run: cargo build --locked --release --bin mkfs_ext4
- name: Format 32 MiB image and validate with fsck.ext4
run: |
truncate -s 32M /tmp/out.img
./target/release/mkfs_ext4 -L CITEST -U deadbeef-cafe-1234-5678-0123456789ab /tmp/out.img
# -f forces a check even if FS thinks it's clean; -n declines
# any repair offer (so this is read-only and exits non-zero
# if anything is wrong rather than silently auto-fixing).
fsck.ext4 -fnv /tmp/out.img
- name: Format multi-group images and validate with fsck.ext4
run: |
truncate -s 320M /tmp/mg3.img
truncate -s 640M /tmp/mg5.img
./target/release/mkfs_ext4 -L CIMULTI3 /tmp/mg3.img
./target/release/mkfs_ext4 -L CIMULTI5 /tmp/mg5.img
fsck.ext4 -fnv /tmp/mg3.img
fsck.ext4 -fnv /tmp/mg5.img
# Open each one through a BACKUP superblock too. The primary is
# what the checks above read; -b points fsck at a backup instead,
# so its s_block_group_nr and its recomputed checksum have to be
# right or the open fails outright. Block 32768 is group 1 and
# block 98304 is group 3, at 4 KiB blocks.
fsck.ext4 -fn -b 32768 -B 4096 /tmp/mg3.img
fsck.ext4 -fn -b 32768 -B 4096 /tmp/mg5.img
fsck.ext4 -fn -b 98304 -B 4096 /tmp/mg5.img
# The group table is where a short final group shows up: group 2 of
# mg3.img must end at the last block of the device (81919), not at
# a full group boundary.
dumpe2fs /tmp/mg3.img | grep -E '^Group [0-9]+:'
dumpe2fs /tmp/mg3.img | grep -q 'Group 2: (Blocks 65536-81919)'
- name: Verify volume label and UUID round-tripped
run: |
# tune2fs prints the on-disk superblock metadata; grep confirms
# the CLI args propagated to the bytes fsck just validated.
tune2fs -l /tmp/out.img > /tmp/sb.txt
cat /tmp/sb.txt
grep -q "Filesystem volume name:.*CITEST" /tmp/sb.txt
grep -qi "Filesystem UUID:.*deadbeef-cafe-1234-5678-0123456789ab" /tmp/sb.txt