Add browser end-to-end test for multiple sync sources #77
Workflow file for this run
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: Code tests & eval | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| check: | |
| name: Type check | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Setup environment | |
| uses: ./.github/actions/common-setup | |
| - name: svelte-check | |
| run: pnpm check | |
| test: | |
| name: Unit tests | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Setup environment | |
| uses: ./.github/actions/common-setup | |
| - name: vitest | |
| run: pnpm test | |
| build: | |
| name: Production build | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Setup environment | |
| uses: ./.github/actions/common-setup | |
| - name: Build production bundle | |
| run: pnpm build | |
| - name: Upload dist artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: dist-${{ github.sha }} | |
| path: dist/ | |
| retention-days: 7 | |
| smoke: | |
| name: Smoke (real sync-server) | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 10 | |
| # Pin sync-server by digest so this test can never silently shift if `latest` | |
| # is republished. Refresh intentionally when targeting a different release. | |
| services: | |
| sync-server: | |
| image: ghcr.io/d4rken-org/octi-server@sha256:3829efba5ca5a4d407a0d0a048b8d0c20264ad2f9e389aa087c857ea0d0bddaa | |
| ports: | |
| - 18080:8080 | |
| env: | |
| OCTI_CORS_ALLOWED_ORIGINS: 'http://127.0.0.1:5173,http://localhost:5173' | |
| sync-server-b: | |
| image: ghcr.io/d4rken-org/octi-server@sha256:3829efba5ca5a4d407a0d0a048b8d0c20264ad2f9e389aa087c857ea0d0bddaa | |
| ports: | |
| - 18081:8080 | |
| env: | |
| OCTI_CORS_ALLOWED_ORIGINS: 'http://127.0.0.1:5173,http://localhost:5173' | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Setup environment | |
| uses: ./.github/actions/common-setup | |
| - name: Wait for sync-servers | |
| run: | | |
| set -euo pipefail | |
| for port in 18080 18081; do | |
| for attempt in $(seq 1 30); do | |
| if curl -sf "http://127.0.0.1:${port}/v1/status" > /dev/null; then | |
| echo "sync-server on ${port} up after ${attempt}s" | |
| continue 2 | |
| fi | |
| sleep 1 | |
| done | |
| echo "sync-server on ${port} did not respond within 30s" >&2 | |
| docker logs ${{ job.services.sync-server.id }} || true | |
| docker logs ${{ job.services['sync-server-b'].id }} || true | |
| exit 1 | |
| done | |
| - name: Run smoke suite | |
| env: | |
| SMOKE_SERVER_URL: http://127.0.0.1:18080 | |
| SMOKE_SERVER_B_URL: http://127.0.0.1:18081 | |
| run: pnpm test:smoke | |
| - name: Dump sync-server logs on failure | |
| if: failure() | |
| run: | | |
| docker logs ${{ job.services.sync-server.id }} || true | |
| docker logs ${{ job.services['sync-server-b'].id }} || true | |
| release-tooling: | |
| name: Release tooling | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Install bats + shellcheck | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y bats shellcheck | |
| - name: Shellcheck bump.sh | |
| run: shellcheck tools/release/bump.sh | |
| - name: Run bump.sh unit tests | |
| run: bats tools/release/bump.bats | |
| - name: Verify package.json + bump.sh are consistent | |
| run: tools/release/bump.sh --mode=check | |
| e2e-smoke: | |
| name: E2E smoke | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 20 | |
| # Mirrors the release-tag.yml e2e job at lower cost: bootstrap a fake phone | |
| # peer, build the SPA, drive it through Playwright with no screenshots. | |
| # Catches selector/bootstrap drift on every PR/main push so a release tag | |
| # never surfaces these surprises for the first time. A second sync-server | |
| # backs the multi-connector spec (link the SPA to two servers via the UI). | |
| services: | |
| sync-server: | |
| image: ghcr.io/d4rken-org/octi-server@sha256:3829efba5ca5a4d407a0d0a048b8d0c20264ad2f9e389aa087c857ea0d0bddaa | |
| ports: | |
| - 18080:8080 | |
| env: | |
| OCTI_CORS_ALLOWED_ORIGINS: 'http://127.0.0.1:4173,http://localhost:4173' | |
| sync-server-b: | |
| image: ghcr.io/d4rken-org/octi-server@sha256:3829efba5ca5a4d407a0d0a048b8d0c20264ad2f9e389aa087c857ea0d0bddaa | |
| ports: | |
| - 18081:8080 | |
| env: | |
| OCTI_CORS_ALLOWED_ORIGINS: 'http://127.0.0.1:4173,http://localhost:4173' | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: { persist-credentials: false } | |
| - name: Setup environment | |
| uses: ./.github/actions/common-setup | |
| - name: Wait for sync-servers | |
| run: | | |
| set -euo pipefail | |
| for port in 18080 18081; do | |
| for attempt in $(seq 1 30); do | |
| if curl -sf "http://127.0.0.1:${port}/v1/status" > /dev/null; then | |
| echo "sync-server on ${port} up after ${attempt}s" | |
| continue 2 | |
| fi | |
| sleep 1 | |
| done | |
| echo "sync-server on ${port} did not respond within 30s" >&2 | |
| docker logs ${{ job.services.sync-server.id }} || true | |
| docker logs ${{ job.services['sync-server-b'].id }} || true | |
| exit 1 | |
| done | |
| # Three bootstrap files with independent one-time-use share codes: | |
| # bootstrap-peer.json (server A) — the single-connector smoke spec | |
| # peer-a.json (server A), peer-b.json (server B) — the multi-connector spec | |
| # Separate files so the two specs never redeem the same code. | |
| - name: Bootstrap fake phone peer (smoke, server A) | |
| env: | |
| SYNC_SERVER_URL: http://127.0.0.1:18080 | |
| OUTPUT_PATH: bootstrap-peer.json | |
| run: pnpm bootstrap-peer | |
| - name: Bootstrap fake phone peer (multi, server A) | |
| env: | |
| SYNC_SERVER_URL: http://127.0.0.1:18080 | |
| OUTPUT_PATH: peer-a.json | |
| run: pnpm bootstrap-peer | |
| - name: Bootstrap fake phone peer (multi, server B) | |
| env: | |
| SYNC_SERVER_URL: http://127.0.0.1:18081 | |
| OUTPUT_PATH: peer-b.json | |
| run: pnpm bootstrap-peer | |
| - name: Install Playwright browsers | |
| run: pnpm exec playwright install --with-deps chromium | |
| - name: Build SPA (stable channel for smoke) | |
| env: | |
| VITE_CHANNEL: stable | |
| VITE_COMMIT_SHA: ${{ github.sha }} | |
| run: pnpm build | |
| - name: Run E2E smoke | |
| env: | |
| BOOTSTRAP_PEER_FILE: bootstrap-peer.json | |
| run: pnpm e2e:smoke | |
| - name: Run E2E multi-connector | |
| env: | |
| BOOTSTRAP_PEER_A_FILE: peer-a.json | |
| BOOTSTRAP_PEER_B_FILE: peer-b.json | |
| run: pnpm e2e:multi | |
| - name: Dump sync-server logs on failure | |
| if: failure() | |
| run: | | |
| docker logs ${{ job.services.sync-server.id }} || true | |
| docker logs ${{ job.services['sync-server-b'].id }} || true | |
| - name: Upload Playwright trace on failure | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: playwright-trace-${{ github.run_id }} | |
| path: | | |
| test-results/ | |
| playwright-report/ | |
| if-no-files-found: ignore |