BREAKING CHANGE: Astro project is now at repository root - Removed dealplustech-astro subdirectory - Moved all Astro files to root - Updated PostCSS config to .cjs - Removed old Next.js files ✅ 11 pages built successfully ✅ Cookie consent banner included ✅ Privacy/Terms links in footer ✅ Ready for Easypanel deployment (no root dir needed) Migration path: - Old structure: /dealplustech-astro/ - New structure: / (root)
281 lines
7.3 KiB
Bash
Executable File
281 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
||
# Easypanel Deployment Skill v2.2
|
||
# Production-ready with error handling
|
||
|
||
set -e
|
||
|
||
CREDENTIALS_FILE="$HOME/.easypanel/credentials"
|
||
STATE_FILE="$HOME/.easypanel/state.json"
|
||
CONFIG_FILE="easypanel.config.json"
|
||
|
||
# Load credentials
|
||
if [ -f "$CREDENTIALS_FILE" ]; then
|
||
export $(grep -v '^#' "$CREDENTIALS_FILE" | xargs) 2>/dev/null || true
|
||
fi
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; }
|
||
log_success() { echo -e "${GREEN}✅ $1${NC}"; }
|
||
log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
||
log_error() { echo -e "${RED}❌ $1${NC}"; }
|
||
|
||
# Check token
|
||
if [ -z "$EASYPANEL_API_TOKEN" ] || [ "$EASYPANEL_API_TOKEN" = "YOUR_API_TOKEN_HERE" ]; then
|
||
log_error "API token not set!"
|
||
echo ""
|
||
echo "Edit ~/.easypanel/credentials and add your token"
|
||
exit 1
|
||
fi
|
||
|
||
# Load config
|
||
load_config() {
|
||
if [ -f "$CONFIG_FILE" ]; then
|
||
APP_NAME=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE'))['easypanel']['app']['name'])" 2>/dev/null || echo "")
|
||
PORT=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE'))['easypanel']['app']['port'])" 2>/dev/null || echo "4321")
|
||
DOCKER_IMAGE=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE'))['easypanel']['app']['image'])" 2>/dev/null || echo "")
|
||
PROJECT_NAME=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE'))['easypanel']['project'])" 2>/dev/null || echo "default")
|
||
fi
|
||
APP_NAME="${APP_NAME:-$(basename "$(pwd)")}"
|
||
PORT="${PORT:-4321}"
|
||
DOCKER_IMAGE="${DOCKER_IMAGE:-$APP_NAME:latest}"
|
||
PROJECT_NAME="${PROJECT_NAME:-default}"
|
||
}
|
||
|
||
# Save state
|
||
save_state() {
|
||
python3 << PYEOF
|
||
import json, os
|
||
from datetime import datetime
|
||
|
||
state_file = "$STATE_FILE"
|
||
os.makedirs(os.path.dirname(state_file), exist_ok=True)
|
||
|
||
if os.path.exists(state_file):
|
||
with open(state_file, 'r') as f:
|
||
state = json.load(f)
|
||
else:
|
||
state = {"version":"2.0","projects":{},"services":{},"deployments":[]}
|
||
|
||
if "$1" == "service":
|
||
state['services']['$2'] = {'id':'$3','project_id':'$PROJECT_ID','name':'$APP_NAME','port':$PORT,'updated':datetime.utcnow().isoformat()+"Z"}
|
||
elif "$1" == "project":
|
||
state['projects']['$2'] = {'id':'$3','name':'$2','updated':datetime.utcnow().isoformat()+"Z"}
|
||
|
||
with open(state_file, 'w') as f:
|
||
json.dump(state, f, indent=2)
|
||
|
||
print(f"Saved: {$1}.$2 = $3")
|
||
PYEOF
|
||
}
|
||
|
||
# Get state
|
||
get_state() {
|
||
python3 << PYEOF 2>/dev/null || echo ""
|
||
import json
|
||
try:
|
||
with open('$STATE_FILE', 'r') as f:
|
||
state = json.load(f)
|
||
key, type = '$1', '$2'
|
||
if type == 'service' and key in state.get('services', {}):
|
||
print(state['services'][key].get('id', ''))
|
||
elif type == 'project' and key in state.get('projects', {}):
|
||
print(state['projects'][key].get('id', ''))
|
||
except:
|
||
pass
|
||
PYEOF
|
||
}
|
||
|
||
# List projects
|
||
list_projects() {
|
||
log_info "Fetching projects from Easypanel..."
|
||
|
||
local response=$(curl -s -w "\n%{http_code}" \
|
||
"http://110.164.146.46:3000/api/trpc/projects.listProjects" \
|
||
-H "Authorization: Bearer $EASYPANEL_API_TOKEN" \
|
||
--insecure --compressed)
|
||
|
||
local http_code=$(echo "$response" | tail -1)
|
||
local body=$(echo "$response" | sed '$d')
|
||
|
||
if [ "$http_code" != "200" ]; then
|
||
log_error "Failed to fetch projects (HTTP $http_code)"
|
||
return 1
|
||
fi
|
||
|
||
echo "$body" | python3 << 'PYEOF'
|
||
import json, sys
|
||
|
||
try:
|
||
data = json.load(sys.stdin)
|
||
result = data.get('result', {})
|
||
data_content = result.get('data', {}) if isinstance(result, dict) else {}
|
||
items = data_content.get('items', [])
|
||
|
||
if not items:
|
||
print("No projects found")
|
||
else:
|
||
print(f"\n{'ID':<25} {'Name':<30}")
|
||
print("-" * 60)
|
||
for proj in items:
|
||
pid = str(proj.get('id', ''))[:23]
|
||
name = str(proj.get('name', ''))[:28]
|
||
print(f"{pid:<25} {name:<30}")
|
||
print("-" * 60)
|
||
print(f"Total: {len(items)} project(s)\n")
|
||
except Exception as e:
|
||
print(f"Error parsing response: {e}")
|
||
print("Raw response:", sys.stdin.read()[:200])
|
||
PYEOF
|
||
}
|
||
|
||
# Deploy command
|
||
cmd_deploy() {
|
||
load_config
|
||
|
||
log_info "========================================"
|
||
log_info "Deploying $APP_NAME"
|
||
log_info "========================================"
|
||
log_info "Project: $PROJECT_NAME"
|
||
log_info "Image: $DOCKER_IMAGE"
|
||
log_info "Port: $PORT"
|
||
log_info ""
|
||
|
||
# Build Docker
|
||
log_info "Building Docker image..."
|
||
if [ ! "$SKIP_BUILD" = "true" ]; then
|
||
docker build -t "$DOCKER_IMAGE" . || {
|
||
log_error "Docker build failed"
|
||
exit 1
|
||
}
|
||
log_success "Built: $DOCKER_IMAGE"
|
||
fi
|
||
|
||
# List projects and find/create
|
||
log_info "Looking for project: $PROJECT_NAME"
|
||
list_projects
|
||
|
||
log_warning ""
|
||
log_warning "⚠️ Manual Step Required"
|
||
log_warning ""
|
||
log_info "Easypanel API requires service creation via dashboard"
|
||
log_info ""
|
||
log_info "Steps:"
|
||
log_info "1. Open: $EASYPANEL_URL"
|
||
log_info "2. Select project: $PROJECT_NAME (or create it)"
|
||
log_info "3. Click 'New Service' → 'Docker image'"
|
||
log_info "4. Enter:"
|
||
log_info " Name: $APP_NAME"
|
||
log_info " Image: $DOCKER_IMAGE"
|
||
log_info " Port: $PORT"
|
||
log_info "5. Deploy"
|
||
log_info ""
|
||
log_info "After deployment, save the service ID:"
|
||
log_info "./deploy.sh register SERVICE_ID"
|
||
log_info ""
|
||
|
||
# Save deployment attempt
|
||
save_state "last_attempt" "$APP_NAME" "deployment"
|
||
}
|
||
|
||
# Register service
|
||
cmd_register() {
|
||
local service_id="$1"
|
||
if [ -z "$service_id" ]; then
|
||
log_error "Service ID required"
|
||
log_info "Usage: ./deploy.sh register SERVICE_ID"
|
||
exit 1
|
||
fi
|
||
|
||
load_config
|
||
save_state "service" "$APP_NAME" "$service_id"
|
||
|
||
log_success "✅ Service registered!"
|
||
log_info "Service ID: $service_id"
|
||
log_info "Next update: ./deploy.sh update"
|
||
}
|
||
|
||
# Update service
|
||
cmd_update() {
|
||
load_config
|
||
|
||
SERVICE_ID=$(get_state "$APP_NAME" "service")
|
||
|
||
if [ -z "$SERVICE_ID" ]; then
|
||
log_error "Service not registered"
|
||
log_info "Run: ./deploy.sh deploy"
|
||
exit 1
|
||
fi
|
||
|
||
log_info "Updating: $APP_NAME ($SERVICE_ID)"
|
||
|
||
# Rebuild
|
||
if [ ! "$SKIP_BUILD" = "true" ]; then
|
||
docker build -t "$DOCKER_IMAGE" . || exit 1
|
||
log_success "Rebuilt: $DOCKER_IMAGE"
|
||
fi
|
||
|
||
log_info "✅ Image ready"
|
||
log_info ""
|
||
log_info "To deploy update:"
|
||
log_info "1. Go to $EASYPANEL_URL"
|
||
log_info "2. Select service: $APP_NAME"
|
||
log_info "3. Click 'Deploy' to pull new image"
|
||
}
|
||
|
||
# Status
|
||
cmd_status() {
|
||
load_config
|
||
SERVICE_ID=$(get_state "$APP_NAME" "service")
|
||
|
||
if [ -z "$SERVICE_ID" ]; then
|
||
log_error "Not deployed"
|
||
exit 1
|
||
fi
|
||
|
||
log_info "Service: $APP_NAME"
|
||
log_info "ID: $SERVICE_ID"
|
||
log_info "Image: $DOCKER_IMAGE"
|
||
log_info "Port: $PORT"
|
||
}
|
||
|
||
# Help
|
||
cmd_help() {
|
||
cat << 'EOF'
|
||
Easypanel Deployment Skill v2.2
|
||
|
||
Usage: ./deploy.sh [command]
|
||
|
||
Commands:
|
||
deploy Build and prepare deployment
|
||
register ID Register service with ID
|
||
update Update existing service
|
||
status Show status
|
||
list List projects
|
||
help This help
|
||
|
||
Workflow:
|
||
1. ./deploy.sh deploy
|
||
2. Create service in Easypanel dashboard
|
||
3. ./deploy.sh register SERVICE_ID
|
||
4. ./deploy.sh update (for future updates)
|
||
EOF
|
||
}
|
||
|
||
SKIP_BUILD="false"
|
||
[ "$1" = "-b" ] || [ "$1" = "--skip-build" ] && SKIP_BUILD="true"
|
||
|
||
case "${1:-deploy}" in
|
||
deploy) cmd_deploy ;;
|
||
register) cmd_register "$2" ;;
|
||
update) cmd_update ;;
|
||
status) cmd_status ;;
|
||
list) list_projects ;;
|
||
help|--help|-h) cmd_help ;;
|
||
*) cmd_help; exit 1 ;;
|
||
esac
|