Files
stats/self-hosting/get_latest_images
Carl-Gerhard Lindesvärd 42d0fb8572 fix self-hosting
2025-10-22 11:38:37 +02:00

320 lines
10 KiB
Bash
Executable File

#!/bin/bash
# GitHub repository (update if needed)
REPO="${GITHUB_REPO:-Openpanel-dev/openpanel}"
# Components to find tags for
COMPONENTS=("worker" "api" "dashboard")
# Docker compose file path
DOCKER_COMPOSE_FILE="${DOCKER_COMPOSE_FILE:-./docker-compose.yml}"
# Color codes for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Show usage
show_usage() {
echo "Usage: $0 [COMMAND] [OPTIONS]"
echo ""
echo "Fetches the latest Git tags for worker, api, and dashboard components"
echo ""
echo "Commands:"
echo " apply Apply the latest tags to docker-compose.yml"
echo " (none) Show the latest tags (default)"
echo ""
echo "Options:"
echo " --list, -l List all available tags"
echo " --repo REPO Specify GitHub repository (default: $REPO)"
echo " --file FILE Specify docker-compose file (default: $DOCKER_COMPOSE_FILE)"
echo " --help, -h Show this help message"
echo ""
echo "Environment variables:"
echo " GITHUB_REPO Set the GitHub repository"
echo " DOCKER_COMPOSE_FILE Set the docker-compose file path"
echo ""
echo "Examples:"
echo " $0 # Show latest tags"
echo " $0 apply # Update docker-compose.yml with latest tags"
echo " $0 --list # List all available tags"
echo ""
exit 0
}
# Parse arguments
LIST_ALL=false
APPLY_MODE=false
while [[ $# -gt 0 ]]; do
case $1 in
apply)
APPLY_MODE=true
shift
;;
--list|-l)
LIST_ALL=true
shift
;;
--repo)
REPO="$2"
shift 2
;;
--file)
DOCKER_COMPOSE_FILE="$2"
shift 2
;;
--help|-h)
show_usage
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
show_usage
;;
esac
done
# Check if jq is installed (required for JSON parsing)
if ! command -v jq &> /dev/null; then
echo -e "${YELLOW}jq is required but not installed${NC}\n"
echo -e "${CYAN}jq is a lightweight JSON processor needed to parse GitHub API responses.${NC}\n"
# Detect OS and suggest installation
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS_ID=$ID
elif [[ "$OSTYPE" == "darwin"* ]]; then
OS_ID="macos"
else
OS_ID="unknown"
fi
# Determine installation command
case $OS_ID in
ubuntu|debian)
INSTALL_CMD="sudo apt-get update && sudo apt-get install -y jq"
;;
rhel|centos|fedora)
INSTALL_CMD="sudo yum install -y jq"
;;
alpine)
INSTALL_CMD="sudo apk add --no-cache jq"
;;
macos)
INSTALL_CMD="brew install jq"
;;
*)
echo -e "${RED}Could not detect your OS.${NC}"
echo -e "${YELLOW}Please install jq manually:${NC}"
echo -e " ${GREEN}Ubuntu/Debian:${NC} sudo apt-get update && sudo apt-get install -y jq"
echo -e " ${GREEN}RHEL/CentOS:${NC} sudo yum install -y jq"
echo -e " ${GREEN}Alpine:${NC} sudo apk add --no-cache jq"
echo -e " ${GREEN}macOS:${NC} brew install jq"
echo ""
exit 1
;;
esac
# Ask user if they want to install
read -p "$(echo -e ${GREEN}Would you like to install jq now? [Y/n]:${NC} )" -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
echo -e "${RED}jq is required to continue. Please install it manually.${NC}"
exit 1
fi
# Install jq
echo -e "${BLUE}Installing jq...${NC}\n"
if eval "$INSTALL_CMD"; then
echo -e "\n${GREEN}✓ jq installed successfully!${NC}\n"
else
echo -e "\n${RED}✗ Failed to install jq. Please install it manually.${NC}"
exit 1
fi
fi
# Check if user needs to be logged in (for apply mode)
if [ "$APPLY_MODE" = true ]; then
# Check if Docker is available
if ! command -v docker &> /dev/null; then
echo -e "${RED}Error: Docker is not installed or not in PATH${NC}"
exit 1
fi
# Check if logged into docker.openpanel.dev
echo -e "${BLUE}Checking Docker registry authentication...${NC}\n"
if ! docker info 2>/dev/null | grep -q "docker.openpanel.dev" && ! grep -q "docker.openpanel.dev" ~/.docker/config.json 2>/dev/null; then
echo -e "${YELLOW}⚠ You need to login to the OpenPanel Docker registry first!${NC}\n"
echo -e "${CYAN}To access the latest Docker images, you need:${NC}"
echo -e " 1. Be a supporter (starts at \$20/month)"
echo -e " 2. Get your API key from your supporter dashboard"
echo -e " 3. Login to the registry with:\n"
echo -e "${GREEN} echo \"your_api_key\" | docker login docker.openpanel.dev -u user --password-stdin${NC}\n"
echo -e "${GRAY}For more info: https://openpanel.dev/docs/self-hosting/supporter-access-latest-docker-images${NC}\n"
read -p "$(echo -e ${YELLOW}Have you already logged in? [y/N]:${NC} )" -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo -e "${RED}Please login first and try again.${NC}"
exit 1
fi
else
echo -e "${GREEN}✓ Docker registry authentication OK${NC}\n"
fi
fi
echo -e "${BLUE}Fetching tags from ${REPO}...${NC}\n"
# Fetch all tags from GitHub API
TAGS_JSON=$(curl -s "https://api.github.com/repos/${REPO}/tags")
# Check if we got valid JSON response
if [ -z "$TAGS_JSON" ]; then
echo -e "${RED}Failed to fetch tags from GitHub API${NC}"
exit 1
fi
# Check if repository has any tags
TAGS_CLEAN=$(echo "$TAGS_JSON" | tr -d '[:space:]')
if [ "$TAGS_CLEAN" == "[]" ]; then
echo -e "${RED}No tags found in repository${NC}"
echo -e "${YELLOW}Create tags using: git tag <tag-name> && git push origin <tag-name>${NC}"
echo ""
echo -e "${GRAY}Example tag naming patterns:${NC}"
echo -e " ${GRAY}- worker-v1.0.0${NC}"
echo -e " ${GRAY}- api-v1.0.0${NC}"
echo -e " ${GRAY}- dashboard-v1.0.0${NC}"
exit 1
fi
# List all tags if requested
if [ "$LIST_ALL" = true ]; then
echo -e "${GREEN}All available tags:${NC}\n"
echo "$TAGS_JSON" | jq -r '.[] | " \(.name) (\(.commit.sha[0:7]))"'
echo ""
exit 0
fi
# Function to find latest tag matching a component
get_latest_tag() {
local component=$1
local output_var_tag=$2
local output_var_sha=$3
# Use jq for JSON parsing
local tag=$(echo "$TAGS_JSON" | jq -r "[.[] | select(.name | contains(\"${component}\"))] | .[0] | .name" 2>/dev/null)
local sha=$(echo "$TAGS_JSON" | jq -r "[.[] | select(.name | contains(\"${component}\"))] | .[0] | .commit.sha" 2>/dev/null)
if [ -z "$tag" ] || [ "$tag" == "null" ]; then
echo -e "${RED}${NC} ${component}: No matching tag found"
echo
return 1
fi
echo -e "${GREEN}${NC} ${component}:"
echo -e " Tag: ${YELLOW}${tag}${NC}"
echo -e " SHA: ${sha}"
echo
# Return values via eval (for compatibility with older bash)
if [ -n "$output_var_tag" ]; then
eval "$output_var_tag='$tag'"
fi
if [ -n "$output_var_sha" ]; then
eval "$output_var_sha='$sha'"
fi
return 0
}
# Function to apply tags to docker-compose.yml
apply_tags() {
echo -e "${CYAN}Applying tags to ${DOCKER_COMPOSE_FILE}...${NC}\n"
# Check if docker-compose file exists
if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then
echo -e "${RED}Error: Docker compose file not found: ${DOCKER_COMPOSE_FILE}${NC}"
exit 1
fi
# Create a backup
local backup_file="${DOCKER_COMPOSE_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$DOCKER_COMPOSE_FILE" "$backup_file"
echo -e "${GRAY}Created backup: ${backup_file}${NC}\n"
local updated=0
local failed=0
for component in "${COMPONENTS[@]}"; do
# Get tag and SHA for this component
local component_tag=""
local component_sha=""
get_latest_tag "$component" component_tag component_sha >/dev/null 2>&1
if [ -z "$component_sha" ] || [ "$component_sha" == "null" ]; then
echo -e "${RED}${NC} ${component}: Skipping (no tag found)"
((failed++))
continue
fi
# Get first 4 characters of SHA
local short_sha="${component_sha:0:4}"
# New image tag format
local new_image="docker.openpanel.dev/openpanel-dev/${component}:main-${short_sha}"
# Find and replace the image line in docker-compose.yml
# Look for lines like: image: something{component}something
if grep -q "image:.*${component}" "$DOCKER_COMPOSE_FILE"; then
# Use sed to replace the entire image line
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS sed syntax
sed -i '' "s|image:.*${component}.*|image: ${new_image}|g" "$DOCKER_COMPOSE_FILE"
else
# Linux sed syntax
sed -i "s|image:.*${component}.*|image: ${new_image}|g" "$DOCKER_COMPOSE_FILE"
fi
echo -e "${GREEN}${NC} Updated ${component}: ${CYAN}${new_image}${NC}"
((updated++))
else
echo -e "${YELLOW}${NC} ${component}: No matching image line found in docker-compose.yml"
((failed++))
fi
done
echo ""
echo -e "${BLUE}Summary:${NC}"
echo -e " Updated: ${GREEN}${updated}${NC}"
echo -e " Failed: ${RED}${failed}${NC}"
echo -e " Backup: ${GRAY}${backup_file}${NC}"
echo ""
if [ $updated -gt 0 ]; then
echo -e "${GREEN}Successfully updated docker-compose.yml!${NC}"
fi
}
# Main execution
if [ "$APPLY_MODE" = true ]; then
# Apply mode: update docker-compose.yml
# First, show all tags
for component in "${COMPONENTS[@]}"; do
get_latest_tag "$component"
done
# Then apply them
apply_tags
else
# Default mode: just show the tags
for component in "${COMPONENTS[@]}"; do
get_latest_tag "$component"
done
echo -e "${GRAY}Tip: Use --list to see all available tags, or 'apply' to update docker-compose.yml${NC}"
echo -e "${BLUE}Done!${NC}"
fi