Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1e60b23
Fix rootless clone port forwarding and add test isolation
ejc3 Dec 21, 2025
efb99c2
Enable parallel test execution with proper root/rootless isolation
ejc3 Dec 21, 2025
c2d052b
Fix rootless podman container export by normalizing file ownership
ejc3 Dec 21, 2025
e5df0d3
Run rootless container tests as testuser, not root
ejc3 Dec 21, 2025
8c5fcdc
Trigger CI rebuild (clear podman cache)
ejc3 Dec 21, 2025
ec6ed7e
Run bridged tests before rootless to ensure rootfs exists
ejc3 Dec 21, 2025
411e5e1
Fix rootless container tests with rootless podman
ejc3 Dec 21, 2025
8dd5c5a
Add /dev/userfaultfd device for rootless container clone tests
ejc3 Dec 21, 2025
604d12a
Add userfaultfd setup to CI for snapshot clone tests
ejc3 Dec 21, 2025
c54c4fc
Fix VM test race condition by running jobs sequentially
ejc3 Dec 21, 2025
c3cd727
Debug: investigate virt-customize hang on BuildJet
ejc3 Dec 21, 2025
37fa51e
Debug: test virt-customize INSIDE container (matching local)
ejc3 Dec 21, 2025
99d9ec6
Debug: run actual fcvm rootfs creation in container
ejc3 Dec 21, 2025
7f84a27
Fix VM test race condition by running jobs sequentially
ejc3 Dec 21, 2025
ace36b3
Consolidate CI jobs to reduce redundant compilation
ejc3 Dec 21, 2025
d3c0a35
CI: Build once, test in parallel with artifact sharing
ejc3 Dec 21, 2025
752d048
CI: Add descriptive job names with environment info
ejc3 Dec 21, 2025
f0e9f3e
Rootless Layer 2 rootfs creation via initrd-based setup
ejc3 Dec 22, 2025
56b2397
Use Kata kernel with FUSE support, embed packages in initrd
ejc3 Dec 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
272 changes: 78 additions & 194 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,9 @@ env:
CARGO_TERM_COLOR: always

jobs:
# Fast jobs run in parallel on every PR and push

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: fcvm
- uses: actions/checkout@v4
with:
repository: ejc3/fuse-backend-rs
ref: master
path: fuse-backend-rs
- uses: actions/checkout@v4
with:
repository: ejc3/fuser
ref: master
path: fuser
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- name: Install cargo-machete
run: cargo install cargo-machete
- name: Check formatting
working-directory: fcvm
run: cargo fmt --all -- --check
- name: Clippy
working-directory: fcvm
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Check unused dependencies
working-directory: fcvm
run: cargo machete

# Build inside container, upload artifacts for parallel test jobs
build:
name: Build
name: Build [container/ubuntu-latest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -61,16 +28,29 @@ jobs:
repository: ejc3/fuser
ref: master
path: fuser
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: fcvm
- name: Build
- name: Build inside container
working-directory: fcvm
run: cargo build --release --all-targets
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
export CI=1
make container-build-only
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: container-build
path: |
fcvm/target/release
!fcvm/target/release/.fingerprint
!fcvm/target/release/build
!fcvm/target/release/deps
!fcvm/target/release/incremental
retention-days: 1

test-unit:
name: Unit Tests
# Lint runs in parallel with build (just needs source)
lint:
name: Lint (fmt+clippy+machete) [host/ubuntu-latest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -87,68 +67,26 @@ jobs:
ref: master
path: fuser
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: fcvm
- name: Run unit tests
working-directory: fcvm
run: cargo test --release --lib --all

test-fuse-integration:
name: FUSE Integration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: fcvm
- uses: actions/checkout@v4
with:
repository: ejc3/fuse-backend-rs
ref: master
path: fuse-backend-rs
- uses: actions/checkout@v4
with:
repository: ejc3/fuser
ref: master
path: fuser
- uses: dtolnay/rust-toolchain@stable
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
with:
workspaces: fcvm
- name: Build
- name: Check formatting
working-directory: fcvm
run: cargo build --release -p fuse-pipe
- name: Run integration_root tests
run: cargo fmt --all -- --check
- name: Clippy
working-directory: fcvm
run: sudo -E env "PATH=$PATH" cargo test --release -p fuse-pipe --test integration_root -- --test-threads=1

test-fuse-noroot:
name: FUSE No-Root
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: fcvm
- uses: actions/checkout@v4
with:
repository: ejc3/fuse-backend-rs
ref: master
path: fuse-backend-rs
- uses: actions/checkout@v4
with:
repository: ejc3/fuser
ref: master
path: fuser
- name: Run no-root FUSE tests (container)
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Install cargo-machete
run: cargo install cargo-machete
- name: Check unused dependencies
working-directory: fcvm
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-noroot
run: cargo machete

test-cli:
name: CLI Tests
# Native tests use rust-cache (compiles incrementally)
test-native:
name: Unit+CLI+FUSE-root [host/ubuntu-latest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -168,12 +106,20 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: fcvm
- name: Run CLI tests
- name: Unit tests
working-directory: fcvm
run: cargo test --release --lib --all
- name: CLI tests
working-directory: fcvm
run: cargo test --release --test test_cli_parsing --test test_state_manager
- name: FUSE integration tests (root)
working-directory: fcvm
run: sudo -E env "PATH=$PATH" cargo test --release -p fuse-pipe --test integration_root -- --test-threads=1

test-fuse-permissions:
name: FUSE Permissions
# Container FUSE tests - download pre-built artifacts
fuse-tests:
name: FUSE (noroot+root) [container/ubuntu-latest]
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -189,16 +135,25 @@ jobs:
repository: ejc3/fuser
ref: master
path: fuser
- name: Run permission tests (container)
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: container-build
path: fcvm/target/release
- name: Run FUSE tests (container, no rebuild)
working-directory: fcvm
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-root
export CI=1
mkdir -p cargo-home
make container-test

test-pjdfstest:
name: POSIX Compliance
# POSIX compliance - download pre-built artifacts
posix-compliance:
name: POSIX (pjdfstest 8789) [container/ubuntu-latest]
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -214,66 +169,25 @@ jobs:
repository: ejc3/fuser
ref: master
path: fuser
- name: Run pjdfstest (container)
working-directory: fcvm
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-pjdfstest

test-vm-sanity:
name: VM Sanity
runs-on: buildjet-32vcpu-ubuntu-2204
steps:
- uses: actions/checkout@v4
with:
path: fcvm
- uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
repository: ejc3/fuse-backend-rs
ref: master
path: fuse-backend-rs
- uses: actions/checkout@v4
with:
repository: ejc3/fuser
ref: master
path: fuser
- name: Check KVM availability
run: |
echo "=== KVM device ==="
ls -la /dev/kvm || echo "No /dev/kvm"
echo "=== CPU virtualization ==="
grep -E "(vmx|svm)" /proc/cpuinfo | head -1 || echo "No VMX/SVM"
echo "=== KVM modules ==="
lsmod | grep kvm || echo "No KVM modules"
- name: Setup KVM permissions
run: sudo chmod 666 /dev/kvm
- name: Setup NBD module for rootfs extraction
run: |
sudo modprobe nbd max_part=8
ls -la /dev/nbd* | head -5
- name: Setup network namespace directory
run: sudo mkdir -p /var/run/netns
- name: Setup iptables for VM networking
run: |
# BuildJet runners have FORWARD chain set to DROP by default
# Set to ACCEPT and add MASQUERADE rule for VM NAT
sudo iptables -P FORWARD ACCEPT
sudo iptables -t nat -A POSTROUTING -s 172.30.0.0/16 -o eth0 -j MASQUERADE || true
- name: Run VM sanity test (bridged)
name: container-build
path: fcvm/target/release
- name: Run pjdfstest (container, no rebuild)
working-directory: fcvm
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-vm-bridged
export CI=1
mkdir -p cargo-home
make container-test-pjdfstest

test-vm-exec:
name: VM Exec
# VM tests on BuildJet - builds inside container (separate from ubuntu-latest)
vm-tests:
name: VM (bridged+rootless) [container/buildjet-32cpu]
runs-on: buildjet-32vcpu-ubuntu-2204
needs: test-vm-sanity # Sequential: flock doesn't work across podman containers sharing /dev/nbd0
if: always() # Run even if previous job failed (rootfs will be cached after first success)
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -298,47 +212,17 @@ jobs:
run: |
sudo iptables -P FORWARD ACCEPT
sudo iptables -t nat -A POSTROUTING -s 172.30.0.0/16 -o eth0 -j MASQUERADE || true
- name: Run VM exec tests
working-directory: fcvm
- name: Setup userfaultfd for snapshot cloning
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-vm-exec

test-vm-egress:
name: VM Egress
runs-on: buildjet-32vcpu-ubuntu-2204
needs: test-vm-exec # Sequential: flock doesn't work across podman containers sharing /dev/nbd0
if: always() # Run even if previous job failed (rootfs will be cached after first success)
steps:
- uses: actions/checkout@v4
with:
path: fcvm
- uses: actions/checkout@v4
with:
repository: ejc3/fuse-backend-rs
ref: master
path: fuse-backend-rs
- uses: actions/checkout@v4
with:
repository: ejc3/fuser
ref: master
path: fuser
- name: Setup KVM permissions
run: sudo chmod 666 /dev/kvm
- name: Setup NBD module
run: sudo modprobe nbd max_part=8
- name: Setup network namespace directory
run: sudo mkdir -p /var/run/netns
- name: Setup iptables for VM networking
run: |
sudo iptables -P FORWARD ACCEPT
sudo iptables -t nat -A POSTROUTING -s 172.30.0.0/16 -o eth0 -j MASQUERADE || true
- name: Run VM egress tests
if [ ! -e /dev/userfaultfd ]; then
sudo mknod /dev/userfaultfd c 10 126
fi
sudo chmod 666 /dev/userfaultfd
sudo sysctl -w vm.unprivileged_userfaultfd=1
- name: Run all VM tests
working-directory: fcvm
run: |
export FUSE_BACKEND_RS=${{ github.workspace }}/fuse-backend-rs
export FUSER=${{ github.workspace }}/fuser
export CONTAINER_ARCH=x86_64
make container-test-vm-egress
make container-test-vm
Loading
Loading