| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- #!/bin/bash
- # Roo Code CLI Local Build Script
- #
- # Usage:
- # ./apps/cli/scripts/build.sh [options]
- #
- # Options:
- # --install Install locally after building
- # --skip-verify Skip end-to-end verification tests (faster builds)
- #
- # Examples:
- # ./apps/cli/scripts/build.sh # Build for local testing
- # ./apps/cli/scripts/build.sh --install # Build and install locally
- # ./apps/cli/scripts/build.sh --skip-verify # Fast local build
- #
- # This script builds the CLI for your current platform. For official releases
- # with multi-platform support, use the GitHub Actions workflow instead:
- # .github/workflows/cli-release.yml
- #
- # Prerequisites:
- # - pnpm installed
- # - Run from the monorepo root directory
- set -e
- # Parse arguments
- LOCAL_INSTALL=false
- SKIP_VERIFY=false
- while [[ $# -gt 0 ]]; do
- case $1 in
- --install)
- LOCAL_INSTALL=true
- shift
- ;;
- --skip-verify)
- SKIP_VERIFY=true
- shift
- ;;
- -*)
- echo "Unknown option: $1" >&2
- exit 1
- ;;
- *)
- shift
- ;;
- esac
- done
- # Colors
- RED='\033[0;31m'
- GREEN='\033[0;32m'
- YELLOW='\033[1;33m'
- BLUE='\033[0;34m'
- BOLD='\033[1m'
- NC='\033[0m'
- info() { printf "${GREEN}==>${NC} %s\n" "$1"; }
- warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; }
- error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; }
- step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; }
- # Get script directory and repo root
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
- CLI_DIR="$REPO_ROOT/apps/cli"
- # Detect current platform
- detect_platform() {
- OS=$(uname -s | tr '[:upper:]' '[:lower:]')
- ARCH=$(uname -m)
- case "$OS" in
- darwin) OS="darwin" ;;
- linux) OS="linux" ;;
- *) error "Unsupported OS: $OS" ;;
- esac
- case "$ARCH" in
- x86_64|amd64) ARCH="x64" ;;
- arm64|aarch64) ARCH="arm64" ;;
- *) error "Unsupported architecture: $ARCH" ;;
- esac
- PLATFORM="${OS}-${ARCH}"
- }
- # Check prerequisites
- check_prerequisites() {
- step "1/6" "Checking prerequisites..."
- if ! command -v pnpm &> /dev/null; then
- error "pnpm is not installed."
- fi
- if ! command -v node &> /dev/null; then
- error "Node.js is not installed."
- fi
- info "Prerequisites OK"
- }
- # Get version
- get_version() {
- VERSION=$(node -p "require('$CLI_DIR/package.json').version")
- GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
- VERSION="${VERSION}-local.${GIT_SHORT_HASH}"
- info "Version: $VERSION"
- }
- # Build everything
- build() {
- step "2/6" "Building extension bundle..."
- cd "$REPO_ROOT"
- pnpm bundle
- step "3/6" "Building CLI..."
- pnpm --filter @roo-code/cli build
- info "Build complete"
- }
- # Create release tarball
- create_tarball() {
- step "4/6" "Creating release tarball for $PLATFORM..."
- RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}"
- TARBALL="roo-cli-${PLATFORM}.tar.gz"
- # Clean up any previous build
- rm -rf "$RELEASE_DIR"
- rm -f "$REPO_ROOT/$TARBALL"
- # Create directory structure
- mkdir -p "$RELEASE_DIR/bin"
- mkdir -p "$RELEASE_DIR/lib"
- mkdir -p "$RELEASE_DIR/extension"
- # Copy CLI dist files
- info "Copying CLI files..."
- cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/"
- # Create package.json for npm install
- info "Creating package.json..."
- node -e "
- const pkg = require('$CLI_DIR/package.json');
- const newPkg = {
- name: '@roo-code/cli',
- version: '$VERSION',
- type: 'module',
- dependencies: {
- '@inkjs/ui': pkg.dependencies['@inkjs/ui'],
- '@trpc/client': pkg.dependencies['@trpc/client'],
- 'commander': pkg.dependencies.commander,
- 'fuzzysort': pkg.dependencies.fuzzysort,
- 'ink': pkg.dependencies.ink,
- 'p-wait-for': pkg.dependencies['p-wait-for'],
- 'react': pkg.dependencies.react,
- 'superjson': pkg.dependencies.superjson,
- 'zustand': pkg.dependencies.zustand
- }
- };
- console.log(JSON.stringify(newPkg, null, 2));
- " > "$RELEASE_DIR/package.json"
- # Copy extension bundle
- info "Copying extension bundle..."
- cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/"
- # Add package.json to extension directory for CommonJS
- echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
- # Find and copy ripgrep binary
- info "Looking for ripgrep binary..."
- RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
- if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
- info "Found ripgrep at: $RIPGREP_PATH"
- mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
- cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
- chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
- mkdir -p "$RELEASE_DIR/bin"
- cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
- chmod +x "$RELEASE_DIR/bin/rg"
- else
- warn "ripgrep binary not found - users will need ripgrep installed"
- fi
- # Create the wrapper script
- info "Creating wrapper script..."
- cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF'
- #!/usr/bin/env node
- import { fileURLToPath } from 'url';
- import { dirname, join } from 'path';
- const __filename = fileURLToPath(import.meta.url);
- const __dirname = dirname(__filename);
- // Set environment variables for the CLI
- process.env.ROO_CLI_ROOT = join(__dirname, '..');
- process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');
- process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');
- // Import and run the actual CLI
- await import(join(__dirname, '..', 'lib', 'index.js'));
- WRAPPER_EOF
- chmod +x "$RELEASE_DIR/bin/roo"
- # Create empty .env file
- touch "$RELEASE_DIR/.env"
- # Create tarball
- info "Creating tarball..."
- cd "$REPO_ROOT"
- tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")"
- # Clean up release directory
- rm -rf "$RELEASE_DIR"
- # Show size
- TARBALL_PATH="$REPO_ROOT/$TARBALL"
- TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}')
- info "Created: $TARBALL ($TARBALL_SIZE)"
- }
- # Verify local installation
- verify_local_install() {
- if [ "$SKIP_VERIFY" = true ]; then
- step "5/6" "Skipping verification (--skip-verify)"
- return
- fi
- step "5/6" "Verifying installation..."
- VERIFY_DIR="$REPO_ROOT/.verify-release"
- VERIFY_INSTALL_DIR="$VERIFY_DIR/cli"
- VERIFY_BIN_DIR="$VERIFY_DIR/bin"
- rm -rf "$VERIFY_DIR"
- mkdir -p "$VERIFY_DIR"
- TARBALL_PATH="$REPO_ROOT/$TARBALL"
- ROO_LOCAL_TARBALL="$TARBALL_PATH" \
- ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \
- ROO_BIN_DIR="$VERIFY_BIN_DIR" \
- ROO_VERSION="$VERSION" \
- "$CLI_DIR/install.sh" || {
- rm -rf "$VERIFY_DIR"
- error "Installation verification failed!"
- }
- # Test --help
- if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then
- rm -rf "$VERIFY_DIR"
- error "CLI --help check failed!"
- fi
- info "CLI --help check passed"
- # Test --version
- if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then
- rm -rf "$VERIFY_DIR"
- error "CLI --version check failed!"
- fi
- info "CLI --version check passed"
- cd "$REPO_ROOT"
- rm -rf "$VERIFY_DIR"
- info "Verification passed!"
- }
- # Install locally
- install_local() {
- if [ "$LOCAL_INSTALL" = false ]; then
- step "6/6" "Skipping install (use --install to auto-install)"
- return
- fi
- step "6/6" "Installing locally..."
- TARBALL_PATH="$REPO_ROOT/$TARBALL"
- ROO_LOCAL_TARBALL="$TARBALL_PATH" \
- ROO_VERSION="$VERSION" \
- "$CLI_DIR/install.sh" || {
- error "Local installation failed!"
- }
- info "Local installation complete!"
- }
- # Print summary
- print_summary() {
- echo ""
- printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n"
- echo ""
- echo " Tarball: $REPO_ROOT/$TARBALL"
- echo ""
- if [ "$LOCAL_INSTALL" = true ]; then
- echo " Installed to: ~/.roo/cli"
- echo " Binary: ~/.local/bin/roo"
- echo ""
- echo " Test it out:"
- echo " roo --version"
- echo " roo --help"
- else
- echo " To install manually:"
- echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh"
- echo ""
- echo " Or re-run with --install:"
- echo " ./apps/cli/scripts/build.sh --install"
- fi
- echo ""
- echo " For official multi-platform releases, use the GitHub Actions workflow:"
- echo " .github/workflows/cli-release.yml"
- echo ""
- }
- # Main
- main() {
- echo ""
- printf "${BLUE}${BOLD}"
- echo " ╭─────────────────────────────────╮"
- echo " │ Roo Code CLI Local Build │"
- echo " ╰─────────────────────────────────╯"
- printf "${NC}"
- echo ""
- detect_platform
- check_prerequisites
- get_version
- build
- create_tarball
- verify_local_install
- install_local
- print_summary
- }
- main
|