feat(status-bar): trace branch PR and CI status - #653
Merged
Conversation
Adds a CI menu to the workstation status bar, between the branch and the git sync control: the pull request open for the current branch plus the state of every check on its head commit, grouped failed / running / skipped / passed. It reuses the ports menu's trigger and portalled panel so the two neighbours read as one control family. Polling is bounded rather than periodic. `useBranchPullRequestStatus` gains an opt-in `poll` mode whose schedule comes from `nextBranchCiPollDelayMs`: 15s backing off to a 60s cap while checks run, three 30s retries when a PR has not reported any checks yet, and no timer at all once every check has a verdict, when there is no PR, or when the window is hidden. A new head SHA restarts the backoff so a push is picked up quickly. Opening the menu or the refresh button forces a read past the 45s cache TTL. The focused-chat rail keeps polling off and shares the same cache and in-flight coalescing, so nothing is fetched twice. Check-state derivation moves to `services/git/ciCheckState`, which `PrChecksTab` now shares instead of re-deriving it. "Settled" is structural (every run reported) rather than reading the server roll-up, which short-circuits to failure while other jobs are still in flight. Pre-commit hook ran. Total eslint: 0, total circular: 0
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a branch CI menu to the workstation status bar, sitting between the branch
button and the git sync control. It shows the pull request open for the current
branch and the state of every check on its head commit, grouped failed /
running / skipped / passed, with a link out to each check's details.
The menu reuses the ports menu's trigger and portalled panel so the two
neighbours in the bar read as one control family.
Problem
Tracing a branch's CI meant leaving the app for GitHub, or opening the PR
sidebar panel and switching to its Checks tab. GitHub Desktop surfaces this in
its own status bar; we had the data (
github_get_checks, already wired for thePR detail panel) but no ambient place to read it.
The naive way to add it — a fixed-interval poller — is the wrong trade. Most of
the time a branch's checks have already finished and nothing can change until
the next push, so a periodic timer spends GitHub API budget to re-confirm a
static answer.
Solution
The menu.
CiStatusMenurenders only when the branch has an open PR. Thetrigger shows a state icon plus
#650, andreported/totalwhile checks arestill running. The panel header carries the PR link, the rolled-up status and a
refresh button; rows show the check name, elapsed time only while running, and
a details link. The reporting app (
GitHub Actions) is kept out of the label —it is the same for nearly every row — and appears in the hover title instead.
Bounded polling.
useBranchPullRequestStatusgains an opt-inpollmode.The schedule lives in
nextBranchCiPollDelayMs:A new head SHA resets the backoff, so a push is picked up at the fast interval
instead of inheriting a cooled-off one. Opening the menu or hitting refresh
forces a read past the 45s cache TTL. A typical 10-minute CI run costs ~11
reads and then goes quiet; a settled branch costs zero.
The focused-chat rail keeps polling off and shares the same TTL cache and
in-flight coalescing, so mounting both surfaces does not fetch twice.
Shared derivation. Check-state mapping moves to
services/git/ciCheckState.ts, whichPrChecksTabnow imports instead ofre-deriving it. "Settled" is computed structurally — every run reported —
rather than reading
summary.state, because the server-side roll-upshort-circuits to
failurewhile other jobs are still in flight, and the rowsshould stay live until they actually finish.
Validation / Test plan
src/services/git/ciCheckState.test.ts(new) — conclusion mapping across allfailing/neutral conclusions, run-before-status flattening, app name kept
unmerged, state counts, and the settle rule including the
decided-failure-with-a-job-still-running case.
src/services/git/branchPullRequestStatus.test.ts— poll schedule: stops withno PR / unreadable / settled checks, backs off and caps while running, and the
bounded grace period for a PR with no checks yet.
src/hooks/git/useBranchPullRequestStatus.test.ts— re-reads while checks runand stops once they settle; never schedules a poll when
pollis notrequested. Existing visibility-gating and TTL cases still pass unchanged.
npx vitest run src/services/git src/hooks/git→ 16 files, 81 tests passing.tsc --noEmitandeslintclean over the touched files.fetches, opening the menu forces a refresh, details links open externally.
Potential risks
checks) while checks are running. Bounded as above, well inside the 5000/hr
authenticated limit, but it is new traffic that did not exist before.
DROPDOWN_CLASSES.searchContainer. Its class list was extracted into ashared
PANEL_HEADER_ROWconstant thatpanelHeaderRowalso points at. Theemitted string is identical, so existing consumers are unaffected — but it is
now a shared definition, and changing it moves both.
PrChecksTabrefactor. It now importscheckRunState/statusContextStaterather than defining them. Behaviour is unchanged; thesidebar still shows the app-qualified check name, only the status-bar menu
drops the prefix.
workstation.ci.*keys were added toenandzhonly, matching the recent two-locale convention. Other locales fall back to
English until translated.