Skip to content

Cover use-release-stream: applyStreamEvent reducer and stream wiring - #868

Merged
selfcontained merged 1 commit into
mainfrom
agt_5e65ea790cb4/job-test-enforcer-c7c18a29
Aug 3, 2026
Merged

Cover use-release-stream: applyStreamEvent reducer and stream wiring#868
selfcontained merged 1 commit into
mainfrom
agt_5e65ea790cb4/job-test-enforcer-c7c18a29

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

Summary

The release SSE hook (apps/web/src/hooks/use-release-stream.ts) had zero direct coverage despite owning the client-side release-job reducer and the post-restart health-poll flow. This PR exports the previously module-private applyStreamEvent (matching the existing use-sse.ts convention of exporting pure appliers for tests) and adds use-release-stream.test.tsx with 23 tests.

What is pinned

Reducer (applyStreamEvent)

  • log append is immutable and ordered; log.rewind drops exactly count entries (server clamps to ≥1, so the count-0 edge is unreachable and intentionally not pinned); log.replace swaps the last line and pushes onto an empty log
  • phase applies across all three jobType variants, preserves the prior error when the event carries none, and overwrites it when it does
  • progress set/clear, runUrl, tag
  • assisted events are ignored unless jobType === "update-assisted"
  • Events before any snapshot (prev null) are no-ops

Hook wiring (stubbed global EventSource + fake timers)

  • Stream URL carries the stable per-mount client id; connectStream closes the prior stream and reuses the id
  • snapshot seeds the job; info-progress routes to infoProgress without touching the job
  • onerror during an update deploy/restart flips to restarting, polls /api/v1/release/status every 2s, completes to done when the expected tag appears, and schedules reloadApp 1.5s later; keeps polling while the old tag is reported
  • Non-update jobs (including an assisted job sitting in restarting) never trigger the health poll
  • Unmount closes the stream and stops the poll interval

9/9 mutant battery killed (append drop, rewind hardcode, replace-push, empty-push drop, error-fallback drop, assisted-guard drop, null-guard fake, onerror jobType-guard relax, poll tag-match invert).

Validation

  • pnpm run check, pnpm run finalize:web clean
  • Unit: server 2390, web 564 (+23), extension 60, scripts 4 — all green
  • E2E: inert 175 passed / 12 skipped; live lane 11 passed (20.6s), zero leaked tmux sessions

🤖 Generated with Claude Code

The release SSE hook had zero direct coverage despite owning the
client-side job-state reducer and the post-restart health-poll flow.
Export applyStreamEvent (same convention as use-sse's appliers) and pin:
log append/rewind/replace semantics, per-jobType phase casts with error
preservation, progress set/clear, assisted-event gating, pre-snapshot
no-ops, info-progress routing, reconnect client-id stability, the
onerror -> health-poll -> done -> reloadApp sequence under fake timers,
and unmount cleanup of both the stream and the poll interval.
9/9 mutant battery killed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@selfcontained
selfcontained merged commit 9ad9d65 into mainAug 3, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_5e65ea790cb4/job-test-enforcer-c7c18a29 branch August 3, 2026 02:24
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@selfcontained