Skip to content

feat(scripts): add try-pr.sh for testing PR worktrees locally#254

Open
suraj-markup wants to merge 1 commit intoComposioHQ:mainfrom
suraj-markup:feat/try-pr-script
Open

feat(scripts): add try-pr.sh for testing PR worktrees locally#254
suraj-markup wants to merge 1 commit intoComposioHQ:mainfrom
suraj-markup:feat/try-pr-script

Conversation

@suraj-markup
Copy link
Collaborator

Summary

Adds scripts/try-pr.sh — a helper script for manually testing changes in any agent session's worktree without permanently changing the global ao command.

Also fixes a false positive bug in isPortAvailable() that caused port-busy warnings to never fire on macOS.


scripts/try-pr.sh

The problem it solves

When an agent session finishes work, the global ao command still points to main. To test the PR's changes you'd have to manually:

  1. cd ~/.worktrees/ao/ao-XX
  2. pnpm build
  3. cd packages/cli && pnpm link --global
  4. Test
  5. Remember to restore back to main

Easy to forget step 5 and end up running PR code thinking it's main.

Usage

# Test CLI/core/plugin changes (~15s build)
bash scripts/try-pr.sh ao-22

# Test dashboard changes too — builds Next.js and starts dev server
bash scripts/try-pr.sh ao-22 --with-web

# Switch back to main when done
bash scripts/try-pr.sh --restore

How it works

  • Builds the worktree (CLI/core/plugins only by default, full build with --with-web)
  • Rewrites the pnpm shim at $(which ao) to point at the worktree's dist/index.js
  • Saves the original shim so --restore can put it back exactly
  • With --with-web: finds a free port (starting at 3001 to avoid conflicting with the running ao start on 3000), passes AO_CONFIG_PATH pointing at your real config so actual sessions show up in the PR dashboard
  • Detects if the PR has web changes and hints to use --with-web if you forgot

isPortAvailable() fix

Problem: The original implementation probed by binding to 127.0.0.1. On macOS, Next.js / pnpm dev listens on :: (IPv6 wildcard) with IPV6_V6ONLY=1, so binding 127.0.0.1 (IPv4) succeeded even when the port was taken — causing port-busy warnings to never fire.

Fix: Switched from bind-based to connect-based detection. A successful TCP connect means something is listening (port in use). ECONNREFUSED means the port is free. Works regardless of whether the listener is on 127.0.0.1, ::1, 0.0.0.0, or ::.

// Before: bind probe — false positive when listener is on ::
server.listen(port, "127.0.0.1");

// After: connect probe — reliable across all bind addresses
s.connect(port, "127.0.0.1");
s.once("connect", () => resolve(false)); // in use
s.once("error",   () => resolve(true));  // free

🤖 Generated with Claude Code

Adds scripts/try-pr.sh — a helper to switch the global 'ao' command to
any session's worktree for manual testing, then restore back to main.

Usage:
  bash scripts/try-pr.sh <session-id>            # CLI/core/plugins only
  bash scripts/try-pr.sh <session-id> --with-web # also builds + starts dashboard
  bash scripts/try-pr.sh --restore               # switch back to main

Also fixes isPortAvailable() to use a connect-based probe instead of
bind-based. The old approach had false positives on macOS when Next.js
listens on :: (IPv6 wildcard) — binding 127.0.0.1 succeeded even though
the port was taken. A TCP connect correctly detects any listener
regardless of which address it's bound to.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant