Files
amethyst/nestsClient/plans/2026-05-07-cross-stack-interop-ci-gating.md
T
Claude bd7b166fda chore(nests): mv nestsClient-browser-interop/ → nestsClient/tests/browser-interop/
Mirrors the existing nestsClient/tests/hang-interop/ layout — all
T16 cross-stack interop test infrastructure (Rust sidecars + bun
browser harness) now lives under nestsClient/tests/.

Updates:
- nestsClient/build.gradle.kts: browserInteropDir path.
- PlaywrightDriver.kt + BrowserInteropTest.kt: kdoc comments.
- All plan docs in nestsClient/plans/ that referenced the old
  path.

Compiles clean post-move. No CI changes (those jobs are
intentionally not wired per 2026-05-07-cross-stack-interop-ci-gating.md;
when re-added they'll reference the new path).
2026-05-07 14:43:55 +00:00

5.9 KiB
Raw Blame History

Plan: wire CI gating for the cross-stack interop suite

Status: specced — pickup ready. Depends on:

  • 2026-05-07-moq-relay-routing-investigation.md closed
  • 2026-05-07-tighten-cross-stack-assertions.md closed
  • 5/5 sweep stability verified

This is the FINAL step of the T16 closure. With stable hard-pass suites, CI gating becomes safe and meaningful.

What's needed

A) .github/workflows/build.yml — the hang-interop job

The job was originally part of this branch but removed per maintainer ask in commit 6829ab727 ("ci(nests): drop hang-interop job from build.yml") because the suite was flaky. Resurrect the exact same shape:

hang-interop:
  needs: lint
  runs-on: ubuntu-latest
  timeout-minutes: 30
  steps:
    - uses: actions/checkout@v6
    - uses: actions/setup-java@v5
      with: { distribution: 'zulu', java-version: 21 }
    - uses: gradle/actions/setup-gradle@v4
      with:
        cache-read-only: ${{ github.ref != 'refs/heads/main' }}
    - uses: dtolnay/rust-toolchain@stable
    - uses: actions/cache@v4
      with:
        path: |
          ~/.cargo/registry
          ~/.cargo/git
          nestsClient/tests/hang-interop/target
          ~/.cache/amethyst-nests-interop/hang-interop-cargo
        key: ${{ runner.os }}-cargo-${{ hashFiles('nestsClient/tests/hang-interop/Cargo.lock', 'nestsClient/tests/hang-interop/REV') }}
        restore-keys: |
          ${{ runner.os }}-cargo-
    - name: Run cross-stack interop suite
      run: ./gradlew :nestsClient:jvmTest -DnestsHangInterop=true
    - uses: actions/upload-artifact@v7
      if: failure()
      with:
        name: Hang Interop Test Reports
        path: nestsClient/build/reports/tests/jvmTest/

The git show 6829ab727 -- .github/workflows/build.yml reverse gives the exact diff to re-add. Linux-only is correct: the cargo install of moq-relay 0.10.x has nontrivial native deps (aws-lc-sys, ring) that take 5+ min cold; cached runs ~30 s. macOS / Windows would double matrix cost without catching new defects.

B) .github/workflows/build.yml — the browser-interop job

Same shape as A, plus bun + Playwright caching:

browser-interop:
  needs: lint
  runs-on: ubuntu-latest
  timeout-minutes: 30
  steps:
    # ...same checkout + JDK + Gradle + Rust + cargo cache as hang-interop...
    - uses: oven-sh/setup-bun@v2
      with: { bun-version: 1.3.11 }
    - uses: actions/cache@v4
      with:
        path: |
          nestsClient/tests/browser-interop/node_modules
          nestsClient/tests/browser-interop/dist
        key: ${{ runner.os }}-bun-${{ hashFiles('nestsClient/tests/browser-interop/package.json', 'nestsClient/tests/browser-interop/bun.lock') }}
    - uses: actions/cache@v4
      with:
        path: ~/.cache/ms-playwright
        key: ${{ runner.os }}-playwright-${{ hashFiles('nestsClient/tests/browser-interop/package.json') }}
    - name: Run browser cross-stack interop suite
      run: |
        ./gradlew :nestsClient:jvmTest \
            --tests "com.vitorpamplona.nestsclient.interop.native.BrowserInteropTest" \
            -DnestsHangInterop=true \
            -DnestsBrowserInterop=true
    - uses: actions/upload-artifact@v7
      if: failure()
      with:
        name: Browser Interop Test Reports
        path: |
          nestsClient/build/reports/tests/jvmTest/
          nestsClient/tests/browser-interop/test-results/
          nestsClient/tests/browser-interop/playwright-report/

Same git show b94737de7 -- .github/workflows/build.yml reverse gives the exact diff (feat/nests-browser-interop's removal commit).

The existing nests-interop opt-in pattern already lives in cli/tests/nests/nests-interop.sh. Confirm both new jobs run in parallel with that without resource contention. They use different ports (NativeMoqRelayHarness reserves ServerSocket(0)) so they're independent at the network level.

Stability bar

Before flipping the CI switch, run:

for i in 1 2 3 4 5 6 7 8 9 10; do
  echo "=== run $i ==="
  ./gradlew :nestsClient:jvmTest \
    --tests HangInteropTest \
    --tests BrowserInteropTest \
    -DnestsHangInterop=true \
    -DnestsBrowserInterop=true \
    --rerun-tasks 2>&1 | grep -E "FAILED]|BUILD"
done

10/10 BUILD SUCCESSFUL. If even one fails, do NOT wire CI; loop back to the routing investigation.

CI runtime budget

  • Hang-interop job: ~3-4 min on warm cache (one suite run, 60 s long-broadcast scenario dominates), ~8 min cold (cargo install moq-relay).
  • Browser-interop job: ~5-7 min warm (Chromium boot × N scenarios), ~10 min cold (Playwright install).
  • Both run in parallel after lint.

Total CI overhead: ~5-10 min on the critical path beyond the existing build matrix. Acceptable.

Documentation updates

After CI is green:

  1. nestsClient/plans/2026-05-06-cross-stack-interop-test-results.md — replace the "CI integration: Not wired" section with "wired, tracking flake-rate at 0/N runs".
  2. nestsClient/plans/2026-05-06-cross-stack-interop-test-gap-matrix.md — replace #6 CI integration: ⏸ deferred with ✅ live.
  3. Pick a maintainer to monitor the first 2 weeks of CI runs and bisect any new flake immediately (don't let it accumulate as "known flake" again).

Acceptance criteria

  • Both jobs added to build.yml and merge to main.
  • 10/10 sweep before merge.
  • First 2 weeks post-merge: ≥ 95% green rate. If lower, the routing investigation isn't really done — pull the jobs again until it is.

Optional follow-ups

  • Add I-12 GOAWAY scenario IF an IETF moq-transport target lands. Currently N/A in moq-lite-03 per cross-stack-interop-test-results.md's I12 section. If an IETF target ever ships, this is the cross-stack regression test.
  • Surface framesPerGroup as a per-deployment config if the framesPerGroup-rerun outcome shows the two rigs can't converge (see 2026-05-07-framespergroup-production-rerun.md).