diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8bd0991..73bcd5b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,6 +117,81 @@ jobs: - name: Test run: vp run --filter helmcode test --shard ${{ matrix.shard }}/${{ strategy.job-total }} + # THROWAWAY: isolates each real-subprocess-spawning ProviderRegistry suite + # on its own runner, one file per job, to find out which one (and where in + # it) is hanging "Test Server 2" on every run since PR #48's + # opencodeRuntime.ts change (detached spawn + process-group kill + # finalizer). Delete these jobs once the probe answers that. + probe_opencode_hang: + name: Probe OpenCode Hang (${{ matrix.file }}) + runs-on: ubuntu-latest + timeout-minutes: 8 + strategy: + fail-fast: false + matrix: + file: + - ProviderRegistry + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + sparse-checkout: | + /* + !/.repos/ + sparse-checkout-cone-mode: false + + - name: Setup Vite+ + uses: voidzero-dev/setup-vp@v1 + with: + node-version-file: package.json + cache: true + run-install: true + + # `timeout`'s SIGTERM only reaches vp's direct process, not a + # detached:true grandchild (opencodeRuntime.ts spawns those) — the last + # run sat past 300s with the step still "in_progress", suggesting an + # orphaned child is holding the log pipe open. So: run in the + # background, poll for it dying on our own, and if it doesn't, snapshot + # `ps -ef` (proof of a surviving orphan) and force-kill everything + # before exiting 0 — the step must always complete so the log upload + # step actually runs. + - name: Probe + run: | + set +e + vp run --filter helmcode test \ + src/provider/Layers/${{ matrix.file }}.test.ts \ + -- --reporter=verbose > /tmp/probe.log 2>&1 & + VP_PID=$! + for i in $(seq 1 60); do + sleep 5 + kill -0 "$VP_PID" 2>/dev/null || break + done + if kill -0 "$VP_PID" 2>/dev/null; then + { + echo "=== TIMED OUT after ~300s, vp (pid $VP_PID) still alive ===" + echo "=== process tree snapshot ===" + ps -ef + } | tee -a /tmp/probe.log + pkill -9 -P "$VP_PID" 2>/dev/null + kill -9 "$VP_PID" 2>/dev/null + else + wait "$VP_PID" + echo "probe exited with $?" | tee -a /tmp/probe.log + fi + { + echo "=== final process snapshot before job teardown ===" + ps -ef + } | tee -a /tmp/probe.log + exit 0 + + - name: Upload probe log + if: always() + uses: actions/upload-artifact@v4 + with: + name: probe-log-${{ matrix.file }} + path: /tmp/probe.log + if-no-files-found: ignore + # Split out of Check and Test: both paid a Rust toolchain install for checks # that take a couple seconds, on the critical path of every PR. rust: