distributed 4.7.0

CQRS/ES framework for Rust using Plain Old Rust Structs — append-only events, replay, snapshots, outbox, service bus, and pluggable infrastructure
Documentation
name: e2e-ui fixture (offline + browser)

# Nested Todos template under tests/e2e-ui — not the root workspace.
# Local parity:
#   cd tests/e2e-ui && make check-client
#   cd tests/e2e-ui && make test
#   cd tests/e2e-ui && make ci-offline
#   cd tests/e2e-ui && make up && make run   # distributed dev; then make test-browser
on:
  workflow_call:

env:
  CARGO_TERM_COLOR: always
  # Playwright / Auth.js over HTTP on localhost
  CI: true

jobs:
  offline:
    name: e2e-ui offline (domain + suite + UI unit)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: tests/e2e-ui
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
        with:
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
        with:
          toolchain: stable
          targets: wasm32-unknown-unknown

      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: |
            . -> target
            tests/e2e-ui -> target
          shared-key: e2e-ui-offline

      - name: Install wasm-pack
        run: cargo install wasm-pack --locked || cargo install wasm-pack

      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: npm
          cache-dependency-path: |
            js/package-lock.json
            tests/e2e-ui/ui/package-lock.json

      - name: Build Distributed CLI
        run: cargo build --manifest-path ../../Cargo.toml -p distributed_cli --bin distributed

      # Production Rust + SvelteKit build enters through the same command users run.
      - name: Distributed build + offline suites
        run: make ci-offline DISTRIBUTED=../../target/debug/distributed

  browser:
    name: e2e-ui Playwright (live stack)
    runs-on: ubuntu-latest
    timeout-minutes: 45
    defaults:
      run:
        working-directory: tests/e2e-ui
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
        with:
          persist-credentials: false

      - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
        with:
          toolchain: stable
          targets: wasm32-unknown-unknown

      - uses: Swatinem/rust-cache@v2
        with:
          workspaces: |
            . -> target
            tests/e2e-ui -> target
          shared-key: e2e-ui-browser

      - name: Install wasm-pack
        run: cargo install wasm-pack --locked || cargo install wasm-pack

      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: npm
          cache-dependency-path: |
            js/package-lock.json
            tests/e2e-ui/package-lock.json
            tests/e2e-ui/ui/package-lock.json

      - name: Install host tools
        run: sudo apt-get update && sudo apt-get install -y jq openssl curl

      - name: Docker stack + OIDC bootstrap (make up)
        run: |
          chmod +x scripts/up.sh
          make up

      - name: Build Distributed CLI
        run: cargo build --manifest-path ../../Cargo.toml -p distributed_cli --bin distributed

      # Build first so dev starts from the same coherent, warm generation that
      # users get after `distributed build`, rather than racing a cold Cargo
      # compile against the readiness deadline.
      - name: Build application with Distributed
        run: ../../target/debug/distributed build . --output json

      - name: Start application with Distributed dev
        run: |
          set -euo pipefail
          export AUTH_URL="${E2E_UI_ORIGIN:-http://localhost:5180}"
          export AUTH_USE_SECURE_COOKIES=false
          export AUTH_TRUST_HOST=true

          ../../target/debug/distributed dev . > .distributed-dev.log 2>&1 &
          echo $! > .distributed-dev.pid

          ok=0
          for i in $(seq 1 240); do
            if grep -Fq 'lifecycle dev: ready generation=' .distributed-dev.log; then
              ok=1
              break
            fi
            if ! kill -0 "$(cat .distributed-dev.pid)" 2>/dev/null; then
              echo "distributed dev exited before readiness"
              tail -200 .distributed-dev.log
              exit 1
            fi
            sleep 0.5
          done
          if [ "$ok" != "1" ]; then
            echo "distributed dev failed to become ready"
            tail -200 .distributed-dev.log
            exit 1
          fi

          grep -F 'lifecycle dev: process api ready http://127.0.0.1:8791' .distributed-dev.log
          grep -F 'lifecycle dev: process ui ready http://localhost:5180' .distributed-dev.log
          tail -40 .distributed-dev.log

      - name: Install Playwright + Chromium
        run: |
          npm install
          npx playwright install chromium --with-deps

      - name: Run browser e2e
        run: npm run test:browser
        env:
          E2E_UI_ORIGIN: http://localhost:5180
          E2E_API_ORIGIN: http://127.0.0.1:8791
          CI: true

      - name: Upload Playwright report
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: e2e-ui-playwright-report
          path: |
            tests/e2e-ui/playwright-report
            tests/e2e-ui/test-results
          if-no-files-found: ignore
          retention-days: 7

      - name: Dump logs on failure
        if: failure()
        run: |
          echo '=== distributed dev ==='
          tail -240 .distributed-dev.log || true
          docker compose -f docker/docker-compose.yml ps -a || true
          docker compose -f docker/docker-compose.yml logs --tail=100 || true

      - name: Stop API/UI
        if: always()
        run: |
          if [ -f .distributed-dev.pid ]; then
            pid=$(cat .distributed-dev.pid)
            kill -INT "$pid" 2>/dev/null || true
            for _ in $(seq 1 40); do
              kill -0 "$pid" 2>/dev/null || break
              sleep 0.25
            done
          fi
          lsof -ti:8791 2>/dev/null | xargs -r kill -9 2>/dev/null || true
          lsof -ti:5180 2>/dev/null | xargs -r kill -9 2>/dev/null || true

      - name: Tear down Docker
        if: always()
        run: docker compose -f docker/docker-compose.yml down -v || true