Skip to content

feat(checks): read Jenkins build stages and details for Jenkins checks - #39

Merged
nplez1 merged 0 commit into
nplez1/mainfrom
nplez1/Jenkins-Status
Sep 27, 2026
Merged

nplez1 merged 0 commit into
nplez1/mainfrom
nplez1/Jenkins-Status

Conversation

@nplez1

@nplez1 nplez1 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner
Files Added Deleted Net
Test 11 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1761 $\color{#cf222e}{\Huge{\mathbf{−}}}$​2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1759
Prod 40 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2736 $\color{#cf222e}{\Huge{\mathbf{−}}}$​129 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2607

ELI5

Some PR checks are Jenkins jobs. Orca showed the check's name and whether it failed, but when you
clicked it to see why, it said it had no details — so the only way to find out which stage broke was
to open Jenkins in a browser.

Now Orca reads the build from Jenkins and shows the stages, which one is still running, and the
build's facts (number, what started it, how long it queued and ran, its parameters and commits).

What Changed

Before: a Jenkins check is a GitHub legacy commit status — a name, a state and a link, with no
check-run or workflow-run id. Orca's only details lookup fetched check runs and workflow jobs by
those ids, so a Jenkins check came back as a valid but empty payload and the expanded pane read
"No inline details are available for this check."

After: expanding a Jenkins check lists its pipeline stages with a pass/fail/running glyph for
each, plus the build's number, trigger, queue time, estimate, duration, parameters and commits.
A stage still running is visible, and the failed stage is named.

The mechanism. Detection is by the check's own URL, because that is the only handle a status
context carries: src/shared/jenkins-urls.ts reads the classic job path (prefixes, folders,
multibranch, display/redirect-style pages, lastBuild permalinks) and translates Blue Ocean links
to their classic equivalent. Main then reads two endpoints on the classic build URL —
<build>/api/json?tree=… for the build and <build>/wfapi/describe for the stage list (best-effort;
a freestyle job has no stages) — and maps them into the existing provider-neutral shape: stages onto
PRCheckJob.steps as one job per build, and metadata onto a new optional
PRCheckRunDetails.build. All four existing detail surfaces therefore render it with no
provider-specific path.

Two supporting changes fall out of that:

  • stepRendering: 'all' marks a stage list. A stage list is the build's shape rather than a
    drill-down, so the sidebar lists every stage instead of its compact failures-only list, and the
    editor stops collapsing stages behind its "N succeeded" toggle. The failures-only filter moved to
    src/shared/check-step-visibility.ts, which is where it was duplicated.
  • The check-fix prompt consumes failing stage names. It previously read only log tails, so without
    this the Jenkins fetch would have cost a request and been thrown away.

Credentials are a list of user-configured servers (base URL, username, API token) — Settings →
Integrations → CI providers — because a user runs several. Profiles live in
~/.orca/jenkins-servers.json and one API token per server in the existing encrypted credential
file. A build URL matches a server by longest configured prefix rather than by origin.

Why

URL-driven detection, confirmed by fetching. There is no id to dispatch on, so the URL has to be
the first move. A parsed URL is only a candidate: main confirms by fetching and answers
not-jenkins when the host turns out not to be Jenkins, so a false positive costs one request and
falls back to the existing GitHub path rather than showing a wrong pane.

Mapping into the existing shape, not a new renderer path. Jenkins details had to reach four
surfaces (sidebar, editor tab, item dialog, PR page). Reusing PRCheckJob.steps and adding one
optional structured field is far less churn than a Jenkins-specific renderer, and it is what makes
the fix land everywhere at once.

A structured metadata field, not provider prose. title/summary are markdown written by the
provider, which localizes itself. These labels are Orca's, so they have to cross IPC as data and go
out through translate().

Prefix matching, not origin. Jenkins is routinely served under a path, and two instances can
share a host.

Alternatives considered: a Jenkins-specific details component per surface (rejected as four copies
of the same layout); putting the fingerprint in the GitHub check mapper in main (rejected — it would
couple every check-list fetch to the Jenkins server list); reusing browser session cookies for auth
(rejected as fragile and tied to cookie import).

Linked Issue

None filed — nothing to link. Say the word if you want one opened and referenced here.

Visual Proof

No screenshots: this needs a live Jenkins (or a faked check pointing at one) plus a running app, and
the authoring environment has neither, so a capture would not have been honest. What follows is the
pane's rendered text, whitespace-normalized, taken from jenkins-check-row-details.test.tsx
(a real render of the component, not hand-written):

Before — the check row, expanded:

1 failing
continuous-integration/jenkins/pr-merge   Failed
No inline details are available for this check.

After — same row, same check:

1 failing
continuous-integration/jenkins/pr-merge   Failed   [View full details]
Status: Failed  Started Jun 16, 5:00 AM  Completed Jun 16, 5:04 AM  Duration 4m 12s
Build
  Number        #12
  Triggered by  Started by user Ada
  Queued        2s
  Estimated     4m 0s
Parameters
  GITHUB_TOKEN  ••••
Commits
  abc123de      Fix the thing          Ada Lovelace
team » repo » main #12
Failed jobs
  #12                                    failure
    ✓ Checkout                           success
    ✗ Unit tests                         failure
    ◌ Integration tests                  pending
    – Deploy                             skipped

Testing

  • pnpm tc (node, cli, web), all seven changed-code-quality scans, and the localization, anti-slop,
    dead-class, max-lines and ts-nocheck gates — green.

  • Targeted suites: src/shared + src/main/jenkins + src/main/ipc → 13,693 passing;
    right-sidebar + editor + settings + pull-request-page + github-item-dialog → 5,292
    passing. 83 new test cases.

  • New coverage worth naming: URL shapes (18), status/secret mapping (9), server matching and
    storage (6), request classification including a same-origin redirect that leaves the configured
    server path
    (20), renderer dispatch (9), settings card (8), the rendered pane (3).

  • Platforms: macOS only. No live Jenkins was exercised — every endpoint interaction is mocked.
    docs/reference/jenkins-check-details.md records that gap and is deliberately not committed
    (docs/** is local-only in this fork).

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

AI Disclosure

Implemented by Pi (coding agent) with GPT-6 Sol at high reasoning performing an independent
review of the uncommitted diff. The review found a credential-scope hole (a same-origin redirect
could carry the Authorization header outside the configured server prefix), a substring-based
parameter mask that let PRIVATE_KEY through, and a stage-timing bug that gave a running stage a
completion time; all three are fixed and covered by regression tests.

Review

Worth a reviewer's eye:

  1. The credential boundary. A response whose final URL falls outside the configured server
    prefix is refused, but with redirect: 'follow' a same-origin intermediate hop still receives the
    header before the final URL is judged. Per-hop control needs redirect: 'manual', which returns
    an opaque redirect under the Fetch standard (no readable Location) and would break permalink
    following. Called out in the doc rather than silently claimed as closed.
  2. An unconfigured host is fetched anonymously so a public Jenkins works with no setup; no token
    is ever attached to one. Intranet/loopback targets are not fenced on purpose.
  3. Parameter masking is a heuristic. Masked by kind and by word-segment name; a secret passed
    under an unremarkable name is shown, which is the exposure api/json already gives the same
    reader.
  4. A freestyle build has no stages, so it shows metadata and nothing else. The follow-up is a
    bounded console excerpt, which was left out of scope here.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: no token ever reaches the renderer, a log, or an error message; parameter values are
    masked in main before crossing IPC.
  • Cross-platform: the code paths are platform-neutral (URL handling plus the shared main-process
    HTTP port rather than a shell), but only macOS was run.
  • SSH/remote: an accepted v1 limit — details are read from the machine running Orca, so a Jenkins
    only reachable from a remote host reports unreachable. No relay was added.
  • Mobile: no mobile surface consumes check details; nothing to wire.
  • Backwards compatibility: PRCheckRunDetails.build and PRCheckJob.stepRendering are optional,
    so an older client ignores them.
  • Performance: two conditional GETs per expanded Jenkins check, 10s timeout and an 8 MB read cap;
    details are only auto-loaded for failed checks, as before.
  • Size: ~4,500 lines across 50 files, of which roughly a third is tests. One feature, but not a
    small diff.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)
    — locally: pnpm tc and every gate in pnpm lint's chain that this change can affect
    (localization ×4, anti-slop, dead classes, max-lines, ts-nocheck, changed-code-quality ×7) are
    green, plus the targeted suites above. The full pnpm test and pnpm build were left to CI.

@nplez1
nplez1 merged this pull request into nplez1/main Sep 27, 2026
35 checks passed
nplez1 added a commit that referenced this pull request Sep 27, 2026
#39)

* feat(checks): read Jenkins build stages and details for Jenkins checks

A CI check that points at Jenkins reaches Orca as a GitHub legacy commit
status: a name, a state and a target_url, with no check-run or workflow-run
id. The only details fetch looked runs up by those ids, so it returned a
valid but empty payload and expanding the check said "No inline details are
available for this check" — while the check was the only place to see which
stage was running or which one broke.

Detect a Jenkins check from its own URL (src/shared/jenkins-urls.ts handles
job prefixes, folders, multibranch, page suffixes, permalinks, and translates
Blue Ocean links to their classic equivalent), then read the build in main
through two GETs: `<build>/api/json?tree=…` for the build and
`<build>/wfapi/describe` for the stage list, best-effort since a freestyle job
has no stages. Stages map onto the existing provider-neutral
`PRCheckJob.steps` (one job per build) and build metadata onto a new optional
`PRCheckRunDetails.build`, so the four existing detail surfaces render it
without a provider-specific path.

`stepRendering: 'all'` marks a stage list: a stage list is the build's shape
rather than a drill-down, so the sidebar lists every stage (including the one
still running) instead of its compact failures-only list, and the editor stops
collapsing stages behind its "N succeeded" toggle. The failures-only filter
itself moved to src/shared/check-step-visibility.ts, where it was duplicated.

Credentials are a list of user-configured servers (base URL, username, API
token), because a user runs several: profiles in ~/.orca/jenkins-servers.json
and one keychain-encrypted token per server. A build URL is matched to a
server by longest configured prefix, not by origin, and a response whose final
URL is outside that prefix is refused, since the Fetch standard only strips
Authorization on a cross-origin hop. Parameter values are masked by kind and
by name before reaching the renderer.

The check-fix prompt now consumes failing stage names, which is what makes a
Jenkins check useful there despite having no log tail.

Endpoint behavior is covered by unit tests with a mocked HTTP client; no live
Jenkins has been exercised, which docs/reference/jenkins-check-details.md
(local-only, not tracked here) records along with the local-reachability and
parameter-masking limits.

* test(main): register the Jenkins fetch call site in the proxy audit

The proxy-guarded fetch audit is stricter than a grep: it counts every
non-`net` `.fetch(` call per main-process file and fails on a count it has
not been told about. src/main/jenkins/jenkins-request.ts went through the
injected HttpClient without being registered, so shard 5 failed on 'keeps
every non-default-session fetcher audited with its expected count'.

Same entry as main/jira/authenticated-request.ts: the injected client resolves
to net.fetch on defaultSession on the desktop, and to the global-fetch-audited
Node fallback elsewhere.
nplez1 added a commit that referenced this pull request Sep 29, 2026
* feat(checks): make the Jenkins build tree readable at scale

The Jenkins details from #39 read the build's stage list but listed every stage in the Checks
pane, buried failures under it, kept an Output box that only repeated the build name, and
stopped at a bare error when the account could not read the job.

- Pane: list only the stages still running and the ones that failed, running first, capped at
  eight, with a "+N more stages" line — a pipeline can have hundreds.
- Detail page: render the stages as a nested tree (stage -> its wfapi flow nodes) like Blue
  Ocean, with failed and running stages open by default.
- Detail page: a Failures block under the run header names each failed stage and its error
  text, so "what broke" needs no scrolling.
- Detail page: drop the Output box for a stage list; the build metadata is the run summary.
- Settings: a Jenkins read failure the user can fix (no server, rejected token, no permission)
  now shows an "Open Jenkins settings" button that deep-links to the Jenkins card.

Main reads each stage's own wfapi/describe (its _links.self.href, bounded to 40 requests at
six concurrent, failed/running first under a four-second budget) for the steps and failure
text, and carries the flow nodes on an optional PRCheckStep.children. The Jenkins node id is
kept so repeated stage names (loops, parallel branches) cannot collide as React keys.

* fix(lint): split files over the max-lines budget

Five files exceed the oxlint max-lines budget on nplez1/main and have no suppression, so the
whole-repo `pnpm exec oxlint` in the static-analysis job fails for every PR cut from it. They
were pushed over by fork-only commits (`#34`, and three direct commits) that never ran PR CI.
The repo's rule is to split rather than suppress, so this extracts cohesive pieces:

- filesystem-watcher.test.ts: the local/WSL lifecycle tests move to
  filesystem-watcher-local-lifecycle.test.ts.
- filesystem-watcher-local-subscription.ts: scheduleLocalWatcherTeardown moves to
  filesystem-watcher-local-teardown.ts.
- ssh-target-cleanup.ts: the per-tab session helpers move to ssh-target-tab-sessions.ts.
- ai-vault-session-refresh.ts: the session-ids key moves to ai-vault-session-ids.ts.
- accounts-search.ts: the Grok and Cursor search entries move to
  accounts-search-extra-providers.ts and are re-exported.

No behavior change; the affected suites pass.
nplez1 added a commit that referenced this pull request Sep 29, 2026
#39)

* feat(checks): read Jenkins build stages and details for Jenkins checks

A CI check that points at Jenkins reaches Orca as a GitHub legacy commit
status: a name, a state and a target_url, with no check-run or workflow-run
id. The only details fetch looked runs up by those ids, so it returned a
valid but empty payload and expanding the check said "No inline details are
available for this check" — while the check was the only place to see which
stage was running or which one broke.

Detect a Jenkins check from its own URL (src/shared/jenkins-urls.ts handles
job prefixes, folders, multibranch, page suffixes, permalinks, and translates
Blue Ocean links to their classic equivalent), then read the build in main
through two GETs: `<build>/api/json?tree=…` for the build and
`<build>/wfapi/describe` for the stage list, best-effort since a freestyle job
has no stages. Stages map onto the existing provider-neutral
`PRCheckJob.steps` (one job per build) and build metadata onto a new optional
`PRCheckRunDetails.build`, so the four existing detail surfaces render it
without a provider-specific path.

`stepRendering: 'all'` marks a stage list: a stage list is the build's shape
rather than a drill-down, so the sidebar lists every stage (including the one
still running) instead of its compact failures-only list, and the editor stops
collapsing stages behind its "N succeeded" toggle. The failures-only filter
itself moved to src/shared/check-step-visibility.ts, where it was duplicated.

Credentials are a list of user-configured servers (base URL, username, API
token), because a user runs several: profiles in ~/.orca/jenkins-servers.json
and one keychain-encrypted token per server. A build URL is matched to a
server by longest configured prefix, not by origin, and a response whose final
URL is outside that prefix is refused, since the Fetch standard only strips
Authorization on a cross-origin hop. Parameter values are masked by kind and
by name before reaching the renderer.

The check-fix prompt now consumes failing stage names, which is what makes a
Jenkins check useful there despite having no log tail.

Endpoint behavior is covered by unit tests with a mocked HTTP client; no live
Jenkins has been exercised, which docs/reference/jenkins-check-details.md
(local-only, not tracked here) records along with the local-reachability and
parameter-masking limits.

* test(main): register the Jenkins fetch call site in the proxy audit

The proxy-guarded fetch audit is stricter than a grep: it counts every
non-`net` `.fetch(` call per main-process file and fails on a count it has
not been told about. src/main/jenkins/jenkins-request.ts went through the
injected HttpClient without being registered, so shard 5 failed on 'keeps
every non-default-session fetcher audited with its expected count'.

Same entry as main/jira/authenticated-request.ts: the injected client resolves
to net.fetch on defaultSession on the desktop, and to the global-fetch-audited
Node fallback elsewhere.
nplez1 added a commit that referenced this pull request Sep 29, 2026
* feat(checks): make the Jenkins build tree readable at scale

The Jenkins details from #39 read the build's stage list but listed every stage in the Checks
pane, buried failures under it, kept an Output box that only repeated the build name, and
stopped at a bare error when the account could not read the job.

- Pane: list only the stages still running and the ones that failed, running first, capped at
  eight, with a "+N more stages" line — a pipeline can have hundreds.
- Detail page: render the stages as a nested tree (stage -> its wfapi flow nodes) like Blue
  Ocean, with failed and running stages open by default.
- Detail page: a Failures block under the run header names each failed stage and its error
  text, so "what broke" needs no scrolling.
- Detail page: drop the Output box for a stage list; the build metadata is the run summary.
- Settings: a Jenkins read failure the user can fix (no server, rejected token, no permission)
  now shows an "Open Jenkins settings" button that deep-links to the Jenkins card.

Main reads each stage's own wfapi/describe (its _links.self.href, bounded to 40 requests at
six concurrent, failed/running first under a four-second budget) for the steps and failure
text, and carries the flow nodes on an optional PRCheckStep.children. The Jenkins node id is
kept so repeated stage names (loops, parallel branches) cannot collide as React keys.

* fix(lint): split files over the max-lines budget

Five files exceed the oxlint max-lines budget on nplez1/main and have no suppression, so the
whole-repo `pnpm exec oxlint` in the static-analysis job fails for every PR cut from it. They
were pushed over by fork-only commits (`#34`, and three direct commits) that never ran PR CI.
The repo's rule is to split rather than suppress, so this extracts cohesive pieces:

- filesystem-watcher.test.ts: the local/WSL lifecycle tests move to
  filesystem-watcher-local-lifecycle.test.ts.
- filesystem-watcher-local-subscription.ts: scheduleLocalWatcherTeardown moves to
  filesystem-watcher-local-teardown.ts.
- ssh-target-cleanup.ts: the per-tab session helpers move to ssh-target-tab-sessions.ts.
- ai-vault-session-refresh.ts: the session-ids key moves to ai-vault-session-ids.ts.
- accounts-search.ts: the Grok and Cursor search entries move to
  accounts-search-extra-providers.ts and are re-exported.

No behavior change; the affected suites pass.
nplez1 added a commit that referenced this pull request Oct 1, 2026
#39)

* feat(checks): read Jenkins build stages and details for Jenkins checks

A CI check that points at Jenkins reaches Orca as a GitHub legacy commit
status: a name, a state and a target_url, with no check-run or workflow-run
id. The only details fetch looked runs up by those ids, so it returned a
valid but empty payload and expanding the check said "No inline details are
available for this check" — while the check was the only place to see which
stage was running or which one broke.

Detect a Jenkins check from its own URL (src/shared/jenkins-urls.ts handles
job prefixes, folders, multibranch, page suffixes, permalinks, and translates
Blue Ocean links to their classic equivalent), then read the build in main
through two GETs: `<build>/api/json?tree=…` for the build and
`<build>/wfapi/describe` for the stage list, best-effort since a freestyle job
has no stages. Stages map onto the existing provider-neutral
`PRCheckJob.steps` (one job per build) and build metadata onto a new optional
`PRCheckRunDetails.build`, so the four existing detail surfaces render it
without a provider-specific path.

`stepRendering: 'all'` marks a stage list: a stage list is the build's shape
rather than a drill-down, so the sidebar lists every stage (including the one
still running) instead of its compact failures-only list, and the editor stops
collapsing stages behind its "N succeeded" toggle. The failures-only filter
itself moved to src/shared/check-step-visibility.ts, where it was duplicated.

Credentials are a list of user-configured servers (base URL, username, API
token), because a user runs several: profiles in ~/.orca/jenkins-servers.json
and one keychain-encrypted token per server. A build URL is matched to a
server by longest configured prefix, not by origin, and a response whose final
URL is outside that prefix is refused, since the Fetch standard only strips
Authorization on a cross-origin hop. Parameter values are masked by kind and
by name before reaching the renderer.

The check-fix prompt now consumes failing stage names, which is what makes a
Jenkins check useful there despite having no log tail.

Endpoint behavior is covered by unit tests with a mocked HTTP client; no live
Jenkins has been exercised, which docs/reference/jenkins-check-details.md
(local-only, not tracked here) records along with the local-reachability and
parameter-masking limits.

* test(main): register the Jenkins fetch call site in the proxy audit

The proxy-guarded fetch audit is stricter than a grep: it counts every
non-`net` `.fetch(` call per main-process file and fails on a count it has
not been told about. src/main/jenkins/jenkins-request.ts went through the
injected HttpClient without being registered, so shard 5 failed on 'keeps
every non-default-session fetcher audited with its expected count'.

Same entry as main/jira/authenticated-request.ts: the injected client resolves
to net.fetch on defaultSession on the desktop, and to the global-fetch-audited
Node fallback elsewhere.
nplez1 added a commit that referenced this pull request Oct 1, 2026
* feat(checks): make the Jenkins build tree readable at scale

The Jenkins details from #39 read the build's stage list but listed every stage in the Checks
pane, buried failures under it, kept an Output box that only repeated the build name, and
stopped at a bare error when the account could not read the job.

- Pane: list only the stages still running and the ones that failed, running first, capped at
  eight, with a "+N more stages" line — a pipeline can have hundreds.
- Detail page: render the stages as a nested tree (stage -> its wfapi flow nodes) like Blue
  Ocean, with failed and running stages open by default.
- Detail page: a Failures block under the run header names each failed stage and its error
  text, so "what broke" needs no scrolling.
- Detail page: drop the Output box for a stage list; the build metadata is the run summary.
- Settings: a Jenkins read failure the user can fix (no server, rejected token, no permission)
  now shows an "Open Jenkins settings" button that deep-links to the Jenkins card.

Main reads each stage's own wfapi/describe (its _links.self.href, bounded to 40 requests at
six concurrent, failed/running first under a four-second budget) for the steps and failure
text, and carries the flow nodes on an optional PRCheckStep.children. The Jenkins node id is
kept so repeated stage names (loops, parallel branches) cannot collide as React keys.

* fix(lint): split files over the max-lines budget

Five files exceed the oxlint max-lines budget on nplez1/main and have no suppression, so the
whole-repo `pnpm exec oxlint` in the static-analysis job fails for every PR cut from it. They
were pushed over by fork-only commits (`#34`, and three direct commits) that never ran PR CI.
The repo's rule is to split rather than suppress, so this extracts cohesive pieces:

- filesystem-watcher.test.ts: the local/WSL lifecycle tests move to
  filesystem-watcher-local-lifecycle.test.ts.
- filesystem-watcher-local-subscription.ts: scheduleLocalWatcherTeardown moves to
  filesystem-watcher-local-teardown.ts.
- ssh-target-cleanup.ts: the per-tab session helpers move to ssh-target-tab-sessions.ts.
- ai-vault-session-refresh.ts: the session-ids key moves to ai-vault-session-ids.ts.
- accounts-search.ts: the Grok and Cursor search entries move to
  accounts-search-extra-providers.ts and are re-exported.

No behavior change; the affected suites pass.
nplez1 added a commit that referenced this pull request Oct 6, 2026
#39)

* feat(checks): read Jenkins build stages and details for Jenkins checks

A CI check that points at Jenkins reaches Orca as a GitHub legacy commit
status: a name, a state and a target_url, with no check-run or workflow-run
id. The only details fetch looked runs up by those ids, so it returned a
valid but empty payload and expanding the check said "No inline details are
available for this check" — while the check was the only place to see which
stage was running or which one broke.

Detect a Jenkins check from its own URL (src/shared/jenkins-urls.ts handles
job prefixes, folders, multibranch, page suffixes, permalinks, and translates
Blue Ocean links to their classic equivalent), then read the build in main
through two GETs: `<build>/api/json?tree=…` for the build and
`<build>/wfapi/describe` for the stage list, best-effort since a freestyle job
has no stages. Stages map onto the existing provider-neutral
`PRCheckJob.steps` (one job per build) and build metadata onto a new optional
`PRCheckRunDetails.build`, so the four existing detail surfaces render it
without a provider-specific path.

`stepRendering: 'all'` marks a stage list: a stage list is the build's shape
rather than a drill-down, so the sidebar lists every stage (including the one
still running) instead of its compact failures-only list, and the editor stops
collapsing stages behind its "N succeeded" toggle. The failures-only filter
itself moved to src/shared/check-step-visibility.ts, where it was duplicated.

Credentials are a list of user-configured servers (base URL, username, API
token), because a user runs several: profiles in ~/.orca/jenkins-servers.json
and one keychain-encrypted token per server. A build URL is matched to a
server by longest configured prefix, not by origin, and a response whose final
URL is outside that prefix is refused, since the Fetch standard only strips
Authorization on a cross-origin hop. Parameter values are masked by kind and
by name before reaching the renderer.

The check-fix prompt now consumes failing stage names, which is what makes a
Jenkins check useful there despite having no log tail.

Endpoint behavior is covered by unit tests with a mocked HTTP client; no live
Jenkins has been exercised, which docs/reference/jenkins-check-details.md
(local-only, not tracked here) records along with the local-reachability and
parameter-masking limits.

* test(main): register the Jenkins fetch call site in the proxy audit

The proxy-guarded fetch audit is stricter than a grep: it counts every
non-`net` `.fetch(` call per main-process file and fails on a count it has
not been told about. src/main/jenkins/jenkins-request.ts went through the
injected HttpClient without being registered, so shard 5 failed on 'keeps
every non-default-session fetcher audited with its expected count'.

Same entry as main/jira/authenticated-request.ts: the injected client resolves
to net.fetch on defaultSession on the desktop, and to the global-fetch-audited
Node fallback elsewhere.
nplez1 added a commit that referenced this pull request Oct 6, 2026
* feat(checks): make the Jenkins build tree readable at scale

The Jenkins details from #39 read the build's stage list but listed every stage in the Checks
pane, buried failures under it, kept an Output box that only repeated the build name, and
stopped at a bare error when the account could not read the job.

- Pane: list only the stages still running and the ones that failed, running first, capped at
  eight, with a "+N more stages" line — a pipeline can have hundreds.
- Detail page: render the stages as a nested tree (stage -> its wfapi flow nodes) like Blue
  Ocean, with failed and running stages open by default.
- Detail page: a Failures block under the run header names each failed stage and its error
  text, so "what broke" needs no scrolling.
- Detail page: drop the Output box for a stage list; the build metadata is the run summary.
- Settings: a Jenkins read failure the user can fix (no server, rejected token, no permission)
  now shows an "Open Jenkins settings" button that deep-links to the Jenkins card.

Main reads each stage's own wfapi/describe (its _links.self.href, bounded to 40 requests at
six concurrent, failed/running first under a four-second budget) for the steps and failure
text, and carries the flow nodes on an optional PRCheckStep.children. The Jenkins node id is
kept so repeated stage names (loops, parallel branches) cannot collide as React keys.

* fix(lint): split files over the max-lines budget

Five files exceed the oxlint max-lines budget on nplez1/main and have no suppression, so the
whole-repo `pnpm exec oxlint` in the static-analysis job fails for every PR cut from it. They
were pushed over by fork-only commits (`#34`, and three direct commits) that never ran PR CI.
The repo's rule is to split rather than suppress, so this extracts cohesive pieces:

- filesystem-watcher.test.ts: the local/WSL lifecycle tests move to
  filesystem-watcher-local-lifecycle.test.ts.
- filesystem-watcher-local-subscription.ts: scheduleLocalWatcherTeardown moves to
  filesystem-watcher-local-teardown.ts.
- ssh-target-cleanup.ts: the per-tab session helpers move to ssh-target-tab-sessions.ts.
- ai-vault-session-refresh.ts: the session-ids key moves to ai-vault-session-ids.ts.
- accounts-search.ts: the Grok and Cursor search entries move to
  accounts-search-extra-providers.ts and are re-exported.

No behavior change; the affected suites pass.
@nplez1
nplez1 deleted the nplez1/Jenkins-Status branch October 24, 2026 03:23
Sign up for free to 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