diff --git a/.github/actions/setup-nix/action.yml b/.github/actions/setup-nix/action.yml new file mode 100644 index 0000000..2c565a6 --- /dev/null +++ b/.github/actions/setup-nix/action.yml @@ -0,0 +1,40 @@ +name: Setup Nix +description: Install Nix with dev shell and optional KVM support + +inputs: + enable-kvm: + description: Enable KVM for NixOS VM tests + default: 'false' + +runs: + using: composite + steps: + - name: Enable KVM group permissions + if: inputs.enable-kvm == 'true' + shell: bash + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + system-features = nixos-test benchmark big-parallel kvm + + - name: Setup magic-nix-cache + uses: DeterminateSystems/magic-nix-cache-action@main + + - name: Install direnv + shell: bash + run: | + nix profile install nixpkgs#direnv nixpkgs#nix-direnv + echo 'source $HOME/.nix-profile/share/nix-direnv/direnvrc' >> "$HOME/.direnvrc" + + - name: Load dev shell environment + shell: bash + run: | + direnv allow . + direnv export json | jq -r 'to_entries[] | select(.value | contains("\n") | not) | "\(.key)=\(.value)"' >> "$GITHUB_ENV" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a5378d1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,91 @@ +name: CI + +on: + push: + branches: [master, main] + pull_request: + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: "-D warnings" + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/setup-nix + + - name: Cache cargo + uses: Swatinem/rust-cache@v2 + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Build all crates + run: cargo build --all-targets + + - name: Run unit tests + run: cargo test --workspace --exclude portalbd-dst + + dst-quick: + runs-on: ubuntu-latest + needs: [check] + steps: + - uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/setup-nix + + - name: Cache cargo + uses: Swatinem/rust-cache@v2 + + - name: Run quick DST (100 iterations) + env: + RUSTFLAGS: "--cfg tokio_unstable" + run: cargo test -p portalbd-dst simulation + + build: + runs-on: ubuntu-latest + needs: [check] + steps: + - uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/setup-nix + + - name: Build portalbd + run: nix build + + nixos-tests: + runs-on: ubuntu-latest + needs: [build] + strategy: + fail-fast: false + matrix: + test: + - basic + - crash-recovery + - snapshot-semantics + - resource-exhaustion + - pjdfs + - csi-node + - csi-k3s + - trace-mkfs + - trace-pgbench + - trace-minecraft + steps: + - uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/setup-nix + with: + enable-kvm: 'true' + + - name: Run ${{ matrix.test }} test + run: nix run -L .#test-${{ matrix.test }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..7b11c99 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,43 @@ +name: Nightly DST + +on: + schedule: + # Run at 2 AM UTC every day + - cron: '0 2 * * *' + workflow_dispatch: + inputs: + seed: + description: 'Optional seed for reproducible DST run' + required: false + type: string + +env: + CARGO_TERM_COLOR: always + +jobs: + dst-nightly: + runs-on: ubuntu-latest + timeout-minutes: 120 + steps: + - uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/setup-nix + + - name: Run nightly DST (long-running) + env: + RUSTFLAGS: "--cfg tokio_unstable" + DST_SEED: ${{ inputs.seed }} + run: | + echo "Starting nightly DST run at $(date)" + cargo test -p portalbd-dst simulation -- --ignored --nocapture + echo "Completed nightly DST run at $(date)" + + - name: Upload failure artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: dst-failure-${{ github.run_id }} + path: target/dst-failures/ + if-no-files-found: ignore + retention-days: 30