| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- #!/bin/bash
- # Roo Code CLI Release Script
- #
- # Usage:
- # ./apps/cli/scripts/release.sh [version]
- #
- # Examples:
- # ./apps/cli/scripts/release.sh # Use version from package.json
- # ./apps/cli/scripts/release.sh 0.1.0 # Specify version
- #
- # This script:
- # 1. Builds the extension and CLI
- # 2. Creates a tarball for the current platform
- # 3. Creates a GitHub release and uploads the tarball
- #
- # Prerequisites:
- # - GitHub CLI (gh) installed and authenticated
- # - pnpm installed
- # - Run from the monorepo root directory
- set -e
- # 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/7" "Checking prerequisites..."
-
- if ! command -v gh &> /dev/null; then
- error "GitHub CLI (gh) is not installed. Install it with: brew install gh"
- fi
-
- if ! gh auth status &> /dev/null; then
- error "GitHub CLI is not authenticated. Run: gh auth login"
- fi
-
- 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() {
- if [ -n "$1" ]; then
- VERSION="$1"
- else
- VERSION=$(node -p "require('$CLI_DIR/package.json').version")
- fi
-
- # Validate semver format
- if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
- error "Invalid version format: $VERSION (expected semver like 0.1.0)"
- fi
-
- TAG="cli-v$VERSION"
- info "Version: $VERSION (tag: $TAG)"
- }
- # Build everything
- build() {
- step "2/7" "Building extension bundle..."
- cd "$REPO_ROOT"
- pnpm bundle
-
- step "3/7" "Building CLI..."
- pnpm --filter @roo-code/cli build
-
- info "Build complete"
- }
- # Create release tarball
- create_tarball() {
- step "4/7" "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 (only runtime dependencies)
- info "Creating package.json..."
- node -e "
- const pkg = require('$CLI_DIR/package.json');
- const newPkg = {
- name: '@roo-code/cli',
- version: pkg.version,
- type: 'module',
- dependencies: {
- commander: pkg.dependencies.commander
- }
- };
- 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 to mark it as CommonJS
- # This is necessary because the main package.json has "type": "module"
- # but the extension bundle is CommonJS
- echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
-
- # Find and copy ripgrep binary
- # The extension looks for ripgrep at: appRoot/node_modules/@vscode/ripgrep/bin/rg
- # The CLI sets appRoot to the CLI package root, so we need to put ripgrep there
- 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"
- # Create the expected directory structure for the extension to find ripgrep
- 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"
- # Also keep a copy in bin/ for direct access
- 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_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 version file
- echo "$VERSION" > "$RELEASE_DIR/VERSION"
-
- # 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)"
- }
- # Create checksum
- create_checksum() {
- step "5/7" "Creating checksum..."
- cd "$REPO_ROOT"
-
- if command -v sha256sum &> /dev/null; then
- sha256sum "$TARBALL" > "${TARBALL}.sha256"
- elif command -v shasum &> /dev/null; then
- shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
- else
- warn "No sha256sum or shasum found, skipping checksum"
- return
- fi
-
- info "Checksum: $(cat "${TARBALL}.sha256")"
- }
- # Check if release already exists
- check_existing_release() {
- step "6/7" "Checking for existing release..."
-
- if gh release view "$TAG" &> /dev/null; then
- warn "Release $TAG already exists"
- read -p "Do you want to delete it and create a new one? [y/N] " -n 1 -r
- echo
- if [[ $REPLY =~ ^[Yy]$ ]]; then
- info "Deleting existing release..."
- gh release delete "$TAG" --yes
- # Also delete the tag if it exists
- git tag -d "$TAG" 2>/dev/null || true
- git push origin ":refs/tags/$TAG" 2>/dev/null || true
- else
- error "Aborted. Use a different version or delete the existing release manually."
- fi
- fi
- }
- # Create GitHub release
- create_release() {
- step "7/7" "Creating GitHub release..."
- cd "$REPO_ROOT"
-
- RELEASE_NOTES=$(cat << EOF
- ## Installation
- \`\`\`bash
- curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh
- \`\`\`
- Or install a specific version:
- \`\`\`bash
- ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh
- \`\`\`
- ## Requirements
- - Node.js 20 or higher
- - macOS (Intel or Apple Silicon) or Linux (x64 or ARM64)
- ## Usage
- \`\`\`bash
- # Set your API key
- export OPENROUTER_API_KEY=sk-or-v1-...
- # Run a task
- roo "What is this project?" --workspace ~/my-project
- # See all options
- roo --help
- \`\`\`
- ## Platform Support
- This release includes:
- - \`roo-cli-${PLATFORM}.tar.gz\` - Built on $(uname -s) $(uname -m)
- > **Note:** Additional platforms will be added as needed. If you need a different platform, please open an issue.
- ## Checksum
- \`\`\`
- $(cat "${TARBALL}.sha256" 2>/dev/null || echo "N/A")
- \`\`\`
- EOF
- )
- # Get the current commit SHA for the release target
- COMMIT_SHA=$(git rev-parse HEAD)
- info "Creating release at commit: ${COMMIT_SHA:0:8}"
-
- # Create release (gh will create the tag automatically)
- info "Creating release..."
- RELEASE_FILES="$TARBALL"
- if [ -f "${TARBALL}.sha256" ]; then
- RELEASE_FILES="$RELEASE_FILES ${TARBALL}.sha256"
- fi
-
- gh release create "$TAG" \
- --title "Roo Code CLI v$VERSION" \
- --notes "$RELEASE_NOTES" \
- --prerelease \
- --target "$COMMIT_SHA" \
- $RELEASE_FILES
-
- info "Release created!"
- }
- # Cleanup
- cleanup() {
- info "Cleaning up..."
- cd "$REPO_ROOT"
- rm -f "$TARBALL" "${TARBALL}.sha256"
- }
- # Print summary
- print_summary() {
- echo ""
- printf "${GREEN}${BOLD}✓ Release v$VERSION created successfully!${NC}\n"
- echo ""
- echo " Release URL: https://github.com/RooCodeInc/Roo-Code/releases/tag/$TAG"
- echo ""
- echo " Install with:"
- echo " curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh"
- echo ""
- }
- # Main
- main() {
- echo ""
- printf "${BLUE}${BOLD}"
- echo " ╭─────────────────────────────────╮"
- echo " │ Roo Code CLI Release Script │"
- echo " ╰─────────────────────────────────╯"
- printf "${NC}"
- echo ""
-
- detect_platform
- check_prerequisites
- get_version "$1"
- build
- create_tarball
- create_checksum
- check_existing_release
- create_release
- cleanup
- print_summary
- }
- main "$@"
|