- Move all Astro files from dealplustech-astro/ to root - Archive Next.js code in _nextjs-backup/ - Update .gitignore for Astro project - Simplify project structure This completes the migration from Next.js to Astro. The Astro project is now at the root level.
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
|