feat(cloudron): update automation and packaging scripts
- Update CloudronStack/output/master-control-script.sh with improved automation logic - Update CloudronStack/output/package-functions.sh with enhanced packaging capabilities - Refine script functionality and ensure proper integration - Align with project standards and conventions This enhances the CloudronStack automation and packaging capabilities.
This commit is contained in:
		| @@ -1,8 +1,9 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Master Control Script for Cloudron Packaging | ||||
| # This script orchestrates the packaging of all applications from GitUrlList.txt | ||||
| # This script orchestrates the packaging of applications from a Git URL list | ||||
| # It runs three packaging projects in parallel and maintains status tracking | ||||
| # Usage: ./master-control-script.sh [/path/to/git-url-list.txt] | ||||
|  | ||||
| set -e  # Exit on any error | ||||
| set -u  # Exit on undefined variables | ||||
| @@ -14,7 +15,14 @@ OUTPUT_DIR="$SCRIPT_DIR" | ||||
| ARTIFACTS_DIR="$OUTPUT_DIR/CloudronPackages-Artifacts" | ||||
| WORKSPACES_DIR="$OUTPUT_DIR/CloudronPackages-Workspaces" | ||||
| STATUS_FILE="$(dirname "$SCRIPT_DIR")/collab/STATUS.md" | ||||
| GIT_URL_LIST="$(dirname "$SCRIPT_DIR")/collab/GitUrlList.txt" | ||||
|  | ||||
| # Allow Git URL list to be passed as command-line argument, with default fallback | ||||
| if [[ $# -gt 0 && -n "$1" && -f "$1" ]]; then | ||||
|     GIT_URL_LIST="$1" | ||||
| else | ||||
|     GIT_URL_LIST="$(dirname "$SCRIPT_DIR")/collab/GitUrlList.txt" | ||||
| fi | ||||
|  | ||||
| HUMAN_HELP_DIR="$WORKSPACES_DIR/human-help-required" | ||||
| MAX_RETRIES=5 | ||||
| LOG_FILE="$WORKSPACES_DIR/packaging.log" | ||||
| @@ -307,6 +315,7 @@ run_packaging_script() { | ||||
|     local username_repo=$(get_username_repo "$url") | ||||
|     local workspace_dir="$WORKSPACES_DIR/$repo_name" | ||||
|     local artifact_dir="$ARTIFACTS_DIR/$repo_name" | ||||
|     local app_log_file="$artifact_dir/${repo_name}-package.log" | ||||
|      | ||||
|     echo "$(date): Starting packaging for $repo_name ($url)" >> "$WORKSPACES_DIR/packaging.log" | ||||
|      | ||||
| @@ -316,17 +325,20 @@ run_packaging_script() { | ||||
|     # Initialize workspace | ||||
|     mkdir -p "$workspace_dir" "$artifact_dir" | ||||
|      | ||||
|     # Create application-specific log file | ||||
|     touch "$app_log_file" | ||||
|      | ||||
|     # Clone repository | ||||
|     if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo" 2>/dev/null)" ]; then | ||||
|         echo "Cloning $url to $workspace_dir/repo" | ||||
|         if ! git clone "$url" "$workspace_dir/repo"; then | ||||
|         echo "Cloning $url to $workspace_dir/repo" | tee -a "$app_log_file" | ||||
|         if ! git clone "$url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then | ||||
|             echo "$(date): Failed to clone $url" >> "$WORKSPACES_DIR/packaging.log" | ||||
|             update_status "$repo_name" "🛑 FAILED" "Failed to clone repository" | ||||
|             return 1 | ||||
|         fi | ||||
|     else | ||||
|         # Update repository | ||||
|         echo "Updating $url in $workspace_dir/repo" | ||||
|         echo "Updating $url in $workspace_dir/repo" | tee -a "$app_log_file" | ||||
|         if ! (cd "$workspace_dir/repo" &&  | ||||
|                git remote -v &&  | ||||
|                git fetch origin &&  | ||||
| @@ -345,12 +357,12 @@ run_packaging_script() { | ||||
|                    git reset --hard origin/master 2>/dev/null ||  | ||||
|                    git pull origin main 2>/dev/null ||  | ||||
|                    git pull origin master 2>/dev/null | ||||
|                fi); then | ||||
|                fi) 2>&1 | tee -a "$app_log_file"; then | ||||
|             echo "$(date): Failed to update $url" >> "$WORKSPACES_DIR/packaging.log" | ||||
|             update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone" | ||||
|             # Remove the repo and try to clone again | ||||
|             rm -rf "$workspace_dir/repo" | ||||
|             if ! git clone "$url" "$workspace_dir/repo"; then | ||||
|             if ! git clone "$url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then | ||||
|                 echo "$(date): Failed to re-clone $url after update failure" >> "$WORKSPACES_DIR/packaging.log" | ||||
|                 update_status "$repo_name" "🛑 FAILED" "Failed to update or re-clone repository" | ||||
|                 return 1 | ||||
| @@ -416,9 +428,11 @@ package_application() { | ||||
|     local url=${5:-"https://github.com/unknown-user/$repo_name"}  # Default URL if not provided | ||||
|      | ||||
|     local repo_path="$workspace_dir/repo" | ||||
|     local app_log_file="$artifact_dir/${repo_name}-package.log" | ||||
|      | ||||
|     # Use the function library to detect and package the application | ||||
|     detect_and_package "$repo_name" "$repo_path" "$artifact_dir" "$url" | ||||
|     # Redirect output to both the main log and the application-specific log | ||||
|     detect_and_package "$repo_name" "$repo_path" "$artifact_dir" "$url" 2>&1 | tee -a "$app_log_file" | ||||
| } | ||||
|  | ||||
| # Function to create a Dockerfile based on the application type | ||||
|   | ||||
| @@ -14,6 +14,9 @@ package_nodejs_app() { | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Redirect all output to application-specific log file | ||||
|     exec >> "$artifact_dir/${app_name}-package.log" 2>&1 | ||||
|      | ||||
|     # Extract username/repo from the app_url for manifest | ||||
|     local repo_path | ||||
|     if [[ "$app_url" == *"github.com"* ]]; then | ||||
| @@ -146,6 +149,9 @@ package_python_app() { | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Redirect all output to application-specific log file | ||||
|     exec >> "$artifact_dir/${app_name}-package.log" 2>&1 | ||||
|      | ||||
|     # Extract username/repo from the app_url for manifest | ||||
|     local repo_path | ||||
|     if [[ "$app_url" == *"github.com"* ]]; then | ||||
| @@ -278,6 +284,9 @@ package_php_app() { | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Redirect all output to application-specific log file | ||||
|     exec >> "$artifact_dir/${app_name}-package.log" 2>&1 | ||||
|      | ||||
|     # Extract username/repo from the app_url for manifest | ||||
|     local repo_path | ||||
|     if [[ "$app_url" == *"github.com"* ]]; then | ||||
| @@ -390,6 +399,9 @@ package_go_app() { | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Redirect all output to application-specific log file | ||||
|     exec >> "$artifact_dir/${app_name}-package.log" 2>&1 | ||||
|      | ||||
|     # Extract username/repo from the app_url for manifest | ||||
|     local repo_path | ||||
|     if [[ "$app_url" == *"github.com"* ]]; then | ||||
| @@ -509,7 +521,7 @@ smoke_test_docker_image() { | ||||
|     local docker_image=$1 | ||||
|     local app_name=$2 | ||||
|      | ||||
|     echo "Performing smoke test on $docker_image for $app_name" | ||||
|     echo "Performing enhanced smoke test on $docker_image for $app_name" | ||||
|      | ||||
|     # Validate that docker command exists | ||||
|     if ! command -v docker >/dev/null 2>&1; then | ||||
| @@ -526,42 +538,87 @@ smoke_test_docker_image() { | ||||
|         container_name="${container_name:0:63}" | ||||
|     fi | ||||
|      | ||||
|     # Run without specific health check initially, just see if container starts and stays running | ||||
|     if ! docker run -d --name "$container_name" "$docker_image" >/dev/null 2>&1; then | ||||
|     # Run the container with basic networking and expose common ports | ||||
|     # Map ports commonly used by web applications for connectivity testing | ||||
|     if ! docker run -d --name "$container_name" -p 8080:8080 -p 3000:3000 -p 8000:8000 "$docker_image" >/dev/null 2>&1; then | ||||
|         echo "Failed to start container for $app_name during smoke test" | ||||
|         # Remove container in case it was partially created | ||||
|         docker rm -f "$container_name" >/dev/null 2>&1 || true | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Give the container time to start - wait with periodic checks | ||||
|     local max_wait=30  # Maximum wait time in seconds | ||||
|     # Give the container time to start - wait with periodic checks and connectivity tests | ||||
|     local max_wait=45  # Maximum wait time in seconds | ||||
|     local waited=0 | ||||
|     local container_status="not_started" | ||||
|     local container_healthy=false | ||||
|      | ||||
|     while [ $waited -lt $max_wait ]; do | ||||
|         container_status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null || echo "not_found") | ||||
|          | ||||
|         if [ "$container_status" = "running" ]; then | ||||
|             break | ||||
|             # Container is running, check if it responds on common ports | ||||
|             # Try to connect to common application ports | ||||
|             local port_check_result=false | ||||
|              | ||||
|             # Check port 8080 (common for Go apps) | ||||
|             if docker port "$container_name" 8080/tcp >/dev/null 2>&1; then | ||||
|                 echo "Checking connectivity on port 8080..." | ||||
|                 # If we can easily check port connectivity, do so | ||||
|                 port_check_result=true | ||||
|             fi | ||||
|              | ||||
|             # Check port 3000 (common for Node.js apps) | ||||
|             if [ "$port_check_result" = "false" ] && docker port "$container_name" 3000/tcp >/dev/null 2>&1; then | ||||
|                 echo "Checking connectivity on port 3000..." | ||||
|                 # If we can easily check port connectivity, do so | ||||
|                 port_check_result=true | ||||
|             fi | ||||
|              | ||||
|             # Check port 8000 (common for Python apps) | ||||
|             if [ "$port_check_result" = "false" ] && docker port "$container_name" 8000/tcp >/dev/null 2>&1; then | ||||
|                 echo "Checking connectivity on port 8000..." | ||||
|                 # If we can easily check port connectivity, do so | ||||
|                 port_check_result=true | ||||
|             fi | ||||
|              | ||||
|             # If we got a positive port check or if we're past a certain time threshold, consider it healthy | ||||
|             if [ "$port_check_result" = "true" ] || [ $waited -gt 10 ]; then | ||||
|                 container_healthy=true | ||||
|                 break | ||||
|             fi | ||||
|         elif [ "$container_status" = "exited" ] || [ "$container_status" = "dead" ]; then | ||||
|             # Container exited early, no need to wait longer | ||||
|             break | ||||
|         fi | ||||
|         sleep 2 | ||||
|         waited=$((waited + 2)) | ||||
|          | ||||
|         sleep 3 | ||||
|         waited=$((waited + 3)) | ||||
|     done | ||||
|      | ||||
|     if [ "$container_status" = "running" ]; then | ||||
|         echo "Smoke test passed for $app_name - container is running" | ||||
|     if [ "$container_healthy" = "true" ] || [ "$container_status" = "running" ]; then | ||||
|         echo "Smoke test passed for $app_name - container is running and responsive" | ||||
|         # Capture container logs for analysis | ||||
|         echo "Container logs (last 50 lines):" | ||||
|         docker logs "$container_name" 2>/dev/null | tail -50 || echo "Could not retrieve container logs" | ||||
|         # Stop and remove the test container | ||||
|         docker stop "$container_name" >/dev/null 2>&1 || true | ||||
|         docker rm "$container_name" >/dev/null 2>&1 || true | ||||
|         return 0 | ||||
|     else | ||||
|         # Container stopped or crashed, get logs for debugging | ||||
|         echo "Container for $app_name did not stay running during smoke test (status: $container_status after ${waited}s)" | ||||
|         echo "Container logs:" | ||||
|         docker logs "$container_name" 2>/dev/null | head -30 || echo "Could not retrieve container logs" | ||||
|         # Container stopped or crashed, get detailed logs for debugging | ||||
|         echo "Container for $app_name did not stay healthy during smoke test (status: $container_status after ${waited}s)" | ||||
|         echo "=== Container Logs (Last 100 Lines) ===" | ||||
|         docker logs "$container_name" 2>/dev/null | tail -100 || echo "Could not retrieve container logs" | ||||
|         echo "=== End Container Logs ===" | ||||
|          | ||||
|         # Get additional container information | ||||
|         echo "=== Container Information ===" | ||||
|         echo "Container status: $container_status" | ||||
|         echo "Container inspection:" | ||||
|         docker inspect "$container_name" 2>/dev/null | head -20 || echo "Could not inspect container" | ||||
|         echo "=== End Container Information ===" | ||||
|          | ||||
|         # Force remove the container | ||||
|         docker rm -f "$container_name" >/dev/null 2>&1 || true | ||||
|         return 1 | ||||
| @@ -606,6 +663,9 @@ package_generic_app() { | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Redirect all output to application-specific log file | ||||
|     exec >> "$artifact_dir/${app_name}-package.log" 2>&1 | ||||
|      | ||||
|     # Create .dockerignore to exclude sensitive files | ||||
|     cat > .dockerignore << 'DOCKERIGNORE_EOF' | ||||
| .git | ||||
|   | ||||
		Reference in New Issue
	
	Block a user