build.sh 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #!/bin/bash
  2. # Roo Code CLI Local Build Script
  3. #
  4. # Usage:
  5. # ./apps/cli/scripts/build.sh [options]
  6. #
  7. # Options:
  8. # --install Install locally after building
  9. # --skip-verify Skip end-to-end verification tests (faster builds)
  10. #
  11. # Examples:
  12. # ./apps/cli/scripts/build.sh # Build for local testing
  13. # ./apps/cli/scripts/build.sh --install # Build and install locally
  14. # ./apps/cli/scripts/build.sh --skip-verify # Fast local build
  15. #
  16. # This script builds the CLI for your current platform. For official releases
  17. # with multi-platform support, use the GitHub Actions workflow instead:
  18. # .github/workflows/cli-release.yml
  19. #
  20. # Prerequisites:
  21. # - pnpm installed
  22. # - Run from the monorepo root directory
  23. set -e
  24. # Parse arguments
  25. LOCAL_INSTALL=false
  26. SKIP_VERIFY=false
  27. while [[ $# -gt 0 ]]; do
  28. case $1 in
  29. --install)
  30. LOCAL_INSTALL=true
  31. shift
  32. ;;
  33. --skip-verify)
  34. SKIP_VERIFY=true
  35. shift
  36. ;;
  37. -*)
  38. echo "Unknown option: $1" >&2
  39. exit 1
  40. ;;
  41. *)
  42. shift
  43. ;;
  44. esac
  45. done
  46. # Colors
  47. RED='\033[0;31m'
  48. GREEN='\033[0;32m'
  49. YELLOW='\033[1;33m'
  50. BLUE='\033[0;34m'
  51. BOLD='\033[1m'
  52. NC='\033[0m'
  53. info() { printf "${GREEN}==>${NC} %s\n" "$1"; }
  54. warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; }
  55. error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; }
  56. step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; }
  57. # Get script directory and repo root
  58. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  59. REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
  60. CLI_DIR="$REPO_ROOT/apps/cli"
  61. # Detect current platform
  62. detect_platform() {
  63. OS=$(uname -s | tr '[:upper:]' '[:lower:]')
  64. ARCH=$(uname -m)
  65. case "$OS" in
  66. darwin) OS="darwin" ;;
  67. linux) OS="linux" ;;
  68. *) error "Unsupported OS: $OS" ;;
  69. esac
  70. case "$ARCH" in
  71. x86_64|amd64) ARCH="x64" ;;
  72. arm64|aarch64) ARCH="arm64" ;;
  73. *) error "Unsupported architecture: $ARCH" ;;
  74. esac
  75. PLATFORM="${OS}-${ARCH}"
  76. }
  77. # Check prerequisites
  78. check_prerequisites() {
  79. step "1/6" "Checking prerequisites..."
  80. if ! command -v pnpm &> /dev/null; then
  81. error "pnpm is not installed."
  82. fi
  83. if ! command -v node &> /dev/null; then
  84. error "Node.js is not installed."
  85. fi
  86. info "Prerequisites OK"
  87. }
  88. # Get version
  89. get_version() {
  90. VERSION=$(node -p "require('$CLI_DIR/package.json').version")
  91. GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
  92. VERSION="${VERSION}-local.${GIT_SHORT_HASH}"
  93. info "Version: $VERSION"
  94. }
  95. # Build everything
  96. build() {
  97. step "2/6" "Building extension bundle..."
  98. cd "$REPO_ROOT"
  99. pnpm bundle
  100. step "3/6" "Building CLI..."
  101. pnpm --filter @roo-code/cli build
  102. info "Build complete"
  103. }
  104. # Create release tarball
  105. create_tarball() {
  106. step "4/6" "Creating release tarball for $PLATFORM..."
  107. RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}"
  108. TARBALL="roo-cli-${PLATFORM}.tar.gz"
  109. # Clean up any previous build
  110. rm -rf "$RELEASE_DIR"
  111. rm -f "$REPO_ROOT/$TARBALL"
  112. # Create directory structure
  113. mkdir -p "$RELEASE_DIR/bin"
  114. mkdir -p "$RELEASE_DIR/lib"
  115. mkdir -p "$RELEASE_DIR/extension"
  116. # Copy CLI dist files
  117. info "Copying CLI files..."
  118. cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/"
  119. # Create package.json for npm install
  120. info "Creating package.json..."
  121. node -e "
  122. const pkg = require('$CLI_DIR/package.json');
  123. const newPkg = {
  124. name: '@roo-code/cli',
  125. version: '$VERSION',
  126. type: 'module',
  127. dependencies: {
  128. '@inkjs/ui': pkg.dependencies['@inkjs/ui'],
  129. '@trpc/client': pkg.dependencies['@trpc/client'],
  130. 'commander': pkg.dependencies.commander,
  131. 'fuzzysort': pkg.dependencies.fuzzysort,
  132. 'ink': pkg.dependencies.ink,
  133. 'p-wait-for': pkg.dependencies['p-wait-for'],
  134. 'react': pkg.dependencies.react,
  135. 'superjson': pkg.dependencies.superjson,
  136. 'zustand': pkg.dependencies.zustand
  137. }
  138. };
  139. console.log(JSON.stringify(newPkg, null, 2));
  140. " > "$RELEASE_DIR/package.json"
  141. # Copy extension bundle
  142. info "Copying extension bundle..."
  143. cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/"
  144. # Add package.json to extension directory for CommonJS
  145. echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
  146. # Find and copy ripgrep binary
  147. info "Looking for ripgrep binary..."
  148. RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
  149. if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
  150. info "Found ripgrep at: $RIPGREP_PATH"
  151. mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
  152. cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
  153. chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
  154. mkdir -p "$RELEASE_DIR/bin"
  155. cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
  156. chmod +x "$RELEASE_DIR/bin/rg"
  157. else
  158. warn "ripgrep binary not found - users will need ripgrep installed"
  159. fi
  160. # Create the wrapper script
  161. info "Creating wrapper script..."
  162. cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF'
  163. #!/usr/bin/env node
  164. import { fileURLToPath } from 'url';
  165. import { dirname, join } from 'path';
  166. const __filename = fileURLToPath(import.meta.url);
  167. const __dirname = dirname(__filename);
  168. // Set environment variables for the CLI
  169. process.env.ROO_CLI_ROOT = join(__dirname, '..');
  170. process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');
  171. process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');
  172. // Import and run the actual CLI
  173. await import(join(__dirname, '..', 'lib', 'index.js'));
  174. WRAPPER_EOF
  175. chmod +x "$RELEASE_DIR/bin/roo"
  176. # Create empty .env file
  177. touch "$RELEASE_DIR/.env"
  178. # Create tarball
  179. info "Creating tarball..."
  180. cd "$REPO_ROOT"
  181. tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")"
  182. # Clean up release directory
  183. rm -rf "$RELEASE_DIR"
  184. # Show size
  185. TARBALL_PATH="$REPO_ROOT/$TARBALL"
  186. TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}')
  187. info "Created: $TARBALL ($TARBALL_SIZE)"
  188. }
  189. # Verify local installation
  190. verify_local_install() {
  191. if [ "$SKIP_VERIFY" = true ]; then
  192. step "5/6" "Skipping verification (--skip-verify)"
  193. return
  194. fi
  195. step "5/6" "Verifying installation..."
  196. VERIFY_DIR="$REPO_ROOT/.verify-release"
  197. VERIFY_INSTALL_DIR="$VERIFY_DIR/cli"
  198. VERIFY_BIN_DIR="$VERIFY_DIR/bin"
  199. rm -rf "$VERIFY_DIR"
  200. mkdir -p "$VERIFY_DIR"
  201. TARBALL_PATH="$REPO_ROOT/$TARBALL"
  202. ROO_LOCAL_TARBALL="$TARBALL_PATH" \
  203. ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \
  204. ROO_BIN_DIR="$VERIFY_BIN_DIR" \
  205. ROO_VERSION="$VERSION" \
  206. "$CLI_DIR/install.sh" || {
  207. rm -rf "$VERIFY_DIR"
  208. error "Installation verification failed!"
  209. }
  210. # Test --help
  211. if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then
  212. rm -rf "$VERIFY_DIR"
  213. error "CLI --help check failed!"
  214. fi
  215. info "CLI --help check passed"
  216. # Test --version
  217. if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then
  218. rm -rf "$VERIFY_DIR"
  219. error "CLI --version check failed!"
  220. fi
  221. info "CLI --version check passed"
  222. cd "$REPO_ROOT"
  223. rm -rf "$VERIFY_DIR"
  224. info "Verification passed!"
  225. }
  226. # Install locally
  227. install_local() {
  228. if [ "$LOCAL_INSTALL" = false ]; then
  229. step "6/6" "Skipping install (use --install to auto-install)"
  230. return
  231. fi
  232. step "6/6" "Installing locally..."
  233. TARBALL_PATH="$REPO_ROOT/$TARBALL"
  234. ROO_LOCAL_TARBALL="$TARBALL_PATH" \
  235. ROO_VERSION="$VERSION" \
  236. "$CLI_DIR/install.sh" || {
  237. error "Local installation failed!"
  238. }
  239. info "Local installation complete!"
  240. }
  241. # Print summary
  242. print_summary() {
  243. echo ""
  244. printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n"
  245. echo ""
  246. echo " Tarball: $REPO_ROOT/$TARBALL"
  247. echo ""
  248. if [ "$LOCAL_INSTALL" = true ]; then
  249. echo " Installed to: ~/.roo/cli"
  250. echo " Binary: ~/.local/bin/roo"
  251. echo ""
  252. echo " Test it out:"
  253. echo " roo --version"
  254. echo " roo --help"
  255. else
  256. echo " To install manually:"
  257. echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh"
  258. echo ""
  259. echo " Or re-run with --install:"
  260. echo " ./apps/cli/scripts/build.sh --install"
  261. fi
  262. echo ""
  263. echo " For official multi-platform releases, use the GitHub Actions workflow:"
  264. echo " .github/workflows/cli-release.yml"
  265. echo ""
  266. }
  267. # Main
  268. main() {
  269. echo ""
  270. printf "${BLUE}${BOLD}"
  271. echo " ╭─────────────────────────────────╮"
  272. echo " │ Roo Code CLI Local Build │"
  273. echo " ╰─────────────────────────────────╯"
  274. printf "${NC}"
  275. echo ""
  276. detect_platform
  277. check_prerequisites
  278. get_version
  279. build
  280. create_tarball
  281. verify_local_install
  282. install_local
  283. print_summary
  284. }
  285. main