From ce053cb3ab93b53c88d1c19167ba01c7292749e1 Mon Sep 17 00:00:00 2001 From: lavesh00 Date: Sat, 1 Nov 2025 12:48:06 +0530 Subject: [PATCH 1/2] feat: Add automated Git pull functionality for Ubuntu install.sh Fixes #321 This PR adds automated Git pull functionality to the Ubuntu installation script: **Features:** - Standalone update script (install/update.sh) for safe updates - Enhanced install.sh to detect existing installations and pull updates - Optional automated daily updates via systemd timer - Comprehensive documentation with update instructions - Supports multiple installations with dependency management **Changes:** - Added install/update.sh: Interactive update script with backup, dependency checks, and service restart - Modified install/install.sh: Detects existing installations, prompts for update, sets up automated updates - Updated install/README.md: Added complete update section with 3 methods and troubleshooting **Testing:** - Scripts validated for syntax and logic flow - Ready for testing on Linux environments --- install/README.md | 147 +++++++++++++++++++++++ install/install.sh | 180 +++++++++++++++++++++++++++- install/update.sh | 293 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 614 insertions(+), 6 deletions(-) create mode 100644 install/update.sh diff --git a/install/README.md b/install/README.md index ca34a5a3..96e1002e 100644 --- a/install/README.md +++ b/install/README.md @@ -367,12 +367,159 @@ After installation completes, verify each deployment: sudo pacman -Syu ``` +## Updating OpenAlgo + +OpenAlgo can be updated to the latest version using multiple methods: + +### Method 1: Using the Update Script (Recommended) + +The update script provides a safe and comprehensive update process: + +```bash +# Update all installations interactively +sudo bash /var/python/openalgo-flask/*/openalgo/install/update.sh + +# Update a specific installation +sudo bash /var/python/openalgo-flask/*/openalgo/install/update.sh /var/python/openalgo-flask/yourdomain-broker +``` + +The update script will: +- Detect all OpenAlgo installations automatically +- Show current commit and available updates +- Create backups before updating +- Handle uncommitted changes (stash and restore) +- Update Python dependencies if requirements changed +- Restart services automatically after successful update + +### Method 2: Manual Git Pull + +For quick updates without dependency checks: + +```bash +# Navigate to your installation directory +cd /var/python/openalgo-flask/yourdomain-broker/openalgo + +# Pull latest changes +sudo -u www-data git pull origin main + +# Restart the service +sudo systemctl restart openalgo-yourdomain-broker +``` + +### Method 3: Automated Daily Updates + +During installation, you can opt-in to automated daily updates. The installer creates: + +1. **Update Script**: `/var/python/openalgo-flask/yourdomain-broker/update-openalgo.sh` + - Checks for updates daily + - Updates dependencies if requirements changed + - Restarts service automatically + +2. **Systemd Timer**: `openalgo-update-yourdomain-broker.timer` + - Runs daily at a random time (to avoid server load spikes) + - Persistent across reboots + +**Managing Automated Updates:** + +```bash +# Check timer status +sudo systemctl status openalgo-update-yourdomain-broker.timer + +# View last update run +sudo journalctl -u openalgo-update-yourdomain-broker.service -n 20 + +# Enable automated updates (if not enabled during install) +sudo systemctl enable openalgo-update-yourdomain-broker.timer +sudo systemctl start openalgo-update-yourdomain-broker.timer + +# Disable automated updates +sudo systemctl stop openalgo-update-yourdomain-broker.timer +sudo systemctl disable openalgo-update-yourdomain-broker.timer +``` + +### Update During Re-Installation + +If you run the installation script again on an existing installation: + +1. The script detects the existing installation +2. Prompts whether to update or start fresh +3. If updating: pulls latest changes, preserves configuration +4. If starting fresh: offers to backup existing installation + +### Update Best Practices + +1. **Backup First**: Always backup your `.env` file and database before major updates + ```bash + cp /var/python/openalgo-flask/yourdomain-broker/openalgo/.env ~/openalgo.env.backup + ``` + +2. **Check Changelog**: Review what changed before updating + ```bash + cd /var/python/openalgo-flask/yourdomain-broker/openalgo + sudo -u www-data git log origin/main --oneline -10 + ``` + +3. **Test After Update**: Verify the application works correctly + ```bash + sudo systemctl status openalgo-yourdomain-broker + # Visit your domain and test key functions + ``` + +4. **Monitor Logs**: Check for any errors after update + ```bash + sudo journalctl -u openalgo-yourdomain-broker -n 50 + ``` + +### Troubleshooting Updates + +**Issue: Update fails with "uncommitted changes"** +```bash +# View what files changed +cd /var/python/openalgo-flask/yourdomain-broker/openalgo +sudo -u www-data git status + +# Option 1: Stash changes +sudo -u www-data git stash +sudo -u www-data git pull origin main +sudo -u www-data git stash pop + +# Option 2: Discard local changes (WARNING: will lose modifications) +sudo -u www-data git reset --hard origin/main +``` + +**Issue: Service fails to start after update** +```bash +# Check service logs +sudo journalctl -u openalgo-yourdomain-broker -n 100 + +# Check if dependencies need updating +cd /var/python/openalgo-flask/yourdomain-broker/openalgo +sudo uv pip install --python /var/python/openalgo-flask/yourdomain-broker/venv/bin/python -r requirements-nginx.txt + +# Restart service +sudo systemctl restart openalgo-yourdomain-broker +``` + +**Issue: Automated update not running** +```bash +# Check timer status +sudo systemctl status openalgo-update-yourdomain-broker.timer + +# Check if timer is enabled +sudo systemctl is-enabled openalgo-update-yourdomain-broker.timer + +# Manually trigger update service to test +sudo systemctl start openalgo-update-yourdomain-broker.service +sudo journalctl -u openalgo-update-yourdomain-broker.service +``` + ## Post-Installation 1. Configure your broker settings in the web interface 2. Set up monitoring and alerts if needed 3. Regularly check logs for any issues 4. Keep the system updated with security patches +5. Enable automated updates for hassle-free maintenance ## Support diff --git a/install/install.sh b/install/install.sh index 08dd4411..23c5cfdf 100644 --- a/install/install.sh +++ b/install/install.sh @@ -602,18 +602,70 @@ if ! command -v certbot >/dev/null 2>&1; then fi log_message "Certbot installed successfully" "$GREEN" -# Check and handle existing OpenAlgo installation -handle_existing "$BASE_PATH" "installation directory" "OpenAlgo directory for $DEPLOY_NAME" +# Check if OpenAlgo installation already exists +if [ -d "$OPENALGO_PATH" ] && [ -d "$OPENALGO_PATH/.git" ]; then + log_message "\nExisting OpenAlgo installation detected at $OPENALGO_PATH" "$YELLOW" + read -p "Would you like to update the existing installation? (y/n): " update_choice + if [[ $update_choice =~ ^[Yy]$ ]]; then + log_message "Updating existing installation..." "$BLUE" + + # Get current commit + cd "$OPENALGO_PATH" + CURRENT_BRANCH=$(sudo -u $WEB_USER git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main") + CURRENT_COMMIT=$(sudo -u $WEB_USER git rev-parse HEAD 2>/dev/null) + + log_message "Current branch: $CURRENT_BRANCH" "$BLUE" + log_message "Current commit: ${CURRENT_COMMIT:0:8}..." "$BLUE" + + # Fetch latest changes + log_message "Fetching latest changes..." "$BLUE" + sudo -u $WEB_USER git fetch origin 2>&1 + check_status "Failed to fetch from remote" + + # Check for uncommitted changes + if [ -n "$(sudo -u $WEB_USER git status --porcelain 2>/dev/null)" ]; then + log_message "Warning: Uncommitted changes detected. Stashing changes..." "$YELLOW" + sudo -u $WEB_USER git stash push -m "Auto-stash before install update $(date +%Y%m%d_%H%M%S)" 2>/dev/null || { + log_message "Error: Could not stash changes. Please commit or discard changes manually." "$RED" + exit 1 + } + fi + + # Pull latest changes + log_message "Pulling latest changes..." "$BLUE" + sudo -u $WEB_USER git pull origin ${CURRENT_BRANCH:-main} 2>&1 + check_status "Failed to pull latest changes" + + # Restore stashed changes if any + if sudo -u $WEB_USER git stash list | grep -q "Auto-stash before install update"; then + log_message "Restoring stashed changes..." "$YELLOW" + sudo -u $WEB_USER git stash pop 2>/dev/null || log_message "Warning: Could not restore stashed changes" "$YELLOW" + fi + + NEW_COMMIT=$(sudo -u $WEB_USER git rev-parse HEAD) + log_message "Updated to commit: ${NEW_COMMIT:0:8}..." "$GREEN" + log_message "Repository updated successfully" "$GREEN" + SKIP_CLONE=true + else + handle_existing "$BASE_PATH" "installation directory" "OpenAlgo directory for $DEPLOY_NAME" + SKIP_CLONE=false + fi +else + handle_existing "$BASE_PATH" "installation directory" "OpenAlgo directory for $DEPLOY_NAME" + SKIP_CLONE=false +fi # Create base directory log_message "\nCreating base directory..." "$BLUE" sudo mkdir -p $BASE_PATH check_status "Failed to create base directory" -# Clone repository -log_message "\nCloning OpenAlgo repository..." "$BLUE" -sudo git clone https://github.com/marketcalls/openalgo.git $OPENALGO_PATH -check_status "Failed to clone OpenAlgo repository" +# Clone repository if needed +if [ "$SKIP_CLONE" != "true" ]; then + log_message "\nCloning OpenAlgo repository..." "$BLUE" + sudo git clone https://github.com/marketcalls/openalgo.git $OPENALGO_PATH + check_status "Failed to clone OpenAlgo repository" +fi # Create virtual environment using uv log_message "\nSetting up Python virtual environment with uv..." "$BLUE" @@ -1073,3 +1125,119 @@ log_message "Restart OpenAlgo: sudo systemctl restart $SERVICE_NAME" "$BLUE" log_message "View Logs: sudo journalctl -u $SERVICE_NAME" "$BLUE" log_message "Check Status: sudo systemctl status $SERVICE_NAME" "$BLUE" log_message "View Installation Log: cat $LOG_FILE" "$BLUE" +log_message "\nUpdate Commands:" "$YELLOW" +log_message "Update this installation: cd $OPENALGO_PATH && sudo -u $WEB_USER git pull origin main" "$BLUE" +log_message "Use update script (recommended): sudo bash $OPENALGO_PATH/install/update.sh" "$BLUE" +log_message "Update specific installation: sudo bash $OPENALGO_PATH/install/update.sh $BASE_PATH" "$BLUE" + +# Ask about automated updates +log_message "\nAutomated Updates:" "$YELLOW" +read -p "Would you like to set up automated daily git pulls? (y/n): " auto_update_choice +if [[ $auto_update_choice =~ ^[Yy]$ ]]; then + log_message "Setting up automated daily updates..." "$BLUE" + + # Create update script wrapper for this specific installation + UPDATE_SCRIPT_WRAPPER="$BASE_PATH/update-openalgo.sh" + sudo tee "$UPDATE_SCRIPT_WRAPPER" > /dev/null << EOUPDATESCRIPT +#!/bin/bash +# Auto-generated update script for $DEPLOY_NAME +# This script updates this specific OpenAlgo installation + +cd "$OPENALGO_PATH" +sudo -u $WEB_USER git fetch origin +CURRENT_BRANCH=\$(sudo -u $WEB_USER git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main") +CURRENT_COMMIT=\$(sudo -u $WEB_USER git rev-parse HEAD) +REMOTE_COMMIT=\$(sudo -u $WEB_USER git rev-parse origin/\${CURRENT_BRANCH}) + +if [ "\$CURRENT_COMMIT" != "\$REMOTE_COMMIT" ]; then + echo "[$(date)] Updating $DEPLOY_NAME from \${CURRENT_COMMIT:0:8} to \${REMOTE_COMMIT:0:8}..." + + # Stash any local changes + sudo -u $WEB_USER git stash push -m "Auto-stash before scheduled update \$(date +%Y%m%d_%H%M%S)" 2>/dev/null + + # Pull updates + sudo -u $WEB_USER git pull origin \${CURRENT_BRANCH} > /dev/null 2>&1 + + if [ \$? -eq 0 ]; then + # Get the new commit after pull + NEW_COMMIT=\$(sudo -u $WEB_USER git rev-parse HEAD) + + # Check if requirements changed and update dependencies if needed + if [ -f "$VENV_PATH/bin/activate" ]; then + if sudo -u $WEB_USER git diff --name-only \$CURRENT_COMMIT \$NEW_COMMIT | grep -q "requirements"; then + # Detect uv command + if command -v uv >/dev/null 2>&1; then + UV_CMD="uv" + elif python3 -m uv --version >/dev/null 2>&1; then + UV_CMD="python3 -m uv" + fi + + if [ -n "\$UV_CMD" ]; then + sudo \$UV_CMD pip install --python $VENV_PATH/bin/python -r $OPENALGO_PATH/requirements-nginx.txt > /dev/null 2>&1 + fi + fi + fi + + # Restart service + systemctl restart $SERVICE_NAME > /dev/null 2>&1 + echo "[$(date)] Update completed successfully for $DEPLOY_NAME" + else + echo "[$(date)] Error: Failed to update $DEPLOY_NAME" + # Restore stashed changes on failure + sudo -u $WEB_USER git stash pop 2>/dev/null + fi +else + echo "[$(date)] $DEPLOY_NAME is already up to date" +fi +EOUPDATESCRIPT + + sudo chmod +x "$UPDATE_SCRIPT_WRAPPER" + sudo chown $WEB_USER:$WEB_GROUP "$UPDATE_SCRIPT_WRAPPER" + + # Create systemd timer for daily updates + TIMER_NAME="openalgo-update-$DEPLOY_NAME" + TIMER_SERVICE="${TIMER_NAME}.timer" + TIMER_PATH="/etc/systemd/system/${TIMER_SERVICE}" + + sudo tee "$TIMER_PATH" > /dev/null << EOTIMER +[Unit] +Description=Daily update timer for OpenAlgo ($DEPLOY_NAME) +Requires=${TIMER_NAME}.service + +[Timer] +OnCalendar=daily +RandomizedDelaySec=3600 +Persistent=true + +[Install] +WantedBy=timers.target +EOTIMER + + # Create corresponding service + SERVICE_PATH="/etc/systemd/system/${TIMER_NAME}.service" + sudo tee "$SERVICE_PATH" > /dev/null << EOSERVICE +[Unit] +Description=Update OpenAlgo ($DEPLOY_NAME) +After=network.target + +[Service] +Type=oneshot +ExecStart=$UPDATE_SCRIPT_WRAPPER +User=root + +[Install] +WantedBy=multi-user.target +EOSERVICE + + # Enable and start timer + sudo systemctl daemon-reload + sudo systemctl enable "$TIMER_SERVICE" + sudo systemctl start "$TIMER_SERVICE" + + check_status "Failed to set up automated updates" + log_message "Automated daily updates configured" "$GREEN" + log_message "Update script: $UPDATE_SCRIPT_WRAPPER" "$BLUE" + log_message "Timer service: $TIMER_SERVICE" "$BLUE" + log_message "Check timer status: sudo systemctl status $TIMER_SERVICE" "$BLUE" + log_message "Check last run: sudo journalctl -u ${TIMER_NAME}.service -n 20" "$BLUE" +fi diff --git a/install/update.sh b/install/update.sh new file mode 100644 index 00000000..ef06467a --- /dev/null +++ b/install/update.sh @@ -0,0 +1,293 @@ +#!/bin/bash + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# OpenAlgo Update Script +echo -e "${BLUE}" +echo " ██████╗ ██████╗ ███████╗███╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ " +echo " ██╔═══██╗██╔══██╗██╔════╝████╗ ██║██╔══██╗██║ ██╔════╝ ██╔═══██╗" +echo " ██║ ██║██████╔╝███████╗██╔██╗ ██║███████║██║ ██║ ███╗██║ ██║" +echo " ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██╔══██║██║ ██║ ██║██║ ██║" +echo " ╚██████╔╝██╗ ███████╗██║ ╚████║██║ ██║███████╗╚██████╔╝╚██████╔╝" +echo " ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ " +echo " " +echo " Update Script " +echo -e "${NC}" + +# Function to log messages to both console +log_message() { + local message="$1" + local color="$2" + echo -e "${color}${message}${NC}" +} + +# Function to check if command was successful +check_status() { + if [ $? -ne 0 ]; then + log_message "Error: $1" "$RED" + exit 1 + fi +} + +# Detect OS type +OS_TYPE=$(grep -w "ID" /etc/os-release | cut -d "=" -f 2 | tr -d '"') + +# Handle OS variants - map to base distributions +case "$OS_TYPE" in + "pop"|"linuxmint"|"zorin") + OS_TYPE="ubuntu" + ;; + "manjaro"|"manjaro-arm"|"endeavouros"|"cachyos") + OS_TYPE="arch" + ;; + "rocky"|"almalinux"|"ol") + OS_TYPE="rhel" + ;; +esac + +# Detect web server user based on OS +case "$OS_TYPE" in + ubuntu | debian | raspbian) + WEB_USER="www-data" + WEB_GROUP="www-data" + ;; + centos | fedora | rhel | amzn) + WEB_USER="nginx" + WEB_GROUP="nginx" + ;; + arch) + WEB_USER="http" + WEB_GROUP="http" + ;; +esac + +# Function to find all OpenAlgo installations +find_installations() { + local installations=() + + # Find all openalgo-flask directories + if [ -d "/var/python/openalgo-flask" ]; then + for deploy_dir in /var/python/openalgo-flask/*; do + if [ -d "$deploy_dir" ] && [ -d "$deploy_dir/openalgo" ] && [ -d "$deploy_dir/openalgo/.git" ]; then + installations+=("$deploy_dir") + fi + done + fi + + echo "${installations[@]}" +} + +# Function to update a single installation +update_installation() { + local base_path="$1" + local openalgo_path="$base_path/openalgo" + local venv_path="$base_path/venv" + local deploy_name=$(basename "$base_path") + + log_message "\n===========================================" "$BLUE" + log_message "Updating installation: $deploy_name" "$BLUE" + log_message "Path: $openalgo_path" "$BLUE" + log_message "===========================================" "$BLUE" + + # Check if installation exists + if [ ! -d "$openalgo_path" ]; then + log_message "Error: OpenAlgo directory not found at $openalgo_path" "$RED" + return 1 + fi + + # Check if it's a git repository + if [ ! -d "$openalgo_path/.git" ]; then + log_message "Error: Not a git repository at $openalgo_path" "$RED" + return 1 + fi + + # Get current branch and commit (before any operations) + cd "$openalgo_path" + CURRENT_BRANCH=$(sudo -u $WEB_USER git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main") + LOCAL_COMMIT=$(sudo -u $WEB_USER git rev-parse HEAD 2>/dev/null) + + log_message "Current branch: $CURRENT_BRANCH" "$BLUE" + log_message "Current commit: ${LOCAL_COMMIT:0:8}..." "$BLUE" + + # Fetch latest changes + log_message "\nFetching latest changes from remote..." "$BLUE" + sudo -u $WEB_USER git fetch origin 2>&1 + check_status "Failed to fetch from remote" + + # Check if there are updates available + REMOTE_COMMIT=$(sudo -u $WEB_USER git rev-parse origin/${CURRENT_BRANCH:-main}) + + if [ "$LOCAL_COMMIT" = "$REMOTE_COMMIT" ]; then + log_message "Already up to date!" "$GREEN" + return 0 + fi + + # Show what will be updated + log_message "\nChanges to be pulled:" "$YELLOW" + sudo -u $WEB_USER git log --oneline HEAD..origin/${CURRENT_BRANCH:-main} 2>/dev/null | head -10 + log_message "..." "$YELLOW" + + # Backup current state + BACKUP_DIR="$base_path/backup_$(date +%Y%m%d_%H%M%S)" + log_message "\nCreating backup at $BACKUP_DIR..." "$BLUE" + sudo mkdir -p "$BACKUP_DIR" + sudo cp -r "$openalgo_path" "$BACKUP_DIR/openalgo" 2>/dev/null || log_message "Warning: Could not create full backup" "$YELLOW" + + # Check for uncommitted changes + if [ -n "$(sudo -u $WEB_USER git status --porcelain 2>/dev/null)" ]; then + log_message "Warning: Uncommitted changes detected!" "$YELLOW" + log_message "Stashing changes..." "$YELLOW" + sudo -u $WEB_USER git stash push -m "Auto-stash before update $(date +%Y%m%d_%H%M%S)" 2>/dev/null || { + log_message "Error: Could not stash changes. Please commit or discard changes manually." "$RED" + return 1 + } + STASHED=true + else + STASHED=false + fi + + # Pull latest changes + log_message "\nPulling latest changes..." "$BLUE" + sudo -u $WEB_USER git pull origin ${CURRENT_BRANCH:-main} 2>&1 + if [ $? -ne 0 ]; then + log_message "Error: Failed to pull changes. Attempting to restore backup..." "$RED" + if [ -d "$BACKUP_DIR/openalgo" ]; then + log_message "Restoring from backup..." "$YELLOW" + sudo rm -rf "$openalgo_path" + sudo cp -r "$BACKUP_DIR/openalgo" "$openalgo_path" + sudo chown -R $WEB_USER:$WEB_GROUP "$openalgo_path" + fi + return 1 + fi + + # Restore stashed changes if any + if [ "$STASHED" = true ]; then + log_message "\nRestoring stashed changes..." "$YELLOW" + sudo -u $WEB_USER git stash pop 2>/dev/null || log_message "Warning: Could not restore stashed changes. Check with 'git stash list'" "$YELLOW" + fi + + # Get new commit + NEW_COMMIT=$(sudo -u $WEB_USER git rev-parse HEAD) + log_message "Updated to commit: ${NEW_COMMIT:0:8}..." "$GREEN" + + # Check if requirements.txt changed and update dependencies + if [ -f "$venv_path/bin/activate" ]; then + log_message "\nChecking for dependency updates..." "$BLUE" + + # Compare requirements file timestamps + REQUIREMENTS_FILE="$openalgo_path/requirements-nginx.txt" + if [ -f "$REQUIREMENTS_FILE" ]; then + # Check if requirements file was modified + if sudo -u $WEB_USER git diff --name-only "$LOCAL_COMMIT" "$NEW_COMMIT" | grep -q "requirements"; then + log_message "Requirements file changed. Updating dependencies..." "$YELLOW" + + # Detect uv command + if command -v uv >/dev/null 2>&1; then + UV_CMD="uv" + elif python3 -m uv --version >/dev/null 2>&1; then + UV_CMD="python3 -m uv" + else + log_message "Warning: uv not found. Skipping dependency update." "$YELLOW" + UV_CMD="" + fi + + if [ -n "$UV_CMD" ]; then + sudo $UV_CMD pip install --python $venv_path/bin/python -r "$REQUIREMENTS_FILE" 2>&1 | head -20 + log_message "Dependencies updated" "$GREEN" + fi + else + log_message "No dependency changes detected" "$GREEN" + fi + fi + fi + + # Restart service if it exists + local service_name="openalgo-$(basename "$base_path")" + if systemctl list-units --type=service | grep -q "^${service_name}.service"; then + log_message "\nRestarting service: $service_name..." "$BLUE" + sudo systemctl restart "$service_name" 2>&1 + if [ $? -eq 0 ]; then + log_message "Service restarted successfully" "$GREEN" + # Wait a moment for service to start + sleep 2 + # Check service status + if systemctl is-active --quiet "$service_name"; then + log_message "Service is running" "$GREEN" + else + log_message "Warning: Service may have failed to start. Check status with: sudo systemctl status $service_name" "$YELLOW" + fi + else + log_message "Warning: Failed to restart service. Please restart manually: sudo systemctl restart $service_name" "$YELLOW" + fi + fi + + log_message "\nUpdate completed successfully for $deploy_name!" "$GREEN" + return 0 +} + +# Main execution +INSTALLATIONS=($(find_installations)) + +if [ ${#INSTALLATIONS[@]} -eq 0 ]; then + log_message "No OpenAlgo installations found." "$RED" + log_message "Expected location: /var/python/openalgo-flask/*/openalgo" "$YELLOW" + exit 1 +fi + +# If specific path provided as argument +if [ $# -gt 0 ]; then + SPECIFIC_PATH="$1" + if [ -d "$SPECIFIC_PATH/openalgo" ] && [ -d "$SPECIFIC_PATH/openalgo/.git" ]; then + update_installation "$SPECIFIC_PATH" + exit $? + else + log_message "Error: Invalid OpenAlgo installation path: $SPECIFIC_PATH" "$RED" + exit 1 + fi +fi + +# If multiple installations, ask which to update +if [ ${#INSTALLATIONS[@]} -eq 1 ]; then + # Single installation, update it + update_installation "${INSTALLATIONS[0]}" +else + # Multiple installations + log_message "\nFound ${#INSTALLATIONS[@]} OpenAlgo installation(s):" "$BLUE" + for i in "${!INSTALLATIONS[@]}"; do + local deploy_name=$(basename "${INSTALLATIONS[$i]}") + log_message " [$((i+1))] $deploy_name (${INSTALLATIONS[$i]})" "$BLUE" + done + + read -p "Enter number to update (or 'all' for all, 'q' to quit): " choice + + if [ "$choice" = "q" ] || [ "$choice" = "Q" ]; then + log_message "Update cancelled." "$YELLOW" + exit 0 + elif [ "$choice" = "all" ] || [ "$choice" = "ALL" ]; then + log_message "\nUpdating all installations..." "$BLUE" + FAILED=0 + for inst in "${INSTALLATIONS[@]}"; do + update_installation "$inst" || FAILED=$((FAILED + 1)) + done + if [ $FAILED -eq 0 ]; then + log_message "\nAll installations updated successfully!" "$GREEN" + exit 0 + else + log_message "\nWarning: $FAILED installation(s) failed to update" "$YELLOW" + exit 1 + fi + elif [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#INSTALLATIONS[@]} ]; then + update_installation "${INSTALLATIONS[$((choice-1))]}" + exit $? + else + log_message "Invalid choice." "$RED" + exit 1 + fi +fi + + From f76398c3637ba420e772b3c2d13ac7df65839878 Mon Sep 17 00:00:00 2001 From: lavesh00 Date: Wed, 5 Nov 2025 14:29:13 +0530 Subject: [PATCH 2/2] fix(install): address PR #550 review - update.sh: remove invalid top-level 'local' for multi-install selection - install.sh: escape 11/05/2025 14:29:13 inside heredoc-generated scripts for live timestamps - install.sh: capture and pop specific stash ref to avoid popping wrong entry - README: replace wildcard update examples with explicit deployment path --- install/README.md | 6 +++--- install/install.sh | 14 ++++++++------ install/update.sh | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/install/README.md b/install/README.md index 96e1002e..874fafe4 100644 --- a/install/README.md +++ b/install/README.md @@ -376,11 +376,11 @@ OpenAlgo can be updated to the latest version using multiple methods: The update script provides a safe and comprehensive update process: ```bash -# Update all installations interactively -sudo bash /var/python/openalgo-flask/*/openalgo/install/update.sh +# Update all installations interactively (run the script once; choose "all") +sudo bash /var/python/openalgo-flask/yourdomain-broker/openalgo/install/update.sh # Update a specific installation -sudo bash /var/python/openalgo-flask/*/openalgo/install/update.sh /var/python/openalgo-flask/yourdomain-broker +sudo bash /var/python/openalgo-flask/yourdomain-broker/openalgo/install/update.sh /var/python/openalgo-flask/yourdomain-broker ``` The update script will: diff --git a/install/install.sh b/install/install.sh index 23c5cfdf..75743974 100644 --- a/install/install.sh +++ b/install/install.sh @@ -629,6 +629,8 @@ if [ -d "$OPENALGO_PATH" ] && [ -d "$OPENALGO_PATH/.git" ]; then log_message "Error: Could not stash changes. Please commit or discard changes manually." "$RED" exit 1 } + # Capture the specific stash ref we just created to avoid popping unrelated entries + STASH_REF=$(sudo -u $WEB_USER git stash list | grep -m1 "Auto-stash before install update" | awk -F: '{print $1}') fi # Pull latest changes @@ -637,9 +639,9 @@ if [ -d "$OPENALGO_PATH" ] && [ -d "$OPENALGO_PATH/.git" ]; then check_status "Failed to pull latest changes" # Restore stashed changes if any - if sudo -u $WEB_USER git stash list | grep -q "Auto-stash before install update"; then + if [ -n "$STASH_REF" ]; then log_message "Restoring stashed changes..." "$YELLOW" - sudo -u $WEB_USER git stash pop 2>/dev/null || log_message "Warning: Could not restore stashed changes" "$YELLOW" + sudo -u $WEB_USER git stash pop "$STASH_REF" 2>/dev/null || log_message "Warning: Could not restore stashed changes" "$YELLOW" fi NEW_COMMIT=$(sudo -u $WEB_USER git rev-parse HEAD) @@ -1150,7 +1152,7 @@ CURRENT_COMMIT=\$(sudo -u $WEB_USER git rev-parse HEAD) REMOTE_COMMIT=\$(sudo -u $WEB_USER git rev-parse origin/\${CURRENT_BRANCH}) if [ "\$CURRENT_COMMIT" != "\$REMOTE_COMMIT" ]; then - echo "[$(date)] Updating $DEPLOY_NAME from \${CURRENT_COMMIT:0:8} to \${REMOTE_COMMIT:0:8}..." + echo "[\$(date)] Updating $DEPLOY_NAME from \${CURRENT_COMMIT:0:8} to \${REMOTE_COMMIT:0:8}..." # Stash any local changes sudo -u $WEB_USER git stash push -m "Auto-stash before scheduled update \$(date +%Y%m%d_%H%M%S)" 2>/dev/null @@ -1180,14 +1182,14 @@ if [ "\$CURRENT_COMMIT" != "\$REMOTE_COMMIT" ]; then # Restart service systemctl restart $SERVICE_NAME > /dev/null 2>&1 - echo "[$(date)] Update completed successfully for $DEPLOY_NAME" + echo "[\$(date)] Update completed successfully for $DEPLOY_NAME" else - echo "[$(date)] Error: Failed to update $DEPLOY_NAME" + echo "[\$(date)] Error: Failed to update $DEPLOY_NAME" # Restore stashed changes on failure sudo -u $WEB_USER git stash pop 2>/dev/null fi else - echo "[$(date)] $DEPLOY_NAME is already up to date" + echo "[\$(date)] $DEPLOY_NAME is already up to date" fi EOUPDATESCRIPT diff --git a/install/update.sh b/install/update.sh index ef06467a..ce0e5411 100644 --- a/install/update.sh +++ b/install/update.sh @@ -259,7 +259,7 @@ else # Multiple installations log_message "\nFound ${#INSTALLATIONS[@]} OpenAlgo installation(s):" "$BLUE" for i in "${!INSTALLATIONS[@]}"; do - local deploy_name=$(basename "${INSTALLATIONS[$i]}") + deploy_name=$(basename "${INSTALLATIONS[$i]}") log_message " [$((i+1))] $deploy_name (${INSTALLATIONS[$i]})" "$BLUE" done