name: CI # Branch pushes are covered by the pull_request trigger. Listening to both for # every branch ran the whole matrix twice per PR. on: push: branches: [master] paths-ignore: ['website/**'] pull_request: branches: ['**'] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 jobs: lint: name: Lint timeout-minutes: 10 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: components: clippy - uses: Swatinem/rust-cache@v2 - name: Run clippy run: cargo clippy --workspace --all-targets --all-features -- -D warnings format: name: Format Check timeout-minutes: 5 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: components: rustfmt - name: Check formatting run: cargo fmt --all -- --check test: name: Test timeout-minutes: 20 runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] rust: [stable] steps: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 - name: Run tests run: cargo test --verbose e2e: name: End-to-end (soulfind) # The CLI suite runs twice (own login + against a daemon), ~8 minutes per # pass, plus the library and protocol suites and a soulfind build. timeout-minutes: 30 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Install SQLite runtime/dev libraries run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev - name: Install D toolchain (LDC) uses: dlang-community/setup-dlang@v2 with: compiler: ldc-latest - name: Build soulfind server run: | git clone --depth 1 https://github.com/soulfind-dev/soulfind.git soulfind dub build :server --root soulfind test -x soulfind/bin/soulfind echo "SOULFIND_BIN=$PWD/soulfind/bin/soulfind" >> "$GITHUB_ENV" - name: Run library e2e tests (required against soulfind) env: SOULSEEK_E2E_REQUIRED: "1" run: cargo test -p soulseek-rs-lib --test e2e -- --nocapture - name: Run CLI e2e tests (required against soulfind) env: SOULSEEK_E2E_REQUIRED: "1" run: cargo test -p soulseek-rs --test cli_e2e -- --nocapture # The window over a real session: keys in, a screen out, a peer on the # other end. Nothing else opens the TUI against a server. - name: Run TUI e2e tests (required against soulfind) env: SOULSEEK_E2E_REQUIRED: "1" run: cargo test -p soulseek-rs --test tui_e2e -- --nocapture # The control protocol as a third party meets it: the TCP transport, the # token, and the gate. None of it is reachable through the command # surface, so the CLI suite cannot cover it in either mode. - name: Run daemon protocol e2e tests (required against soulfind) env: SOULSEEK_E2E_REQUIRED: "1" run: cargo test -p soulseek-rs --test daemon_protocol_e2e -- --nocapture --test-threads=1 # The same suite again, with every session served by a daemon instead of # the command's own login. Identical records and exit codes both ways is # what makes daemon mode a routing decision rather than a second # implementation to keep in step. - name: Run CLI e2e tests against a daemon env: SOULSEEK_E2E_REQUIRED: "1" SOULSEEK_E2E_MODE: daemon run: cargo test -p soulseek-rs --test cli_e2e -- --nocapture --test-threads=1 # A mixed load of mock peers around one real client. Every ceiling this # project has hit only showed under simultaneous searches, downloads, # uploads and browses, and three of the four lost work silently, so the # gate is the functional dimensions at 100%, never the throughput number. stress: name: Stress (soulfind) timeout-minutes: 20 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Install SQLite runtime/dev libraries run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev - name: Install D toolchain (LDC) uses: dlang-community/setup-dlang@v2 with: compiler: ldc-latest - name: Build soulfind server run: | git clone --depth 1 https://github.com/soulfind-dev/soulfind.git soulfind dub build :server --root soulfind test -x soulfind/bin/soulfind echo "SOULFIND_BIN=$PWD/soulfind/bin/soulfind" >> "$GITHUB_ENV" # An eighth of the local profile: soulfind on a four-core runner brings # about 150 mock logins online, and the point is lost work, not load. - name: Run the stress benchmark with the functional gate env: STRESS_REQUIRE_FUNCTIONAL: "1" STRESS_PEERS: "128" STRESS_SEARCHES: "32" STRESS_DOWNLOADS: "128" STRESS_LEECHERS: "64" STRESS_BROWSES: "32" run: | ulimit -n 20000 cargo run --release -p soulseek-rs-lib --example stress