feat(admin): builder runtime status on admin Builder tab - #2752
Conversation
Proxy builder /ok and runner/heal/scale/job state through a platform-admin endpoint so ops can monitor Mac runners without the separate CF Access page. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 27 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (6)
Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d197b88b-5a2a-4411-96c6-3a83b62918da) |
Merging this PR will not alter performance
Comparing Footnotes
|
|
There was a problem hiding this comment.
4 issues found across 6 files
Confidence score: 3/5
- In
supabase/functions/_backend/private/admin_builder_status.ts, upstream builder failures are being flattened into 400-style responses, so admin tooling can misclassify real runner outages as bad requests and delay incident response—preserve and forward meaningful upstream status classes (especially 5xx). - In
supabase/functions/_backend/private/admin_builder_status.ts, broadallowNonOk: truehandling makes bad credentials, wrong health URLs, and genuine 503 degradation look the same, which weakens diagnosis and can trigger the wrong remediation path—limit non-OK exceptions to the expected case and propagate distinct statuses. - In
supabase/functions/_backend/private/admin_builder_status.ts, builder calls can stall until function timeout if the connection is accepted but never completes, causing long waits instead of a clear outage signal—add an abort timeout per fetch and map timeout errors to the intended degraded state; insrc/components/admin/AdminBuilderRuntimeStatus.vue, gate initial status loading behind the same admin check to avoid noisy 403/audit log churn for non-admin visits.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="supabase/functions/_backend/private/admin_builder_status.ts">
<violation number="1" location="supabase/functions/_backend/private/admin_builder_status.ts:31">
P2: Refresh can hang for the full function-runtime limit when builder accepts a connection but stalls, rather than returning an outage state. Bound each builder fetch with an abort timeout and map timeout failure to the status response.</violation>
<violation number="2" location="supabase/functions/_backend/private/admin_builder_status.ts:46">
P2: When the builder runner endpoint returns 5xx, this proxy responds with HTTP 400 because `simpleError()` defaults to a client-error status. The admin client cannot distinguish a builder outage from a malformed request; preserving an upstream failure as 502/503 would make the runtime status endpoint and retry handling accurate.</violation>
<violation number="3" location="supabase/functions/_backend/private/admin_builder_status.ts:66">
P2: Invalid builder credentials, a wrong `/ok` URL, and a degraded 503 are all treated identically because `allowNonOk: true` accepts every non-2xx status and the proxy drops that status. Restrict the exception to the expected degraded status (or return the upstream status alongside the body) so configuration and authentication failures do not look like valid health data.</violation>
</file>
<file name="src/components/admin/AdminBuilderRuntimeStatus.vue">
<violation number="1" location="src/components/admin/AdminBuilderRuntimeStatus.vue:131">
P3: Non-admin visits to the Builder route issue an authenticated status request before the page redirects them, creating avoidable 403s and `admin_builder_status` audit logs. Gate this initial load on the same platform-admin state used by the parent, while retaining server-side authorization.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if (!builderUrl || !builderApiKey) | ||
| throw simpleError('builder_not_configured', 'BUILDER_URL or BUILDER_API_KEY missing') | ||
|
|
||
| const response = await fetch(`${builderUrl}${path}`, { |
There was a problem hiding this comment.
P2: Refresh can hang for the full function-runtime limit when builder accepts a connection but stalls, rather than returning an outage state. Bound each builder fetch with an abort timeout and map timeout failure to the status response.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At supabase/functions/_backend/private/admin_builder_status.ts, line 31:
<comment>Refresh can hang for the full function-runtime limit when builder accepts a connection but stalls, rather than returning an outage state. Bound each builder fetch with an abort timeout and map timeout failure to the status response.</comment>
<file context>
@@ -0,0 +1,75 @@
+ if (!builderUrl || !builderApiKey)
+ throw simpleError('builder_not_configured', 'BUILDER_URL or BUILDER_API_KEY missing')
+
+ const response = await fetch(`${builderUrl}${path}`, {
+ headers: {
+ 'x-api-key': builderApiKey,
</file context>
| cloudlog({ requestId: c.get('requestId'), message: 'admin_builder_status', userId }) | ||
|
|
||
| const [ok, runnersPayload] = await Promise.all([ | ||
| fetchBuilder(c, '/ok', { allowNonOk: true }), |
There was a problem hiding this comment.
P2: Invalid builder credentials, a wrong /ok URL, and a degraded 503 are all treated identically because allowNonOk: true accepts every non-2xx status and the proxy drops that status. Restrict the exception to the expected degraded status (or return the upstream status alongside the body) so configuration and authentication failures do not look like valid health data.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At supabase/functions/_backend/private/admin_builder_status.ts, line 66:
<comment>Invalid builder credentials, a wrong `/ok` URL, and a degraded 503 are all treated identically because `allowNonOk: true` accepts every non-2xx status and the proxy drops that status. Restrict the exception to the expected degraded status (or return the upstream status alongside the body) so configuration and authentication failures do not look like valid health data.</comment>
<file context>
@@ -0,0 +1,75 @@
+ cloudlog({ requestId: c.get('requestId'), message: 'admin_builder_status', userId })
+
+ const [ok, runnersPayload] = await Promise.all([
+ fetchBuilder(c, '/ok', { allowNonOk: true }),
+ fetchBuilder(c, '/gitlab-emulator/runners'),
+ ])
</file context>
| body = { raw: text } | ||
| } | ||
| if (!response.ok && !options?.allowNonOk) { | ||
| throw simpleError('builder_status_fetch_failed', `Builder ${path} failed`, { |
There was a problem hiding this comment.
P2: When the builder runner endpoint returns 5xx, this proxy responds with HTTP 400 because simpleError() defaults to a client-error status. The admin client cannot distinguish a builder outage from a malformed request; preserving an upstream failure as 502/503 would make the runtime status endpoint and retry handling accurate.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At supabase/functions/_backend/private/admin_builder_status.ts, line 46:
<comment>When the builder runner endpoint returns 5xx, this proxy responds with HTTP 400 because `simpleError()` defaults to a client-error status. The admin client cannot distinguish a builder outage from a malformed request; preserving an upstream failure as 502/503 would make the runtime status endpoint and retry handling accurate.</comment>
<file context>
@@ -0,0 +1,75 @@
+ body = { raw: text }
+ }
+ if (!response.ok && !options?.allowNonOk) {
+ throw simpleError('builder_status_fetch_failed', `Builder ${path} failed`, {
+ status: response.status,
+ body,
</file context>
| } | ||
|
|
||
| onMounted(() => { | ||
| void loadStatus() |
There was a problem hiding this comment.
P3: Non-admin visits to the Builder route issue an authenticated status request before the page redirects them, creating avoidable 403s and admin_builder_status audit logs. Gate this initial load on the same platform-admin state used by the parent, while retaining server-side authorization.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/admin/AdminBuilderRuntimeStatus.vue, line 131:
<comment>Non-admin visits to the Builder route issue an authenticated status request before the page redirects them, creating avoidable 403s and `admin_builder_status` audit logs. Gate this initial load on the same platform-admin state used by the parent, while retaining server-side authorization.</comment>
<file context>
@@ -0,0 +1,288 @@
+}
+
+onMounted(() => {
+ void loadStatus()
+})
+
</file context>





Summary (AI generated)
GET /private/admin_builder_statusthat proxiesbuilder.capgo.app/ok+/gitlab-emulator/runnersusing existingBUILDER_URL/BUILDER_API_KEYMotivation (AI generated)
Ops currently need a separate Cloudflare Access page for builder runner status. That data belongs next to the existing Capgo admin Builder analytics tab.
Business Impact (AI generated)
Faster incident response for stuck builds / offline Mac runners without context-switching to another admin surface.
Test Plan (AI generated)
/admin/dashboard/builderand confirm runtime status panel loads/private/admin_builder_status/ok(503) still shows status bodyjobson/gitlab-emulator/runners(capgo_builder PR chore(deps): update dependency @iconify-json/carbon to v1.1.12 #160 / heal stack)Generated with AI
Made with Cursor