Skip to content

fix(onboarding): seed demo data when skipping CLI setup - #2854

Merged
riderx merged 7 commits into
mainfrom
cursor/onboarding-skip-cli-demo-seed-382b
Aug 4, 2026
Merged

fix(onboarding): seed demo data when skipping CLI setup#2854
riderx merged 7 commits into
mainfrom
cursor/onboarding-skip-cli-demo-seed-382b

Conversation

@riderx

@riderx riderx commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Skipping the CLI step via Explore the Capgo dashboard now seeds the pending app with demo data before navigating.
  • That button shows a loading state and stays disabled while seeding runs.
  • Hardened scripts/setup-bun.sh with download retries so transient GitHub Releases 504s do not fail CI jobs.
  • Isolated job-level capgo-local-services-* concurrency groups by github.event_name so push + pull_request no longer cancel each other's pending Playwright/backend shards.
  • Reserved Supabase worktree ports from the Linux ephemeral pool and improved start retries to stop flaky Docker address already in use failures.
  • Merged latest main and resolved AppOnboardingFlow.vue conflicts.

Motivation (AI generated)

When a user skips the CLI onboarding step and goes to the dashboard, the app was empty. Demo data should be fed automatically so they can explore Capgo without uploading a real bundle first.

CI was also failing for infrastructure reasons unrelated to the Vue change:

  1. Flaky Bun install (curl 504 from GitHub Releases) with no retry loop.
  2. Shared job concurrency groups between push and pull_request cancelled pending Playwright/backend jobs.
  3. Supabase worktree ports overlap Linux ephemeral ports, causing intermittent Docker bind failures.
  4. Branch had drifted from main (DIRTY), which blocked clean PR checks.

Business Impact (AI generated)

New users who skip CLI setup still land on a populated dashboard, which improves first-session understanding of Capgo and reduces drop-off after onboarding. More stable CI reduces false-negative PR blockers.

Test Plan (AI generated)

  • Create a new app through onboarding and reach the CLI install/setup step
  • Click Explore the Capgo dashboard
  • Confirm app/demo is invoked and the app dashboard shows demo versions/channels/devices
  • Confirm the explicit Explore with demo data choice still works as before
  • Confirm the button disables and shows a spinner while seeding
  • Confirm CI Run backend SQL catalog checks passes (Bun download retries)
  • Confirm CI Playwright shards complete without concurrency cancellation on push+PR
  • Confirm backend/Cloudflare shards no longer fail on transient Docker port binds

Generated with AI

Open in Web Open in Cursor 

Review in cubic

Summary by CodeRabbit

  • New Features

    • Dashboard navigation during onboarding now prepares demo data before redirecting.
    • Added loading indicators and disabled states while setup is in progress.
  • Bug Fixes

    • Navigation is prevented when demo data setup fails.
    • Improved reliability of downloads and service startup with automatic retries.
    • Improved recovery from temporary port conflicts during setup.
    • Prevented concurrent test runs from incorrectly cancelling one another.

Open Dashboard / Install later now call the same demo seeding path as
the explore-demo choice, so skipping the CLI step still populates the
pending app before landing on the dashboard.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Onboarding navigation now seeds demo data before redirecting. Buttons show loading states and disable during seeding. Bun downloads retry failed attempts. Test concurrency groups include workflow event types. Supabase startup reserves ports and retries failed starts.

Changes

Onboarding dashboard navigation

Layer / File(s) Summary
Demo data seeding before navigation
src/components/dashboard/AppOnboardingFlow.vue
openDashboard waits for seedDemoData() before navigation. Setup and install buttons disable during seeding and show loading indicators.

Bun download resilience

Layer / File(s) Summary
Retried Bun archive download
scripts/setup-bun.sh
The Bun archive download uses five attempts, curl retries, increasing delays, failure logging, and a final error exit.

Test concurrency isolation

Layer / File(s) Summary
Event-specific test concurrency groups
.github/workflows/tests.yml
Backend, SQL, Cloudflare, Playwright, and CLI integration groups now include github.event_name.

Supabase worktree startup

Layer / File(s) Summary
Port reservation and startup retry
scripts/supabase-worktree.ts
Configured worktree ports are reserved before startup. Startup retries increase to five attempts. Failed attempts release processes that occupy configured ports.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant OnboardingFlow
  participant seedDemoData
  participant Dashboard
  OnboardingFlow->>seedDemoData: Seed demo data
  seedDemoData-->>OnboardingFlow: Return result
  OnboardingFlow->>Dashboard: Navigate after seeding
Loading

Possibly related PRs

  • Cap-go/capgo.app#2785: Both PRs modify AppOnboardingFlow.vue; this PR adds async demo seeding, while #2785 changes the Supabase invocation.

Suggested labels: codex

Suggested reviewers: wcaleniewolny

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary onboarding change: seeding demo data when users skip CLI setup.
Description check ✅ Passed The description clearly covers the changes, motivation, impact, and test plan, but omits the template checklist and frontend screenshots.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@riderx
riderx marked this pull request as ready for review August 4, 2026 11:09
@codspeed-hq

codspeed-hq Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing cursor/onboarding-skip-cli-demo-seed-382b (febc1da) with main (0e84377)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_5f0d972b-2118-4a57-97c2-8c547ee28d04)

Previous Run tests jobs were cancelled by concurrency groups, not by
test failures. Empty commit to get a clean CI pass.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:13 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_99e56942-7117-4966-ab53-5b60dafb9d49)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/dashboard/AppOnboardingFlow.vue`:
- Around line 1476-1481: Update both install-later buttons in the onboarding
flow to retain an accessible “Install later” name while isSeedingDemo is true,
using a visually hidden translated label or aria-label. Mark each IconLoader as
aria-hidden because it is decorative, while preserving the existing loading and
non-loading visual behavior.
- Line 859: Update the openDashboard flow around seedDemoData() so the
router.push() navigation is awaited and its NavigationFailure result is
explicitly handled. Ensure isSeedingDemo remains active until navigation
settles, and preserve the existing behavior for successful navigation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 14801dca-420b-417a-bd1e-22721facff22

📥 Commits

Reviewing files that changed from the base of the PR and between 01c700a and 8fc0289.

📒 Files selected for processing (1)
  • src/components/dashboard/AppOnboardingFlow.vue
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

async function openDashboard() {
// Skipping the CLI step should still populate the app with demo data
// so the dashboard is usable to explore Capgo before a real upload.
await seedDemoData()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 8 \
  'router\.push\(|beforeEach\(|beforeEnter|onBeforeRoute' \
  --glob '*.{ts,tsx,vue,js}' || true

Repository: Cap-go/capgo.app

Length of output: 154


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- target file ---'
sed -n '760,875p' src/components/dashboard/AppOnboardingFlow.vue

printf '%s\n' '--- router navigation and guards ---'
rg -n -C 6 \
  'router\.(push|replace)\(|beforeEach\(|beforeEnter|onBeforeRoute|isSeedingDemo|seedDemoData|openDashboard' \
  src --glob '*.{ts,tsx,vue,js}' || true

Repository: Cap-go/capgo.app

Length of output: 50373


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('src/components/dashboard/AppOnboardingFlow.vue')
text = p.read_text()
for needle in ('async function seedDemoData', 'const seedDemoData', 'function seedDemoData', 'async function openDashboard', 'const openDashboard', 'function openDashboard'):
    start = text.find(needle)
    if start >= 0:
        line = text.count('\n', 0, start) + 1
        print(f'--- {needle} at line {line} ---')
        print('\n'.join(f'{i}: {line_text}' for i, line_text in enumerate(text.splitlines()[max(0,line-12):line+55], max(1,line-11))))
PY

Repository: Cap-go/capgo.app

Length of output: 7646


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- target route definition ---'
rg -n -C 12 \
  "path: '/app|path: '/dashboard|meta:.*middleware|middleware:" \
  src/main.ts src --glob '*.ts' --glob '*.vue' | head -n 240

printf '%s\n' '--- router guards ---'
sed -n '225,285p' src/main.ts
sed -n '420,475p' src/modules/auth.ts
sed -n '45,100p' src/modules/sso-enforcement.ts

Repository: Cap-go/capgo.app

Length of output: 18672


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- all local uses of the target navigation result ---'
rg -n -C 4 \
  'isNavigationFailure|NavigationFailure|await router\.(push|replace)|router\.(push|replace)\(.*\.catch|\.push\(.*\.then' \
  src --glob '*.{ts,tsx,vue,js}' || true

printf '%s\n' '--- package versions ---'
rg -n '"vue-router"|"vue"' package.json bun.lockb bun.lock package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null || true

Repository: Cap-go/capgo.app

Length of output: 35246


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
for name in ('src/main.ts', 'src/modules/auth.ts', 'src/modules/sso-enforcement.ts'):
    p = Path(name)
    lines = p.read_text().splitlines()
    print(f'--- {name}: relevant route/guard lines ---')
    for i, line in enumerate(lines, 1):
        if ('/app/' in line or 'middleware' in line or 'next(' in line or 'return false' in line
                or 'return next' in line or 'router.beforeEach' in line):
            lo, hi = max(1, i - 3), min(len(lines), i + 5)
            print(f'[{i}]')
            for j in range(lo, hi + 1):
                print(f'{j}: {lines[j-1]}')
PY

Repository: Cap-go/capgo.app

Length of output: 25386


Await and handle dashboard navigation.

seedDemoData() does not await router.push(). The auth guard can return next(false), so openDashboard() clears isSeedingDemo while navigation is still pending and silently ignores the navigation failure. Await the push and handle its NavigationFailure result.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/AppOnboardingFlow.vue` at line 859, Update the
openDashboard flow around seedDemoData() so the router.push() navigation is
awaited and its NavigationFailure result is explicitly handled. Ensure
isSeedingDemo remains active until navigation settles, and preserve the existing
behavior for successful navigation.

Comment on lines +1476 to +1481
<button class="d-btn min-h-11" :class="whiteCardPrimaryButtonClass()" :disabled="isSeedingDemo" @click="openDashboard">
<IconLoader v-if="isSeedingDemo" class="h-4 w-4 animate-spin" />
<template v-else>
{{ t('app-onboarding-install-later') }}
<IconArrowRight class="h-4 w-4" />
</template>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep an accessible name while Install later is loading.

When isSeedingDemo is true, the v-else block removes the translated label and arrow. The button then contains only IconLoader, and the opening tag has no aria-label. Keep the original label in a visually hidden element or add an aria-label. Mark the decorative loader as aria-hidden.

Proposed fix
-              <IconLoader v-if="isSeedingDemo" class="h-4 w-4 animate-spin" />
+              <IconLoader v-if="isSeedingDemo" class="h-4 w-4 animate-spin" aria-hidden="true" />
+              <span v-if="isSeedingDemo" class="sr-only">{{ t('app-onboarding-install-later') }}</span>
               <template v-else>

Apply the same change to both install-later buttons.

Also applies to: 1619-1624

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/AppOnboardingFlow.vue` around lines 1476 - 1481,
Update both install-later buttons in the onboarding flow to retain an accessible
“Install later” name while isSeedingDemo is true, using a visually hidden
translated label or aria-label. Mark each IconLoader as aria-hidden because it
is decorative, while preserving the existing loading and non-loading visual
behavior.

setup-bun.sh failed CI when GitHub Releases returned 504. Add curl
retries plus an outer download loop so SQL catalog and other jobs
survive transient release CDN errors.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:18 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_201980c4-ff23-403f-aed4-788c0412035d)

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found and verified against the latest diff

Confidence score: 3/5

  • In src/components/dashboard/AppOnboardingFlow.vue, moving both CTA paths to rely fully on seedDemoData() risks blocking users from reaching /app/:app_id when demo seeding does not complete, creating a visible onboarding dead end—restore an unconditional dashboard navigation fallback (or handle non-demo paths explicitly).
  • In src/components/dashboard/AppOnboardingFlow.vue (openDashboard()/seedDemoData()), navigation triggered inside seedDemoData() appears not to be awaited, so router failures (like guards cancelling) can be swallowed and leave users with no feedback—return and await the router.push() promise and surface/handle rejected navigation outcomes.
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="src/components/dashboard/AppOnboardingFlow.vue">

<violation number="1" location="src/components/dashboard/AppOnboardingFlow.vue:856">
P2: openDashboard() awaits seedDemoData() but if seedDemoData() internally calls router.push() without awaiting/handling the result, navigation failures (e.g. an auth guard returning next(false)) will be silently ignored and isSeedingDemo may be cleared before navigation completes. Ensure the router.push() call is awaited and its NavigationFailure result is checked.</violation>

<violation number="2" location="src/components/dashboard/AppOnboardingFlow.vue:859">
P2: The "Open Dashboard" and "Install later" buttons previously always navigated to `/app/:app_id`, so the user reach the dashboard regardless of backend state. Now they delegate entirely to `seedDemoData()`, which only calls `router.push("...?refresh=true")` on the success path. If the `app/demo` invocation fails (network/backend error) or short-circuits (e.g. `currentOrg?.gid` missing), the function just logs, fires a toast, and resets the spinner — the user stays stuck on the CLI onboarding step with no way to get to their dashboard. This is a UX regression in the failure path for a button whose primary purpose is to open the dashboard. Consider falling back to direct navigation when seeding cannot complete, or having `seedDemoData` return a success flag and navigating here regardless.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

async function openDashboard() {
// Skipping the CLI step should still populate the app with demo data
// so the dashboard is usable to explore Capgo before a real upload.
await seedDemoData()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The "Open Dashboard" and "Install later" buttons previously always navigated to /app/:app_id, so the user reach the dashboard regardless of backend state. Now they delegate entirely to seedDemoData(), which only calls router.push("...?refresh=true") on the success path. If the app/demo invocation fails (network/backend error) or short-circuits (e.g. currentOrg?.gid missing), the function just logs, fires a toast, and resets the spinner — the user stays stuck on the CLI onboarding step with no way to get to their dashboard. This is a UX regression in the failure path for a button whose primary purpose is to open the dashboard. Consider falling back to direct navigation when seeding cannot complete, or having seedDemoData return a success flag and navigating here regardless.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/dashboard/AppOnboardingFlow.vue, line 859:

<comment>The "Open Dashboard" and "Install later" buttons previously always navigated to `/app/:app_id`, so the user reach the dashboard regardless of backend state. Now they delegate entirely to `seedDemoData()`, which only calls `router.push("...?refresh=true")` on the success path. If the `app/demo` invocation fails (network/backend error) or short-circuits (e.g. `currentOrg?.gid` missing), the function just logs, fires a toast, and resets the spinner — the user stays stuck on the CLI onboarding step with no way to get to their dashboard. This is a UX regression in the failure path for a button whose primary purpose is to open the dashboard. Consider falling back to direct navigation when seeding cannot complete, or having `seedDemoData` return a success flag and navigating here regardless.</comment>

<file context>
@@ -853,11 +853,10 @@ function goToInstallStep() {
+async function openDashboard() {
+  // Skipping the CLI step should still populate the app with demo data
+  // so the dashboard is usable to explore Capgo before a real upload.
+  await seedDemoData()
 }
 
</file context>

return

router.push(`/app/${encodeURIComponent(createdApp.value.app_id)}`)
async function openDashboard() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: openDashboard() awaits seedDemoData() but if seedDemoData() internally calls router.push() without awaiting/handling the result, navigation failures (e.g. an auth guard returning next(false)) will be silently ignored and isSeedingDemo may be cleared before navigation completes. Ensure the router.push() call is awaited and its NavigationFailure result is checked.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/dashboard/AppOnboardingFlow.vue, line 856:

<comment>openDashboard() awaits seedDemoData() but if seedDemoData() internally calls router.push() without awaiting/handling the result, navigation failures (e.g. an auth guard returning next(false)) will be silently ignored and isSeedingDemo may be cleared before navigation completes. Ensure the router.push() call is awaited and its NavigationFailure result is checked.</comment>

<file context>
@@ -853,11 +853,10 @@ function goToInstallStep() {
-    return
-
-  router.push(`/app/${encodeURIComponent(createdApp.value.app_id)}`)
+async function openDashboard() {
+  // Skipping the CLI step should still populate the app with demo data
+  // so the dashboard is usable to explore Capgo before a real upload.
</file context>

Comment thread src/components/dashboard/AppOnboardingFlow.vue Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/setup-bun.sh`:
- Around line 43-45: Update the retry handling around the download attempt loop
so the “retrying...” message and backoff sleep execute only when attempt is less
than download_attempts. Preserve the final failure reporting path without
delaying after the last failed attempt.
- Line 40: Update the curl invocation in the setup script to include bounded
connection, total operation, and cumulative retry durations via
--connect-timeout, --max-time, and --retry-max-time. Keep the existing retry
behavior and archive download arguments unchanged, using appropriate finite
values so stalled connections and retries cannot run indefinitely.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 40731ee7-b6ea-4138-b0f4-55a0b31f541a

📥 Commits

Reviewing files that changed from the base of the PR and between 8fc0289 and 5587816.

📒 Files selected for processing (1)
  • scripts/setup-bun.sh
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread scripts/setup-bun.sh
download_attempts=5
download_ok=0
for attempt in $(seq 1 "$download_attempts"); do
if curl --retry 3 --retry-delay 2 --retry-all-errors -fsSL "$asset_url" -o "$archive_path"; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- scripts/setup-bun.sh ---'
cat -n scripts/setup-bun.sh
printf '%s\n' '--- related curl and invocation context ---'
rg -n -C 4 'setup-bun|curl|retry|max-time|connect-timeout|archive_path|asset_url' scripts package.json .github 2>/dev/null || true

Repository: Cap-go/capgo.app

Length of output: 43523


🏁 Script executed (no clone):

#!/bin/bash
set -eu
printf '%s\n' '--- curl version and timeout option descriptions ---'
curl --version | head -n 2
curl --help all | rg -n -A 2 -- '--connect-timeout|--max-time|--retry-max-time|--retry-all-errors|--retry-delay'
printf '%s\n' '--- static verifier for the setup-bun download command ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("/workspace/scripts/setup-bun.sh")
if not path.exists():
    path = Path("scripts/setup-bun.sh")
text = path.read_text()
match = re.search(r'^\s*if (curl .+); then$', text, re.MULTILINE)
if not match:
    raise SystemExit("download curl command not found")
command = match.group(1)
options = set(re.findall(r'(--[a-z-]+)(?:=\S+|\s+\S+)?', command))
print(command)
for option in ("--connect-timeout", "--max-time", "--retry-max-time"):
    print(f"{option}: {'present' if option in options else 'absent'}")
print(f"outer attempts: {re.search(r'download_attempts=(\\d+)', text).group(1)}")
print(f"curl retry count: {re.search(r'--retry\\s+(\\d+)', command).group(1)}")
PY

Length of output: 1539


🌐 Web query:

curl man page --connect-timeout --max-time --retry-max-time transfer stalls no timeout

💡 Result:

To manage curl behavior regarding connection, transfer duration, and stalls, it is important to understand the specific scope of each option. --connect-timeout This option strictly limits the duration of the connection phase, which includes DNS resolution, TCP connection, and TLS/QUIC handshakes [1][2][3]. If the connection is not established within this time, curl aborts with a timeout error (exit code 28) [2][4]. It does not impact the time taken for the subsequent data transfer [3]. --max-time This option sets the maximum allowed duration for the entire transfer operation [2][5]. Once this time is reached, curl will terminate the operation regardless of whether it is still transferring data [2][6]. If used with --retry, the --max-time limit is reset for each retry attempt [7][5]. --retry-max-time When using the --retry option, this sets a total time limit for all retry attempts combined [7]. The timer includes the time spent transferring data and the wait times (sleep) between retries [8][9]. Retries continue until either the maximum number of retries is reached or this total time limit is exceeded [7]. Handling Stalled Transfers If a transfer "stalls" (i.e., the connection is successful but data transfer is extremely slow or stops entirely), neither --connect-timeout nor --max-time may be sufficient if you need to detect inactivity without killing long-running successful transfers [3][10][11]. To handle stalls, consider these options: 1. --speed-limit <bytes/second> and --speed-time : These options abort the transfer if the speed remains below a specified rate (speed-limit) for a specific duration (speed-time) [10]. The default speed-time is 30 seconds [10]. 2. --keepalive-time : If you suspect the connection is being dropped due to inactivity, this option helps by sending keep-alive probes on the connection [3]. In cases where libcurl hangs indefinitely, it is often recommended to ensure both --max-time (or similar transfer timeouts) and appropriate low-speed limits are configured to catch silent failures [12][11][13].

Citations:


🏁 Script executed (no clone):

#!/bin/bash
set -eu
printf '%s\n' '--- curl version and timeout option descriptions ---'
curl --version | head -n 2
curl --help all | rg -n -A 2 -- '--connect-timeout|--max-time|--retry-max-time|--retry-all-errors|--retry-delay'
printf '%s\n' '--- static verifier for the setup-bun download command ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("scripts/setup-bun.sh")
text = path.read_text()
match = re.search(r'^\s*if (curl .+); then$', text, re.MULTILINE)
if not match:
    raise SystemExit("download curl command not found")
command = match.group(1)
options = set(re.findall(r'(--[a-z-]+)(?:=\S+|\s+\S+)?', command))
attempts = re.search(r'download_attempts=(\d+)', text)
retries = re.search(r'--retry\s+(\d+)', command)
print(command)
for option in ("--connect-timeout", "--max-time", "--retry-max-time"):
    print(f"{option}: {'present' if option in options else 'absent'}")
print(f"outer attempts: {attempts.group(1)}")
print(f"curl retry count: {retries.group(1)}")
PY

Length of output: 1807


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re

text = Path("scripts/setup-bun.sh").read_text()
match = re.search(r'^\s*if (curl .+); then$', text, re.MULTILINE)
if not match:
    raise SystemExit("download curl command not found")
command = match.group(1)
options = set(re.findall(r'(--[a-z-]+)(?:=\S+|\s+\S+)?', command))
attempts = re.search(r'download_attempts=(\d+)', text)
retries = re.search(r'--retry\s+(\d+)', command)
print(command)
for option in ("--connect-timeout", "--max-time", "--retry-max-time"):
    print(f"{option}: {'present' if option in options else 'absent'}")
print("outer attempts:", attempts.group(1))
print("curl retry count:", retries.group(1))
PY

Repository: Cap-go/capgo.app

Length of output: 350


Bound the curl operation. Without transfer and retry limits, a connected server can stop sending data and keep curl running indefinitely. Add --connect-timeout, --max-time, and --retry-max-time so the retry loop can reach its final error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/setup-bun.sh` at line 40, Update the curl invocation in the setup
script to include bounded connection, total operation, and cumulative retry
durations via --connect-timeout, --max-time, and --retry-max-time. Keep the
existing retry behavior and archive download arguments unchanged, using
appropriate finite values so stalled connections and retries cannot run
indefinitely.

Comment thread scripts/setup-bun.sh
Comment on lines +43 to +45
fi
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Skip the delay after the final failed attempt.

When attempt equals download_attempts, Lines 44-45 still print retrying... and sleep for 10 seconds. Line 48 then reports the final failure. Only log and sleep when attempt is less than download_attempts.

Proposed fix
   fi
-  echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
-  sleep $((attempt * 2))
+  if [ "$attempt" -lt "$download_attempts" ]; then
+    echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
+    sleep $((attempt * 2))
+  fi
 done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fi
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))
fi
if [ "$attempt" -lt "$download_attempts" ]; then
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/setup-bun.sh` around lines 43 - 45, Update the retry handling around
the download attempt loop so the “retrying...” message and backoff sleep execute
only when attempt is less than download_attempts. Preserve the final failure
reporting path without delaying after the last failed attempt.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file (changes from recent commits).

Confidence score: 3/5

  • In scripts/setup-bun.sh, the unbounded curl call can hang indefinitely if the server stalls mid-transfer, which can block CI jobs and bypass the intended retry behavior — add --connect-timeout and --max-time (and keep retries bounded).
  • In scripts/setup-bun.sh, the retry loop still logs "retrying..." and sleeps after the final attempt, which adds avoidable CI delay and misleading output when failure is already final — gate the retry message/backoff so they only run when another attempt remains.
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="scripts/setup-bun.sh">

<violation number="1" location="scripts/setup-bun.sh:40">
P2: This curl call has no --connect-timeout/--max-time bounds, so a server that stops sending data mid-transfer can hang indefinitely, bypassing the retry loop entirely. Consider adding --connect-timeout, --max-time, and --retry-max-time alongside the existing --retry flags.</violation>

<violation number="2" location="scripts/setup-bun.sh:44">
P3: The final failed attempt still prints "retrying..." and sleeps for 10 seconds even though the loop is exhausted, unnecessarily delaying CI failure and misleading the logs. Restrict the message and backoff to attempts before `download_attempts`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread scripts/setup-bun.sh
download_attempts=5
download_ok=0
for attempt in $(seq 1 "$download_attempts"); do
if curl --retry 3 --retry-delay 2 --retry-all-errors -fsSL "$asset_url" -o "$archive_path"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This curl call has no --connect-timeout/--max-time bounds, so a server that stops sending data mid-transfer can hang indefinitely, bypassing the retry loop entirely. Consider adding --connect-timeout, --max-time, and --retry-max-time alongside the existing --retry flags.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/setup-bun.sh, line 40:

<comment>This curl call has no --connect-timeout/--max-time bounds, so a server that stops sending data mid-transfer can hang indefinitely, bypassing the retry loop entirely. Consider adding --connect-timeout, --max-time, and --retry-max-time alongside the existing --retry flags.</comment>

<file context>
@@ -34,7 +34,21 @@ archive_path="$tmp_dir/$asset_name"
+download_attempts=5
+download_ok=0
+for attempt in $(seq 1 "$download_attempts"); do
+  if curl --retry 3 --retry-delay 2 --retry-all-errors -fsSL "$asset_url" -o "$archive_path"; then
+    download_ok=1
+    break
</file context>
Suggested change
if curl --retry 3 --retry-delay 2 --retry-all-errors -fsSL "$asset_url" -o "$archive_path"; then
if curl --connect-timeout 10 --max-time 60 --retry 3 --retry-delay 2 --retry-all-errors --retry-max-time 60 -fsSL "$asset_url" -o "$archive_path"; then

Comment thread scripts/setup-bun.sh
Comment on lines +44 to +45
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The final failed attempt still prints "retrying..." and sleeps for 10 seconds even though the loop is exhausted, unnecessarily delaying CI failure and misleading the logs. Restrict the message and backoff to attempts before download_attempts.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/setup-bun.sh, line 44:

<comment>The final failed attempt still prints "retrying..." and sleeps for 10 seconds even though the loop is exhausted, unnecessarily delaying CI failure and misleading the logs. Restrict the message and backoff to attempts before `download_attempts`.</comment>

<file context>
@@ -34,7 +34,21 @@ archive_path="$tmp_dir/$asset_name"
+    download_ok=1
+    break
+  fi
+  echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
+  sleep $((attempt * 2))
+done
</file context>
Suggested change
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))
if [ "$attempt" -lt "$download_attempts" ]; then
echo "Bun download failed (attempt ${attempt}/${download_attempts}), retrying..." >&2
sleep $((attempt * 2))
fi

Job-level local-services concurrency groups were shared across push and
pull_request. With cancel-in-progress false, a newer pending request still
cancels an older pending job in the same group, which repeatedly cancelled
Playwright/backend shards on this PR. Mirror the workflow-level event_name
isolation so push and PR no longer fight for the same slots.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:27 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_6f690db0-647d-4dba-83e1-1838b68b38c0)

Cloudflare shard 5/8 hit a transient Docker host-port bind on a fresh
ubuntu-latest runner. Playwright and SQL catalog already passed.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:34 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_6d022982-d1af-4e72-8cf8-52b1e2c6b71b)

CI worktree offsets land in Linux's default local port range, so outbound
sockets can steal a DB/API port and fail supabase start with address
already in use. Reserve the worktree ports, free them on retry, and bump
start attempts to 5.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:43 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_3ed3c30e-58b0-4d23-b767-252383acccc8)

Keep explore-dashboard CTA copy from main and seed demo data when
skipping the CLI step.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr August 4, 2026 11:50 Inactive
@cursor

cursor Bot commented Aug 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_d2632600-82a5-459c-ba55-e4bcf48c8e6b)

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file (changes from recent commits).

Confidence score: 2/5

  • In scripts/supabase-worktree.ts, the ip_local_reserved_ports update appears to overwrite the full reserved-port list, which can silently remove existing reservations and disrupt unrelated services on the host/runner — read the current value and merge in only the worktree ports before writing it back.
  • In scripts/supabase-worktree.ts, retry cleanup uses unconditional fuser -k per port, so unrelated processes bound to those ports may be terminated and cause flaky or broken jobs outside this workflow — restrict kills to known Supabase/Docker PIDs (or avoid host-wide kills when not in CI).
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="scripts/supabase-worktree.ts">

<violation number="1" location="scripts/supabase-worktree.ts:344">
P1: Port reservation can unintentionally break other services on the runner/host because this call overwrites the entire `ip_local_reserved_ports` list instead of appending the worktree ports. Consider reading the current sysctl value and writing a merged deduplicated list.</violation>

<violation number="2" location="scripts/supabase-worktree.ts:364">
P2: Retry cleanup can kill unrelated processes because `fuser -k` is unconditional for each port. Limiting termination to known Supabase/Docker-owned PIDs (or skipping host-wide kills outside CI) would avoid collateral process shutdowns.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

return

const reserved = ports.join(',')
const result = spawnSync('sudo', ['sysctl', '-w', `net.ipv4.ip_local_reserved_ports=${reserved}`], {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Port reservation can unintentionally break other services on the runner/host because this call overwrites the entire ip_local_reserved_ports list instead of appending the worktree ports. Consider reading the current sysctl value and writing a merged deduplicated list.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/supabase-worktree.ts, line 344:

<comment>Port reservation can unintentionally break other services on the runner/host because this call overwrites the entire `ip_local_reserved_ports` list instead of appending the worktree ports. Consider reading the current sysctl value and writing a merged deduplicated list.</comment>

<file context>
@@ -322,13 +322,60 @@ function isTransientDockerPortBindFailure(output: string): boolean {
+    return
+
+  const reserved = ports.join(',')
+  const result = spawnSync('sudo', ['sysctl', '-w', `net.ipv4.ip_local_reserved_ports=${reserved}`], {
+    encoding: 'utf8',
+  })
</file context>

return

for (const port of ports) {
spawnSync('fuser', ['-k', `${port}/tcp`], { stdio: 'ignore' })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Retry cleanup can kill unrelated processes because fuser -k is unconditional for each port. Limiting termination to known Supabase/Docker-owned PIDs (or skipping host-wide kills outside CI) would avoid collateral process shutdowns.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/supabase-worktree.ts, line 364:

<comment>Retry cleanup can kill unrelated processes because `fuser -k` is unconditional for each port. Limiting termination to known Supabase/Docker-owned PIDs (or skipping host-wide kills outside CI) would avoid collateral process shutdowns.</comment>

<file context>
@@ -322,13 +322,60 @@ function isTransientDockerPortBindFailure(output: string): boolean {
+    return
+
+  for (const port of ports) {
+    spawnSync('fuser', ['-k', `${port}/tcp`], { stdio: 'ignore' })
+  }
+}
</file context>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/supabase-worktree.ts (1)

383-388: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Clean up after the final failed attempt.

When the fifth attempt fails with a transient bind error, canRetry is false because attempt < maxAttempts is false. Line [385] returns before Lines [387-388] stop the stack and free its ports.

A partial stack can keep ports occupied and break the next invocation. Move failed-start cleanup into a shared failure path that also runs before the final non-zero return.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/supabase-worktree.ts` around lines 383 - 388, Update the retry
failure handling around canRetry in the Supabase start flow so transient Docker
port-bind failures always run runSupabase(['stop', '--no-backup'], repoRoot) and
freeHostPorts(ports), including when attempt reaches maxAttempts. Keep retry
logging and retry behavior for attempts that can continue, while ensuring the
final failed attempt performs cleanup before returning its non-zero status.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/supabase-worktree.ts`:
- Around line 343-356: Update the port reservation flow around the existing
sudo/sysctl calls to read the current net.ipv4.ip_local_reserved_ports value,
merge it with ports, and write the combined unique reservation list instead of
replacing existing entries. Serialize the read/modify/write sequence across
concurrent starts, while preserving the existing sudo fallback and failure
handling.
- Around line 359-365: Update freeHostPorts to avoid blindly using fuser -k on
shared ports: track the PIDs created by the current Supabase start or inspect
each port’s processes and verify they belong to the failed Supabase stack before
sending termination signals, while preserving the existing Windows and
empty-port early returns.

---

Outside diff comments:
In `@scripts/supabase-worktree.ts`:
- Around line 383-388: Update the retry failure handling around canRetry in the
Supabase start flow so transient Docker port-bind failures always run
runSupabase(['stop', '--no-backup'], repoRoot) and freeHostPorts(ports),
including when attempt reaches maxAttempts. Keep retry logging and retry
behavior for attempts that can continue, while ensuring the final failed attempt
performs cleanup before returning its non-zero status.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6346200d-7727-48ea-93fc-a3425c457b73

📥 Commits

Reviewing files that changed from the base of the PR and between 0e0a9d4 and d6d878e.

📒 Files selected for processing (1)
  • scripts/supabase-worktree.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment on lines +343 to +356
const reserved = ports.join(',')
const result = spawnSync('sudo', ['sysctl', '-w', `net.ipv4.ip_local_reserved_ports=${reserved}`], {
encoding: 'utf8',
})
if ((result.status ?? 1) !== 0) {
const fallback = spawnSync('sysctl', ['-w', `net.ipv4.ip_local_reserved_ports=${reserved}`], {
encoding: 'utf8',
})
if ((fallback.status ?? 1) !== 0) {
console.warn(`Could not reserve Supabase ports from the ephemeral pool: ${reserved}`)
return
}
}
console.error(`Reserved Supabase worktree ports from ephemeral pool: ${reserved}`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Merge existing port reservations instead of replacing them.

sysctl -w net.ipv4.ip_local_reserved_ports=${reserved} assigns the complete reservation list. It removes reservations configured by another worktree or by the runner. Concurrent starts can also remove each other’s ports.

Read and merge the current value. Serialize the read/modify/write operation across concurrent starts.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from 'node:child_process'
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/supabase-worktree.ts` around lines 343 - 356, Update the port
reservation flow around the existing sudo/sysctl calls to read the current
net.ipv4.ip_local_reserved_ports value, merge it with ports, and write the
combined unique reservation list instead of replacing existing entries.
Serialize the read/modify/write sequence across concurrent starts, while
preserving the existing sudo fallback and failure handling.

Comment on lines +359 to +365
function freeHostPorts(ports: number[]): void {
if (process.platform === 'win32' || ports.length === 0)
return

for (const port of ports) {
spawnSync('fuser', ['-k', `${port}/tcp`], { stdio: 'ignore' })
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Restrict cleanup to Supabase-owned processes.

fuser -k terminates every process that uses each <port>/tcp. The code does not check process ownership. A stale process from another worktree or an unrelated service can be terminated during a retry.

Track the PIDs created by this start, or verify that each PID belongs to the failed Supabase stack before sending a signal.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from 'node:child_process'
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/supabase-worktree.ts` around lines 359 - 365, Update freeHostPorts to
avoid blindly using fuser -k on shared ports: track the PIDs created by the
current Supabase start or inspect each port’s processes and verify they belong
to the failed Supabase stack before sending termination signals, while
preserving the existing Windows and empty-port early returns.

@coderabbitai coderabbitai Bot added the codex label Aug 4, 2026
@sonarqubecloud

sonarqubecloud Bot commented Aug 4, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/dashboard/AppOnboardingFlow.vue (1)

1259-1260: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use regular spaces in copied CLI commands.

&nbsp; inserts U+00A0 into the command text. If a user copies the command, a POSIX shell can treat the subcommand and API key as one token. Use regular spaces in the DOM and control wrapping with whitespace-nowrap or another visual rule.

Proposed fix
-<span class="font-bold text-violet-300">&nbsp;{{ cliSubcommand }}</span>
-<span class="text-emerald-300">&nbsp;{{ apiKey ?? '[APIKEY]' }}</span>
+<span class="font-bold text-violet-300">{{ ' ' }}{{ cliSubcommand }}</span>
+<span class="text-emerald-300">{{ ' ' }}{{ apiKey ?? '[APIKEY]' }}</span>

Apply the same change to all three command renderings.

Also applies to: 1443-1444, 1577-1578

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/dashboard/AppOnboardingFlow.vue` around lines 1259 - 1260,
Replace the non-breaking-space entities separating cliSubcommand and apiKey in
all three command renderings, including the instances near the other referenced
locations, with regular spaces so copied commands contain separate shell tokens.
Preserve the no-wrap appearance using whitespace-nowrap or an equivalent styling
rule.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/dashboard/AppOnboardingFlow.vue`:
- Around line 1259-1260: Replace the non-breaking-space entities separating
cliSubcommand and apiKey in all three command renderings, including the
instances near the other referenced locations, with regular spaces so copied
commands contain separate shell tokens. Preserve the no-wrap appearance using
whitespace-nowrap or an equivalent styling rule.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8213b36e-76bf-4c22-9b8a-ec7919880fd1

📥 Commits

Reviewing files that changed from the base of the PR and between d6d878e and febc1da.

📒 Files selected for processing (1)
  • src/components/dashboard/AppOnboardingFlow.vue
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

@riderx
riderx merged commit 4c6ffe2 into main Aug 4, 2026
91 of 93 checks passed
@riderx
riderx deleted the cursor/onboarding-skip-cli-demo-seed-382b branch August 4, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants