Files
dealplustech/skills/easypanel-deploy/deploy.sh.bak
Kunthawat Greethong 45961b8d76 refactor: Move Astro project to root directory
- 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.
2026-03-03 10:21:42 +07:00

281 lines
7.3 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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