Add automatic update functionality to HOPS v3.3.0

- Add git-based update mechanism with backup functionality
- Support command-line flags: --update, --check-updates, --version, --help
- Interactive update checking via main menu (option 6)
- Automatic backup of local changes before updates
- Version comparison and changelog display
- Enhanced error handling for update process

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Stephen Klein
2025-07-19 07:33:18 -04:00
parent b114bd54c8
commit 7d8aeee45b
+179 -20
View File
@@ -2,13 +2,13 @@
# HOPS - Homelab Orchestration Provisioning Script # HOPS - Homelab Orchestration Provisioning Script
# Primary Management Script # Primary Management Script
# Version: 3.2.0 # Version: 3.3.0
# Exit on any error # Exit on any error
set -e set -e
# Script version and metadata # Script version and metadata
readonly SCRIPT_VERSION="3.2.0" readonly SCRIPT_VERSION="3.3.0"
readonly SCRIPT_NAME="HOPS" readonly SCRIPT_NAME="HOPS"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -17,19 +17,11 @@ readonly INSTALLER_SCRIPT="$SCRIPT_DIR/install"
readonly UNINSTALLER_SCRIPT="$SCRIPT_DIR/uninstall" readonly UNINSTALLER_SCRIPT="$SCRIPT_DIR/uninstall"
readonly SERVICE_DEFINITIONS="$SCRIPT_DIR/services" readonly SERVICE_DEFINITIONS="$SCRIPT_DIR/services"
# Color codes for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly PURPLE='\033[0;35m'
readonly CYAN='\033[0;36m'
readonly WHITE='\033[1;37m'
readonly NC='\033[0m' # No Color
# Load system utilities # Load system utilities
source "$SCRIPT_DIR/lib/system.sh" source "$SCRIPT_DIR/lib/system.sh"
# Color codes are defined in lib/common.sh
# Logging setup (will be set by setup_logging) # Logging setup (will be set by setup_logging)
LOG_DIR="" LOG_DIR=""
LOG_FILE="" LOG_FILE=""
@@ -546,6 +538,109 @@ show_logs() {
read -r read -r
} }
# Check for updates
check_for_updates() {
info "Checking for updates..."
# Check if we're in a git repository
if ! git -C "$SCRIPT_DIR" rev-parse --git-dir >/dev/null 2>&1; then
warning "Not in a git repository. Cannot check for updates."
return 1
fi
# Fetch latest changes
if ! git -C "$SCRIPT_DIR" fetch origin main >/dev/null 2>&1; then
warning "Failed to fetch updates from remote repository."
return 1
fi
# Check if we're behind
local local_commit=$(git -C "$SCRIPT_DIR" rev-parse HEAD)
local remote_commit=$(git -C "$SCRIPT_DIR" rev-parse origin/main)
if [[ "$local_commit" == "$remote_commit" ]]; then
success "HOPS is up to date (v$SCRIPT_VERSION)"
return 0
else
local commits_behind=$(git -C "$SCRIPT_DIR" rev-list --count HEAD..origin/main)
warning "HOPS is $commits_behind commits behind. Update available!"
# Show what's new
echo -e "\n${BLUE}📋 Recent changes:${NC}"
git -C "$SCRIPT_DIR" log --oneline --max-count=5 HEAD..origin/main | sed 's/^/ • /'
return 1
fi
}
# Update HOPS
update_hops() {
show_header
echo -e "${WHITE}🔄 HOPS Update${NC}\n"
# Check if we're in a git repository
if ! git -C "$SCRIPT_DIR" rev-parse --git-dir >/dev/null 2>&1; then
error_exit "Not in a git repository. Cannot update automatically."
fi
# Check for local changes
if ! git -C "$SCRIPT_DIR" diff-index --quiet HEAD --; then
warning "Local changes detected. These will be backed up before updating."
# Create backup
local backup_dir="$SCRIPT_DIR/.backup-$(date +%Y%m%d-%H%M%S)"
info "Creating backup at: $backup_dir"
if ! cp -r "$SCRIPT_DIR" "$backup_dir"; then
error_exit "Failed to create backup"
fi
success "Backup created successfully"
fi
# Fetch and show what will be updated
info "Fetching latest changes..."
if ! git -C "$SCRIPT_DIR" fetch origin main; then
error_exit "Failed to fetch updates from remote repository"
fi
# Check if update is needed
if ! check_for_updates; then
echo -e "\n${WHITE}Continue with update? [y/N]: ${NC}"
read -r update_choice
if [[ ! "$update_choice" =~ ^[Yy]$ ]]; then
info "Update cancelled"
echo -e "\n${WHITE}Press Enter to return to main menu...${NC}"
read -r
return
fi
else
info "Already up to date"
echo -e "\n${WHITE}Press Enter to return to main menu...${NC}"
read -r
return
fi
# Perform the update
info "Updating HOPS..."
if git -C "$SCRIPT_DIR" pull origin main; then
success "HOPS updated successfully!"
# Source the updated script to get new version
if [[ -f "$SCRIPT_DIR/hops" ]]; then
local new_version=$(grep '^readonly SCRIPT_VERSION=' "$SCRIPT_DIR/hops" | cut -d'"' -f2)
success "Updated to version $new_version"
fi
echo -e "\n${YELLOW}💡 Note: Please restart HOPS to use the updated version${NC}"
else
error_exit "Update failed. Your installation may be in an inconsistent state."
fi
echo -e "\n${WHITE}Press Enter to exit (restart HOPS to use new version)...${NC}"
read -r
exit 0
}
# Show help information # Show help information
show_help() { show_help() {
show_header show_header
@@ -624,11 +719,12 @@ show_main_menu() {
echo -e " 5) Access Information ${YELLOW}(not installed)${NC}" echo -e " 5) Access Information ${YELLOW}(not installed)${NC}"
fi fi
echo -e " 6) View Logs" echo -e " 6) Check for Updates"
echo -e " 7) Help & Documentation" echo -e " 7) View Logs"
echo -e " 8) Exit" echo -e " 8) Help & Documentation"
echo -e " 9) Exit"
echo -e "\n${WHITE}Select an option [1-8]: ${NC}" echo -e "\n${WHITE}Select an option [1-9]: ${NC}"
} }
# Main program loop # Main program loop
@@ -662,24 +758,87 @@ main() {
show_access_info show_access_info
;; ;;
6) 6)
show_logs # Check for updates and optionally update
if check_for_updates; then
echo -e "\n${WHITE}Press Enter to return to main menu...${NC}"
read -r
else
echo -e "\n${WHITE}Would you like to update now? [y/N]: ${NC}"
read -r update_choice
if [[ "$update_choice" =~ ^[Yy]$ ]]; then
update_hops
fi
fi
;; ;;
7) 7)
show_help show_logs
;; ;;
8) 8)
show_help
;;
9)
info "Thank you for using HOPS!" info "Thank you for using HOPS!"
exit 0 exit 0
;; ;;
*) *)
warning "Invalid option. Please select 1-8." warning "Invalid option. Please select 1-9."
sleep 2 sleep 2
;; ;;
esac esac
done done
} }
# Handle command line arguments
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
--update)
init_logging
check_root
update_hops
exit $?
;;
--check-updates)
init_logging
if check_for_updates; then
exit 0
else
exit 1
fi
;;
--version)
echo "HOPS v$SCRIPT_VERSION"
exit 0
;;
--help|-h)
echo "HOPS - Homelab Orchestration Provisioning Script v$SCRIPT_VERSION"
echo ""
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " --update Update HOPS to the latest version"
echo " --check-updates Check if updates are available (exit 1 if updates available)"
echo " --version Show version information"
echo " --help, -h Show this help message"
echo ""
echo "When run without options, HOPS starts in interactive mode."
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information."
exit 1
;;
esac
shift
done
}
# Script entry point # Script entry point
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@" # Parse command line arguments first
parse_args "$@"
# If no arguments provided, run main interactive mode
main
fi fi