syntaxis/install/install.sh
Jesús Pérez faf0d2c6b9
Some checks failed
Build - Verify Code & Build Binaries / Check Code Format (push) Has been cancelled
Build - Verify Code & Build Binaries / Lint with Clippy (push) Has been cancelled
Build - Verify Code & Build Binaries / Test Suite (push) Has been cancelled
Build - Verify Code & Build Binaries / Cargo Check (push) Has been cancelled
Build - Verify Code & Build Binaries / Security Audit (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - macos-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - ubuntu-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - windows-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - macos-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - ubuntu-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - windows-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / All Checks Passed (push) Has been cancelled
CI/CD with Staging Preset / Validate Installation with Staging Preset (macos-latest) (push) Has been cancelled
CI/CD with Staging Preset / Validate Installation with Staging Preset (ubuntu-latest) (push) Has been cancelled
CI/CD with Staging Preset / Build and Test with Staging Preset (push) Has been cancelled
CI/CD with Staging Preset / Integration Test with Docker Compose (push) Has been cancelled
CI/CD with Staging Preset / Validate Documentation (push) Has been cancelled
CI/CD with Staging Preset / Test Summary (push) Has been cancelled
Provisioning Tests / Provisioning Tests (macos-latest) (push) Has been cancelled
Provisioning Tests / Provisioning Tests (ubuntu-20.04) (push) Has been cancelled
Provisioning Tests / Provisioning Tests (ubuntu-latest) (push) Has been cancelled
Provisioning Tests / Lint Provisioning Scripts (push) Has been cancelled
Provisioning Tests / Test Report (push) Has been cancelled
chore: reorganization following layout_conventions.md
2025-12-26 18:46:38 +00:00

844 lines
23 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
################################################################################
# syntaxis One-Line Installer
#
# Usage:
# curl -sSL https://raw.githubusercontent.com/syntaxis/main/install.sh | bash
# curl -sSL https://raw.githubusercontent.com/syntaxis/main/install.sh | bash -s -- --help
#
# Options:
# --help Show this help message
# --version TAG Install specific version/tag
# --prefix DIR Custom installation directory
# --skip-deps Skip dependency installation
# --no-verify Skip test verification (faster, not recommended)
# --unattended Non-interactive mode
# --keep-build Keep build artifacts
# --config-only Only deploy configurations (skip build)
# --dry-run Show what would be installed
#
# Environment Variables:
# WORKSPACE_INSTALL_DIR Installation directory (default: ~/.local/share/syntaxis)
# WORKSPACE_NO_COLOR Disable colored output
# WORKSPACE_SKIP_TESTS Skip test verification
# CARGO_HOME Cargo installation directory
#
################################################################################
set -euo pipefail
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
INSTALLER_VERSION="1.0.0"
PROJECT_REPO="https://github.com/syntaxis.git"
INSTALL_DIR="${WORKSPACE_INSTALL_DIR:-$HOME/.local/share/syntaxis}"
LOG_FILE="$HOME/.syntaxis/install.log"
MANIFEST_DIR="$HOME/.syntaxis"
CONFIG_DIR="$HOME/.config/syntaxis"
DATA_DIR="$HOME/.local/share/syntaxis"
# Script state
STEP=0
TOTAL_STEPS=8
DRY_RUN=false
SKIP_DEPS=false
NO_VERIFY=false
UNATTENDED=false
KEEP_BUILD=false
CONFIG_ONLY=false
VERSION_TAG="main"
CLEANUP_ON_ERROR=true
# Initialize log file
mkdir -p "$MANIFEST_DIR"
: > "$LOG_FILE"
################################################################################
# Utility Functions
################################################################################
log() {
local msg="$*"
echo -e "[$(date +'%Y-%m-%d %H:%M:%S')] $msg" | tee -a "$LOG_FILE"
}
log_error() {
local msg="$*"
echo -e "${RED}[ERROR]${NC} $msg" | tee -a "$LOG_FILE" >&2
}
log_success() {
local msg="$*"
echo -e "${GREEN}${NC} $msg" | tee -a "$LOG_FILE"
}
log_info() {
local msg="$*"
echo -e "${BLUE}${NC} $msg" | tee -a "$LOG_FILE"
}
log_warn() {
local msg="$*"
echo -e "${YELLOW}⚠️${NC} $msg" | tee -a "$LOG_FILE"
}
step() {
STEP=$((STEP + 1))
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE}[$STEP/$TOTAL_STEPS]${NC} $*"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
check_command() {
local cmd="$1"
if command -v "$cmd" &> /dev/null; then
return 0
else
return 1
fi
}
prompt_yes_no() {
local question="$1"
local default="${2:-y}"
if [[ "$UNATTENDED" == "true" ]]; then
return 0 # Default to yes in unattended mode
fi
local prompt="$question (y/n) [$default]: "
local response
read -p "$prompt" response
response="${response:-$default}"
if [[ "$response" =~ ^[Yy] ]]; then
return 0
else
return 1
fi
}
detect_os() {
case "$(uname -s)" in
Darwin*) echo "macos" ;;
Linux*) echo "linux" ;;
*) echo "unknown" ;;
esac
}
detect_arch() {
case "$(uname -m)" in
x86_64) echo "x86_64" ;;
aarch64) echo "aarch64" ;;
arm64) echo "aarch64" ;; # macOS Apple Silicon
*) echo "unknown" ;;
esac
}
detect_linux_distro() {
if [[ -f /etc/os-release ]]; then
. /etc/os-release
echo "$ID"
else
echo "unknown"
fi
}
show_help() {
cat << 'EOF'
syntaxis One-Line Installer
USAGE:
curl -sSL https://raw.githubusercontent.com/syntaxis/main/install.sh | bash
bash install.sh [OPTIONS]
OPTIONS:
-h, --help Show this help message
-v, --version TAG Install specific version/tag (default: main)
--prefix DIR Custom installation directory
--skip-deps Skip dependency installation (assume already installed)
--no-verify Skip test verification (faster, not recommended)
--unattended Non-interactive mode (use all defaults)
--keep-build Keep build artifacts (default: cleanup)
--config-only Only deploy configurations (skip build)
--dry-run Show what would be installed
ENVIRONMENT VARIABLES:
WORKSPACE_INSTALL_DIR Installation directory
WORKSPACE_NO_COLOR Disable colored output
WORKSPACE_SKIP_TESTS Skip test verification
CARGO_HOME Cargo installation directory
EXAMPLES:
# Standard installation
bash install.sh
# Unattended installation with custom prefix
bash install.sh --unattended --prefix /opt/workspace
# Only deploy configurations (binaries already installed)
bash install.sh --config-only
# See what would be installed without making changes
bash install.sh --dry-run
For more information, visit: https://github.com/syntaxis
EOF
}
rollback_on_error() {
if [[ "$DRY_RUN" == "true" ]] || [[ "$CLEANUP_ON_ERROR" != "true" ]]; then
return
fi
log_warn "Rolling back installation..."
# Remove partially installed binaries
rm -f "$HOME/.cargo/bin/workspace"* 2>/dev/null || true
# Note: Don't remove installation directory as it might be user repo
log_warn "Installation failed. See $LOG_FILE for details."
}
trap rollback_on_error ERR
################################################################################
# Phase 1: Pre-Flight Checks
################################################################################
preflight_checks() {
step "Pre-Flight Checks"
local os=$(detect_os)
local arch=$(detect_arch)
log "Detected OS: $os ($arch)"
if [[ "$os" == "unknown" ]] || [[ "$arch" == "unknown" ]]; then
log_error "Unsupported OS or architecture"
return 1
fi
# Check basic tools
local missing_tools=()
for tool in git curl; do
if ! check_command "$tool"; then
missing_tools+=("$tool")
fi
done
if [[ ${#missing_tools[@]} -gt 0 ]]; then
log_error "Missing required tools: ${missing_tools[*]}"
log "Please install: ${missing_tools[*]}"
if [[ "$os" == "macos" ]]; then
log " brew install ${missing_tools[*]}"
elif [[ "$os" == "linux" ]]; then
local distro=$(detect_linux_distro)
case "$distro" in
ubuntu|debian)
log " sudo apt-get update && sudo apt-get install -y ${missing_tools[*]}"
;;
fedora|rhel)
log " sudo dnf install -y ${missing_tools[*]}"
;;
arch)
log " sudo pacman -S --noconfirm ${missing_tools[*]}"
;;
esac
fi
return 1
fi
log_success "Pre-flight checks passed"
}
################################################################################
# Phase 2: Install Core Dependencies
################################################################################
install_rust() {
if check_command "rustc"; then
local rust_version=$(rustc --version | awk '{print $2}')
log_success "Rust already installed: $rust_version"
return 0
fi
log_info "Installing Rust toolchain..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would install Rust via: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs"
return 0
fi
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.75 2>&1 | tee -a "$LOG_FILE"
# Source cargo environment
if [[ -f "$HOME/.cargo/env" ]]; then
# shellcheck disable=SC1090
source "$HOME/.cargo/env"
fi
if ! check_command "rustc"; then
log_error "Rust installation failed"
return 1
fi
log_success "Rust installed: $(rustc --version)"
}
install_nushell() {
if check_command "nu"; then
local nu_version=$(nu --version 2>&1 | head -1)
log_success "NuShell already installed: $nu_version"
return 0
fi
log_info "Installing NuShell..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would install NuShell via: cargo install nu"
return 0
fi
# Try system package manager first
local os=$(detect_os)
if [[ "$os" == "macos" ]] && check_command "brew"; then
log_info "Installing NuShell via Homebrew..."
brew install nushell 2>&1 | tee -a "$LOG_FILE" || true
fi
# Fallback to cargo
if ! check_command "nu"; then
log_info "Installing NuShell via cargo..."
cargo install nu --locked 2>&1 | tee -a "$LOG_FILE"
fi
if ! check_command "nu"; then
log_error "NuShell installation failed"
return 1
fi
log_success "NuShell installed: $(nu --version 2>&1 | head -1)"
}
install_just() {
if check_command "just"; then
local just_version=$(just --version)
log_success "Just already installed: $just_version"
return 0
fi
log_info "Installing Just task runner..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would install Just via: cargo install just"
return 0
fi
cargo install just 2>&1 | tee -a "$LOG_FILE"
if ! check_command "just"; then
log_error "Just installation failed"
return 1
fi
log_success "Just installed: $(just --version)"
}
install_system_deps() {
local os=$(detect_os)
log_info "Checking system dependencies..."
case "$os" in
macos)
if ! check_command "cc"; then
log_info "Installing Xcode Command Line Tools..."
if [[ "$DRY_RUN" != "true" ]]; then
xcode-select --install 2>&1 | tee -a "$LOG_FILE" || true
# Wait for installation
sudo xcode-select --switch /Library/Developer/CommandLineTools 2>/dev/null || true
fi
fi
log_success "System dependencies ready"
;;
linux)
local distro=$(detect_linux_distro)
local deps=()
# Check for required tools
check_command "gcc" || deps+=("gcc")
check_command "make" || deps+=("make")
check_command "pkg-config" || deps+=("pkg-config")
# Check for sqlite development headers
if ! pkg-config --exists sqlite3 2>/dev/null; then
case "$distro" in
ubuntu|debian) deps+=("libsqlite3-dev") ;;
fedora|rhel) deps+=("sqlite-devel") ;;
arch) deps+=("sqlite") ;;
esac
fi
if [[ ${#deps[@]} -gt 0 ]]; then
log_info "Installing dependencies: ${deps[*]}"
if [[ "$DRY_RUN" != "true" ]]; then
case "$distro" in
ubuntu|debian)
sudo apt-get update && sudo apt-get install -y build-essential pkg-config libsqlite3-dev 2>&1 | tee -a "$LOG_FILE"
;;
fedora|rhel)
sudo dnf install -y gcc gcc-c++ make pkg-config sqlite-devel 2>&1 | tee -a "$LOG_FILE"
;;
arch)
sudo pacman -S --noconfirm base-devel pkg-config sqlite 2>&1 | tee -a "$LOG_FILE"
;;
*)
log_warn "Unknown Linux distribution. Install build essentials manually."
;;
esac
fi
fi
log_success "System dependencies ready"
;;
esac
}
install_dependencies() {
if [[ "$SKIP_DEPS" == "true" ]]; then
log_warn "Skipping dependency installation (--skip-deps)"
return 0
fi
step "Install Core Dependencies"
install_rust
install_nushell
install_just
install_system_deps
log_success "All dependencies installed"
}
################################################################################
# Phase 3: Clone/Verify Repository
################################################################################
clone_or_verify_repo() {
step "Clone/Verify Repository"
# Check if already in a git repository
if git rev-parse --git-dir &> /dev/null; then
log_success "Already in a git repository"
INSTALL_DIR="$(pwd)"
cd "$INSTALL_DIR"
else
log_info "Cloning syntaxis repository..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would clone: $PROJECT_REPO to $INSTALL_DIR"
return 0
fi
if [[ -d "$INSTALL_DIR" ]]; then
if [[ -d "$INSTALL_DIR/.git" ]]; then
log_info "Repository already exists, updating..."
cd "$INSTALL_DIR"
git pull origin "$VERSION_TAG" 2>&1 | tee -a "$LOG_FILE"
else
log_error "Directory exists but is not a git repository: $INSTALL_DIR"
return 1
fi
else
mkdir -p "$(dirname "$INSTALL_DIR")"
git clone -b "$VERSION_TAG" "$PROJECT_REPO" "$INSTALL_DIR" 2>&1 | tee -a "$LOG_FILE"
cd "$INSTALL_DIR"
fi
fi
# Verify repository structure
local required_files=("Cargo.toml" "workspace-manager/Cargo.toml" "Justfile")
for file in "${required_files[@]}"; do
if [[ ! -f "$file" ]]; then
log_error "Missing required file: $file"
return 1
fi
done
log_success "Repository verified: $INSTALL_DIR"
}
################################################################################
# Phase 4: Build Workspace
################################################################################
build_workspace() {
if [[ "$CONFIG_ONLY" == "true" ]]; then
log_warn "Skipping build (--config-only)"
return 0
fi
step "Build Workspace"
log_info "Building workspace binaries (this may take 10-20 minutes)..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would run: cargo build --release --workspace (excluding workspace-api, workspace-vapora)"
return 0
fi
# Build release binaries
RUST_BACKTRACE=1 cargo build --release --workspace \
--exclude workspace-api \
--exclude workspace-vapora \
2>&1 | tee -a "$LOG_FILE"
if [[ $? -ne 0 ]]; then
log_error "Build failed"
return 1
fi
# Run tests
if [[ "$NO_VERIFY" != "true" ]]; then
log_info "Running tests..."
cargo test --release --workspace --lib \
--exclude workspace-api \
--exclude workspace-vapora \
2>&1 | tee -a "$LOG_FILE"
if [[ $? -ne 0 ]]; then
log_warn "Some tests failed, continuing anyway..."
fi
fi
log_success "Build completed"
}
################################################################################
# Phase 5: Install Binaries
################################################################################
install_binaries() {
if [[ "$CONFIG_ONLY" == "true" ]]; then
log_warn "Skipping binary installation (--config-only)"
return 0
fi
step "Install Binaries"
log_info "Installing binaries to ~/.cargo/bin..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would install: workspace, workspace-tui, workspace-dashboard"
return 0
fi
local binaries=("workspace-cli" "workspace-tui" "workspace-dashboard")
for binary in "${binaries[@]}"; do
log_info "Installing $binary..."
if ! cargo install --path "workspace-manager/crates/$binary" 2>&1 | tee -a "$LOG_FILE"; then
log_error "Failed to install $binary"
return 1
fi
done
# Verify installations
for binary in "workspace" "workspace-tui" "workspace-dashboard"; do
if ! check_command "$binary"; then
log_error "Binary not found in PATH: $binary"
return 1
fi
done
log_success "All binaries installed: workspace, workspace-tui, workspace-dashboard"
}
################################################################################
# Phase 6: Deploy Configurations
################################################################################
deploy_configurations() {
step "Deploy Configurations"
log_info "Deploying configuration files..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would deploy configurations to $CONFIG_DIR"
return 0
fi
# Create directories
mkdir -p "$CONFIG_DIR/features"
mkdir -p "$DATA_DIR"
mkdir -p "$MANIFEST_DIR"
# Deploy main config
if [[ -f "workspace-manager/workspace-api-config.template.toml" ]]; then
cp "workspace-manager/workspace-api-config.template.toml" "$CONFIG_DIR/workspace-api.toml"
log_success "Deployed: workspace-api.toml"
else
log_warn "Main config template not found"
fi
# Deploy feature configs
if [[ -d "workspace-manager/configs/features" ]]; then
for template in workspace-manager/configs/features/*.template; do
if [[ -f "$template" ]]; then
local filename=$(basename "$template" .template)
cp "$template" "$CONFIG_DIR/features/$filename"
fi
done
local count=$(find "$CONFIG_DIR/features" -type f | wc -l)
log_success "Deployed: $count feature configurations"
else
log_warn "Feature configs directory not found"
fi
log_success "Configurations deployed to: $CONFIG_DIR"
}
################################################################################
# Phase 7: Setup Environment
################################################################################
setup_environment() {
step "Setup Environment"
log_info "Setting up environment variables and PATH..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would update shell configuration files"
return 0
fi
# Detect shell
local shell_name=$(basename "$SHELL")
local shell_rc=""
case "$shell_name" in
bash)
shell_rc="$HOME/.bashrc"
;;
zsh)
shell_rc="$HOME/.zshrc"
;;
fish)
shell_rc="$HOME/.config/fish/config.fish"
;;
*)
log_warn "Unknown shell: $shell_name"
shell_rc="$HOME/.bashrc"
;;
esac
# Add cargo bin to PATH if not already present
if [[ -n "$shell_rc" ]] && [[ -f "$shell_rc" ]]; then
if ! grep -q '.cargo/bin' "$shell_rc"; then
echo "" >> "$shell_rc"
echo "# syntaxis" >> "$shell_rc"
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> "$shell_rc"
log_success "Updated $shell_rc"
fi
fi
# Export environment variables for current session
export PATH="$HOME/.cargo/bin:$PATH"
export WORKSPACE_CONFIG_DIR="$CONFIG_DIR"
export WORKSPACE_DATA_DIR="$DATA_DIR"
log_success "Environment configured"
}
################################################################################
# Phase 8: Verification & Summary
################################################################################
verify_installation() {
step "Verify Installation"
log_info "Verifying installation..."
if [[ "$DRY_RUN" == "true" ]]; then
log "[DRY RUN] Would verify binaries and configurations"
return 0
fi
local verification_ok=true
# Check binaries
for binary in workspace workspace-tui workspace-dashboard; do
if check_command "$binary"; then
log_success "Found: $binary"
else
log_warn "Not found: $binary"
verification_ok=false
fi
done
# Check configurations
if [[ -f "$CONFIG_DIR/workspace-api.toml" ]]; then
log_success "Found: workspace-api.toml"
else
log_warn "Not found: workspace-api.toml"
verification_ok=false
fi
local feature_count=$(find "$CONFIG_DIR/features" -type f 2>/dev/null | wc -l)
if [[ $feature_count -gt 0 ]]; then
log_success "Found: $feature_count feature configurations"
else
log_warn "No feature configurations found"
fi
if [[ "$verification_ok" == "true" ]]; then
log_success "Installation verified successfully"
return 0
else
log_warn "Some components missing, but installation may still be functional"
return 0 # Don't fail on partial verification
fi
}
show_summary() {
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}✨ Installation Complete!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo "Installation Details:"
echo " Version: 0.1.0"
echo " Installation: $INSTALL_DIR"
echo " Binaries: workspace, workspace-tui, workspace-dashboard"
echo " Config: $CONFIG_DIR"
echo " Data: $DATA_DIR"
echo " Log: $LOG_FILE"
echo ""
echo "Quick Start:"
echo " workspace --help # CLI documentation"
echo " workspace-tui # Launch TUI"
echo " cd $INSTALL_DIR && just run-dashboard # Start web dashboard (port 3000)"
echo ""
echo "Next Steps:"
echo " 1. Customize config: nano $CONFIG_DIR/workspace-api.toml"
echo " 2. Create a project: workspace project create my-project"
echo " 3. Read docs: https://github.com/syntaxis"
echo ""
# Remind to reload shell
if [[ -n "$SHELL" ]]; then
echo -e "${YELLOW}⚠️${NC} Reload your shell for PATH changes to take effect:"
echo " source ~/$( basename "$SHELL" )rc"
fi
echo ""
log_success "Thank you for installing syntaxis!"
}
################################################################################
# Main Installation Flow
################################################################################
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help
exit 0
;;
-v|--version)
VERSION_TAG="$2"
shift 2
;;
--prefix)
INSTALL_DIR="$2"
shift 2
;;
--skip-deps)
SKIP_DEPS=true
shift
;;
--no-verify)
NO_VERIFY=true
shift
;;
--unattended)
UNATTENDED=true
shift
;;
--keep-build)
KEEP_BUILD=true
shift
;;
--config-only)
CONFIG_ONLY=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Show welcome message
echo -e "${BLUE}"
echo "╔════════════════════════════════════════════════════════╗"
echo "║ syntaxis Installer v$INSTALLER_VERSION"
echo "║ One-Command Installation for Project Management ║"
echo "╚════════════════════════════════════════════════════════╝"
echo -e "${NC}"
log "Starting installation..."
log "Installation directory: $INSTALL_DIR"
log "Log file: $LOG_FILE"
# Execute installation phases
preflight_checks || exit 1
install_dependencies || exit 1
clone_or_verify_repo || exit 1
build_workspace || exit 1
install_binaries || exit 1
deploy_configurations || exit 1
setup_environment || exit 1
verify_installation || exit 1
# Show summary
show_summary
# Cleanup build artifacts if requested
if [[ "$KEEP_BUILD" != "true" ]] && [[ "$DRY_RUN" != "true" ]]; then
log_info "Cleaning up build artifacts..."
cd "$INSTALL_DIR"
rm -rf target 2>/dev/null || true
log_success "Cleanup complete"
fi
log_success "Installation successful"
exit 0
}
# Run main function
main "$@"