Merge pull request #494 from BCNelson/bcn/e2eTesting #1152
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - dev | |
| - "feat/**" | |
| - "fix/**" | |
| pull_request: | |
| branches: [ "main", "dev" ] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUSTFLAGS: "-Dwarnings" | |
| DATABASE_URL: "postgres://postgres:postgres@localhost/oxicloud_test" | |
| jobs: | |
| # Detect which parts of the codebase changed | |
| changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| frontend: ${{ steps.filter.outputs.frontend }} | |
| backend: ${{ steps.filter.outputs.backend }} | |
| wasm: ${{ steps.filter.outputs.wasm }} | |
| plugins: ${{ steps.filter.outputs.plugins }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| frontend: | |
| - 'frontend/**' | |
| backend: | |
| - 'src/**' | |
| - 'Cargo.toml' | |
| - 'Cargo.lock' | |
| - 'tests/**' | |
| wasm: | |
| - 'wasm/**' | |
| - 'scripts/build-wasm.sh' | |
| plugins: | |
| - 'wasm/oxicloud-plugin-hello/**' | |
| - 'scripts/build-plugin-hello.sh' | |
| - 'tests/fixtures/plugins/**' | |
| - 'src/infrastructure/services/plugins/**' | |
| - 'src/application/ports/plugin_ports.rs' | |
| - 'src/application/adapters/plugin_lifecycle_hook.rs' | |
| - 'src/application/adapters/plugin_user_lifecycle_hook.rs' | |
| frontend-check: | |
| name: Frontend — svelte-check, ESLint, Stylelint, Prettier | |
| needs: changes | |
| if: needs.changes.outputs.frontend == 'true' | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 26.3.0 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Check (svelte-check + eslint + stylelint + prettier) | |
| run: npm run check | |
| - name: Unit tests | |
| run: npm run test:unit | |
| rust-fmt: | |
| name: Rustfmt | |
| needs: changes | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - run: cargo fmt --all --check | |
| rust-clippy: | |
| name: Clippy | |
| needs: changes | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| - run: cargo clippy --all-targets --all-features -- -D warnings | |
| # Mirrors the `wasm-check` justfile recipe. The wasm crate is a | |
| # standalone workspace under `wasm/oxicloud-hash/` and is NOT | |
| # built by the server's `cargo build` — these checks have to run | |
| # explicitly from inside the sub-workspace. clippy + tests run | |
| # against the HOST target (no wasm32 target needed in CI) which | |
| # is enough to cover the algorithmic logic; the wasm32 build is | |
| # exercised by `scripts/build-wasm.sh` and the frontend tests. | |
| wasm-check: | |
| name: Wasm — fmt + clippy | |
| needs: changes | |
| if: needs.changes.outputs.wasm == 'true' | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: wasm/oxicloud-hash | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: wasm/oxicloud-hash | |
| - run: cargo fmt --all --check | |
| - run: cargo clippy --all-features --release -- -D warnings | |
| # Mirrors the `wasm-test` justfile recipe. Tests run in release | |
| # mode because the FastCDC + BLAKE3 workload takes minutes in | |
| # the default debug profile (no inlining / no SIMD). | |
| wasm-test: | |
| name: Wasm — release tests | |
| needs: changes | |
| if: needs.changes.outputs.wasm == 'true' | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: wasm/oxicloud-hash | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: wasm/oxicloud-hash | |
| - run: cargo test --release | |
| # Plugin runtime (Extism). Rebuilds the committed .wasm fixtures from | |
| # wasm/oxicloud-plugin-hello/ and fails if they drift from what is | |
| # committed (staleness guard), then runs the plugin-runtime tests with | |
| # the `plugins` feature. The wasm32 target is needed only to rebuild the | |
| # fixtures; the host tests themselves do not need it. | |
| plugins: | |
| name: Plugins — fixtures + runtime tests | |
| needs: changes | |
| if: needs.changes.outputs.plugins == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Rebuild committed wasm fixtures | |
| run: bash scripts/build-plugin-hello.sh | |
| - name: Fail if fixtures are stale (rebuild + commit them) | |
| run: git diff --exit-code tests/fixtures/plugins/ | |
| - name: Run plugin runtime tests | |
| # Quote: the trailing `::` confuses GitHub's YAML parser (mapping | |
| # values not allowed) and aborts the whole workflow at load time. | |
| run: 'cargo test --features plugins plugins::' | |
| rust-test: | |
| name: Server Unit and Functionnal Tests | |
| needs: changes | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:18-alpine | |
| env: | |
| POSTGRES_USER: postgres | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: oxicloud_test | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd "pg_isready -U postgres" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Initialize test database | |
| # Applies every migration + seeds the integration-test admin row. | |
| # Same script used by `just test-integration` locally. | |
| run: bash tests/common/init-test-schema.sh | |
| env: | |
| PGHOST: localhost | |
| PGPORT: "5432" | |
| PGUSER: postgres | |
| PGPASSWORD: postgres | |
| PGDATABASE: oxicloud_test | |
| - name: Run tests | |
| run: cargo test --all-features --workspace | |
| env: | |
| DATABASE_URL: "postgres://postgres:postgres@localhost/oxicloud_test" | |
| - name: Run integration tests | |
| run: cargo test --all-features --workspace --tests | |
| env: | |
| DATABASE_URL: "postgres://postgres:postgres@localhost/oxicloud_test" | |
| RUSTFLAGS: "-Dwarnings --cfg integration_tests" | |
| rust-audit: | |
| name: Security Audit | |
| needs: changes | |
| if: needs.changes.outputs.backend == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: rustsec/audit-check@v2.0.0 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 26.3.0 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Build SPA (Vite -> static-dist/) | |
| working-directory: frontend | |
| run: npm ci && npm run build | |
| - run: cargo build --release | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: oxicloud-release | |
| path: target/release/oxicloud | |
| retention-days: 1 | |
| api-test: | |
| name: API & Webdav tests | |
| needs: build | |
| if: github.event_name == 'pull_request' | |
| timeout-minutes: 30 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: oxicloud-release | |
| path: target/release/ | |
| - name: Set execute bit on pre-built binary | |
| run: chmod +x target/release/oxicloud | |
| - name: Install Hurl, b3sum, and xq | |
| env: | |
| HURL_MAJOR: "8" | |
| # sibprogrammer/xq — standalone Go binary, real XPath via libxml2. | |
| # Pinned to match the dev-box version so the test scripts can rely | |
| # on syntax stability. Bump in lockstep with the dev install. | |
| XQ_VERSION: "1.3.0" | |
| run: | | |
| HURL_VERSION=$(curl -fsSL -H "Authorization: Bearer ${{ github.token }}" \ | |
| https://api.github.com/repos/Orange-OpenSource/hurl/releases \ | |
| | jq -r "map(select(.tag_name | startswith(\"${HURL_MAJOR}.\"))) | first | .tag_name") | |
| curl -fLO "https://github.com/Orange-OpenSource/hurl/releases/download/${HURL_VERSION}/hurl_${HURL_VERSION}_amd64.deb" | |
| sudo apt-get install -y "./hurl_${HURL_VERSION}_amd64.deb" b3sum | |
| curl -fLO "https://github.com/sibprogrammer/xq/releases/download/v${XQ_VERSION}/xq_${XQ_VERSION}_linux_amd64.tar.gz" | |
| tar -xzf "xq_${XQ_VERSION}_linux_amd64.tar.gz" xq | |
| sudo install -m 0755 xq /usr/local/bin/xq | |
| - name: Run Hurl API tests | |
| run: bash tests/api/run.sh | |
| env: | |
| BUILD_TARGET: release | |
| - name: Run Webdav tests | |
| run: bash tests/webdav/run.sh | |
| env: | |
| BUILD_TARGET: release | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: hurl-report | |
| path: tests/api/storage/ | |
| retention-days: 7 | |
| front-test: | |
| name: Frontend end-to-end tests (via Playwright) | |
| # ensure that api tests are ok before | |
| needs: api-test | |
| if: github.event_name == 'pull_request' | |
| timeout-minutes: 60 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: oxicloud-release | |
| path: target/release/ | |
| - name: Set execute bit on pre-built binary | |
| run: chmod +x target/release/oxicloud | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 26.3.0 | |
| - name: Install Node dependencies | |
| working-directory: tests/e2e | |
| run: npm ci | |
| # The release binary serves the SPA from ./static-dist on disk (not | |
| # embedded), and the Build job builds it WITHOUT VITE_E2E so it lacks the | |
| # `data-testid` hooks the specs target. Build it here with VITE_E2E=1 so | |
| # the server actually serves the e2e SPA the scenarios drive. | |
| - name: Build SPA for e2e (VITE_E2E keeps data-testid hooks) | |
| working-directory: frontend | |
| run: npm ci && VITE_E2E=1 npm run build | |
| - name: Install Playwright browsers | |
| working-directory: tests/e2e | |
| run: npx playwright install --with-deps | |
| - name: Run Playwright tests (spawns DB via pretest hook) | |
| working-directory: tests/e2e | |
| run: npm test | |
| env: | |
| BUILD_TARGET: release | |
| - name: Print server startup log | |
| if: always() | |
| run: cat tests/e2e/server-startup.log || echo "no server-startup.log produced" | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: playwright-report | |
| path: tests/e2e/playwright-report/ | |
| retention-days: 30 |