Files
orca/mobile/src/tasks/github-check-summary.ts
T
KyuJoo HanandOrcaWin 6f3845baa4 fix(checks): rank successful checks above skipped and neutral (#11337)
* fix(checks): rank successful checks above skipped and neutral

Checks were ordered with `skipped` (4) and `neutral` (3) ahead of
`success` (5), so a PR with a long tail of skipped jobs pushed every
passing check below the fold — you scroll past a wall of "Skipped" to
find out whether anything actually ran.

Rank the no-signal conclusions last (`success` 3, `neutral` 4, `skipped`
5) and pull the order out of its three duplicated copies
(checks-panel-content, PullRequestPage, GitHubItemDialog) into
`src/shared/pr-check-severity-order.ts`. Unknown conclusions now sink to
the bottom instead of silently ranking as `neutral`.

* fix(checks): look up check ranks through a Map, not an object literal

An object-literal rank table resolves `constructor`, `toString`, and
`__proto__` off Object.prototype, so those keys returned a function
instead of falling through to UNKNOWN_CHECK_RANK — the comparator then
subtracted functions, went NaN, and left the list in arbitrary order.
Conclusions come from provider payloads, so keep the lookup on a Map and
cover prototype property names in the test.

* test(checks): cover provider-neutral ordering states

* fix(checks): preserve actionable provider states

* fix(checks): preserve unresolved provider rollups

* fix(checks): keep unknown GitLab rollups neutral

* fix: preserve neutral review check summaries

* fix: complete provider-neutral check ordering remediation

* fix: use provider-neutral mobile review status input

* fix: hydrate GitLab mobile review status

* fix: type mobile GitLab review hydration

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-07-30 13:29:41 -07:00

61 lines
1.4 KiB
TypeScript

export type GitHubCheckLike = {
status: string
conclusion?: string | null
}
export type GitHubCheckSummary = {
state: 'success' | 'failure' | 'pending' | 'neutral' | 'none'
total: number
passed: number
failed: number
pending: number
neutral: number
}
function isFailedCheck(check: GitHubCheckLike): boolean {
return (
check.conclusion === 'failure' ||
check.conclusion === 'timed_out' ||
check.conclusion === 'cancelled'
)
}
function isPendingCheck(check: GitHubCheckLike): boolean {
return (
check.status === 'queued' || check.status === 'in_progress' || check.conclusion === 'pending'
)
}
export function buildGitHubCheckSummary(checks: GitHubCheckLike[]): GitHubCheckSummary {
let failed = 0
let pending = 0
let neutral = 0
for (const check of checks) {
if (isFailedCheck(check) || check.conclusion === 'action_required') {
failed += 1
} else if (isPendingCheck(check)) {
pending += 1
} else if (check.conclusion === 'success') {
continue
} else {
neutral += 1
}
}
const total = checks.length
const passed = total - failed - pending - neutral
const state =
total === 0
? 'none'
: failed > 0
? 'failure'
: pending > 0
? 'pending'
: neutral > 0
? 'neutral'
: 'success'
return { state, total, passed, failed, pending, neutral }
}