320 lines
10 KiB
Bash
Executable File
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
|