feat(cloudron): update CloudronStack configuration and assets
- Add new PROMPT file in collab directory for AI collaboration guidance - Add STATUS.md file in collab directory to track current status - Create output directory for project artifacts - Remove redundant commit-template.txt that is now centralized at top level - Update collab directory structure and content for better organization These changes improve the CloudronStack component's structure and documentation for better collaboration.
This commit is contained in:
		
							
								
								
									
										33
									
								
								CloudronStack/collab/PROMPT
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								CloudronStack/collab/PROMPT
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| Create Cloudron packages for all upstream applications found in: | ||||
|  | ||||
| collab/GitUrlList.txt for Cloudron. | ||||
|  | ||||
| Create shell scripts todo the packaging work and run three packaging projects in parallel. | ||||
|  | ||||
| Create a master control script to orchestrate the individual packaging scripts. | ||||
|  | ||||
| Create and maintain a status tracker in collab/STATUS.md | ||||
|  | ||||
| Take on these roles/perspectives for this chat: | ||||
|  | ||||
| - Prompt engineering expert | ||||
| - Cloudron packaging expert | ||||
| - Dockerfile expert | ||||
|  | ||||
| Do all of your work in the output/  directory tree. | ||||
|  | ||||
| It contains two subdirectories: | ||||
|  | ||||
| CloudronPackages-Artifacts for storing the actual Cloudron package artifacts | ||||
| CloudronPackages-Workspaces for cloning git repo, storing logs and whatever else is needed during packaging work | ||||
|  | ||||
| The docker images must build as part of package smoke testing. | ||||
|  | ||||
| Use this prefix for all docker images created by this process: | ||||
|  | ||||
| tsysdevstack-cloudron-buildtest- | ||||
|  | ||||
| If a packaging script has a problem and you cant solve the problem after five tries, flag it in STATUS-HumanHelp-<application> and move on | ||||
|  | ||||
| This is a big project. I expect it to run fully autonomously over the next four days or so. Be careful. Be Brutal. audit your work as you go. | ||||
| be methodical. start from first principles and develop a robust system and think/code defensively. | ||||
							
								
								
									
										87
									
								
								CloudronStack/collab/STATUS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								CloudronStack/collab/STATUS.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| # Cloudron Packaging Status Tracker | ||||
|  | ||||
| ## Overview | ||||
| This file tracks the status of Cloudron packaging for all upstream applications. | ||||
|  | ||||
| ## Status Legend | ||||
| - ✅ COMPLETE: Successfully packaged | ||||
| - 🔄 IN PROGRESS: Currently being packaged | ||||
| - 🛑 FAILED: Packaging failed after 5+ attempts | ||||
| - ⏳ PENDING: Awaiting packaging | ||||
|  | ||||
| ## Applications Status | ||||
|  | ||||
| | Application | URL | Status | Notes | | ||||
| |-------------|-----|--------|-------| | ||||
| | goalert | https://github.com/target/goalert | ⏳ PENDING | | | ||||
| | tirreno | https://github.com/tirrenotechnologies/tirreno | ⏳ PENDING | | | ||||
| | runme | https://github.com/runmedev/runme | ⏳ PENDING | | | ||||
| | datahub | https://github.com/datahub-project/datahub | ⏳ PENDING | | | ||||
| | docassemble | https://github.com/jhpyle/docassemble | ⏳ PENDING | | | ||||
| | pimcore | https://github.com/pimcore/pimcore | ⏳ PENDING | | | ||||
| | database-gateway | https://github.com/kazhuravlev/database-gateway | ⏳ PENDING | | | ||||
| | webhook | https://github.com/adnanh/webhook | ⏳ PENDING | | | ||||
| | fx | https://github.com/metrue/fx | ⏳ PENDING | | | ||||
| | fonoster | https://github.com/metrue/fx | ⏳ PENDING | | | ||||
| | oat-sa | https://github.com/oat-sa | ⏳ PENDING | | | ||||
| | rundeck | https://github.com/rundeck/rundeck | ⏳ PENDING | | | ||||
| | hyperswitch | https://github.com/juspay/hyperswitch | ⏳ PENDING | | | ||||
| | PayrollEngine | https://github.com/Payroll-Engine/PayrollEngine | ⏳ PENDING | | | ||||
| | openboxes | https://github.com/openboxes/openboxes | ⏳ PENDING | | | ||||
| | nautilus_trader | https://github.com/nautechsystems/nautilus_trader | ⏳ PENDING | | | ||||
| | apisix | https://github.com/apache/apisix | ⏳ PENDING | | | ||||
| | grist-core | https://github.com/gristlabs/grist-core | ⏳ PENDING | | | ||||
| | healthchecks | https://github.com/healthchecks/healthchecks | ⏳ PENDING | | | ||||
| | fleet | https://github.com/fleetdm/fleet | ⏳ PENDING | | | ||||
| | netbox | https://github.com/netbox-community/netbox | ⏳ PENDING | | | ||||
| | seatunnel | https://github.com/apache/seatunnel | ⏳ PENDING | | | ||||
| | rathole | https://github.com/rapiz1/rathole | ⏳ PENDING | | | ||||
| | easy-gate | https://github.com/wiredlush/easy-gate | ⏳ PENDING | | | ||||
| | huginn | https://github.com/huginn/huginn | ⏳ PENDING | | | ||||
| | consuldemocracy | https://github.com/consuldemocracy/consuldemocracy | ⏳ PENDING | | | ||||
| | boinc | https://github.com/BOINC/boinc | ⏳ PENDING | | | ||||
| | slurm | https://github.com/SchedMD/slurm | ⏳ PENDING | | | ||||
| | gophish | https://github.com/gophish/gophish | ⏳ PENDING | | | ||||
| | SniperPhish | https://github.com/GemGeorge/SniperPhish | ⏳ PENDING | | | ||||
| | InvenTree | https://github.com/inventree/InvenTree | ⏳ PENDING | | | ||||
| | mender | https://github.com/mendersoftware/mender | ⏳ PENDING | | | ||||
| | langfuse | https://github.com/langfuse/langfuse | ⏳ PENDING | | | ||||
| | wireviz-web | https://github.com/wireviz/wireviz-web | ⏳ PENDING | | | ||||
| | WireViz | https://github.com/wireviz/WireViz | ⏳ PENDING | | | ||||
| | killbill | https://github.com/killbill/killbill | ⏳ PENDING | | | ||||
| | autobom | https://github.com/opulo-inc/autobom | ⏳ PENDING | | | ||||
| | midday | https://github.com/midday-ai/midday | ⏳ PENDING | | | ||||
| | openblocks | https://github.com/openblocks-dev/openblocks | ⏳ PENDING | | | ||||
| | docker-drawio | https://github.com/jgraph/docker-drawio | ⏳ PENDING | | | ||||
| | signoz | https://github.com/SigNoz/signoz | ⏳ PENDING | | | ||||
| | sentry | https://github.com/getsentry/sentry | ⏳ PENDING | | | ||||
| | chirpstack | https://github.com/chirpstack/chirpstack | ⏳ PENDING | | | ||||
| | elabftw | https://github.com/elabftw/elabftw | ⏳ PENDING | | | ||||
| | PLMore | https://github.com/PLMore/PLMore | ⏳ PENDING | | | ||||
| | satnogs | https://gitlab.com/librespacefoundation/satnogs | ⏳ PENDING | | | ||||
| | jamovi | https://github.com/jamovi/jamovi | ⏳ PENDING | | | ||||
| | reviewboard | https://github.com/reviewboard/reviewboard | ⏳ PENDING | | | ||||
| | Core | https://github.com/Resgrid/Core | ⏳ PENDING | | | ||||
| | sdrangel | https://github.com/f4exb/sdrangel | ⏳ PENDING | | | ||||
| | no-code-architects-toolkit | https://github.com/stephengpope/no-code-architects-toolkit | ⏳ PENDING | | | ||||
| | warp | https://github.com/sebo-b/warp | ⏳ PENDING | | | ||||
| | windmill | https://github.com/windmill-labs/windmill | ⏳ PENDING | | | ||||
| | corteza | https://github.com/cortezaproject/corteza | ⏳ PENDING | | | ||||
| | mendersoftware | https://github.com/mendersoftware | ⏳ PENDING | | | ||||
| | security-awareness-training | https://github.com/security-companion/security-awareness-training | ⏳ PENDING | | | ||||
| | comply | https://github.com/strongdm/comply | ⏳ PENDING | | | ||||
| | policies | https://github.com/todogroup/policies | ⏳ PENDING | | | ||||
| | puter | https://github.com/HeyPuter/puter | ⏳ PENDING | | | ||||
|  | ||||
| ## Progress Summary | ||||
| - Total Applications: 51 | ||||
| - Completed: 0 (0%) | ||||
| - In Progress: 0 (0%) | ||||
| - Failed: 0 (0%) | ||||
| - Pending: 51 (100%) | ||||
|  | ||||
| ## Human Help Required | ||||
| None at the moment. | ||||
|  | ||||
| ## Last Updated | ||||
| Wednesday, October 29, 2025 | ||||
| @@ -1,15 +0,0 @@ | ||||
| # Please use conventional commit format: type(scope): description | ||||
| # Example: feat(auth): add jwt token expiration | ||||
| #  | ||||
| # Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert | ||||
| #  | ||||
| # Explain what and why in imperative mood: | ||||
| #  | ||||
| #  | ||||
| #  | ||||
| # Signed-off-by: Your Name <your.email@example.com> | ||||
| #  | ||||
| # ------------------------ >8 ------------------------ | ||||
| # Do not modify or remove the line above. | ||||
| # Everything below it will be ignored. | ||||
| diff --git a/... | ||||
							
								
								
									
										289
									
								
								CloudronStack/output/master-control-script.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										289
									
								
								CloudronStack/output/master-control-script.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Master Control Script for Cloudron Packaging | ||||
| # This script orchestrates the packaging of all applications from GitUrlList.txt | ||||
| # It runs three packaging projects in parallel and maintains status tracking | ||||
|  | ||||
| set -e  # Exit on any error | ||||
|  | ||||
| # Configuration | ||||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||
| OUTPUT_DIR="$SCRIPT_DIR/output" | ||||
| ARTIFACTS_DIR="$OUTPUT_DIR/CloudronPackages-Artifacts" | ||||
| WORKSPACES_DIR="$OUTPUT_DIR/CloudronPackages-Workspaces" | ||||
| STATUS_FILE="$SCRIPT_DIR/collab/STATUS.md" | ||||
| GIT_URL_LIST="$SCRIPT_DIR/collab/GitUrlList.txt" | ||||
| HUMAN_HELP_DIR="$WORKSPACES_DIR/human-help-required" | ||||
| MAX_RETRIES=5 | ||||
|  | ||||
| # Docker image prefix | ||||
| DOCKER_PREFIX="tsysdevstack-cloudron-buildtest-" | ||||
|  | ||||
| # Source the packaging functions | ||||
| source "$SCRIPT_DIR/package-functions.sh" | ||||
|  | ||||
| # Create necessary directories | ||||
| mkdir -p "$ARTIFACTS_DIR" "$WORKSPACES_DIR" "$HUMAN_HELP_DIR" | ||||
|  | ||||
| # Function to update status in STATUS.md | ||||
| update_status() { | ||||
|     local app_name=$1 | ||||
|     local new_status=$2 | ||||
|     local notes=${3:-""} | ||||
|      | ||||
|     # Escape special characters for sed | ||||
|     local escaped_app_name=$(echo "$app_name" | sed 's/[[\.*^$()+?{|]/\\&/g') | ||||
|     local escaped_status=$(echo "$new_status" | sed 's/[[\.*^$()+?{|]/\\&/g') | ||||
|     local escaped_notes=$(echo "$notes" | sed 's/[[\.*^$()+?{|]/\\&/g' | sed 's/&/&/g; s/</</g; s/>/>/g') | ||||
|      | ||||
|     # Update status in the file - find the line with the app name and update its status | ||||
|     sed -i "s/^| $escaped_app_name |.*|.*|.*$/| $app_name |.*| $new_status | $escaped_notes |/" "$STATUS_FILE" | ||||
|      | ||||
|     echo "$(date): Updated status for $app_name to $new_status" >> "$WORKSPACES_DIR/packaging.log" | ||||
| } | ||||
|  | ||||
| # Function to get the repository name from URL | ||||
| get_repo_name() { | ||||
|     local url=$1 | ||||
|     if [[ "$url" == *"github.com"* ]]; then | ||||
|         echo "${url##*/}" | sed 's/\.git$//' | ||||
|     elif [[ "$url" == *"gitlab.com"* ]]; then | ||||
|         echo "${url##*/}" | sed 's/\.git$//' | ||||
|     else | ||||
|         echo "${url##*/}" | sed 's/\.git$//' | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Function to extract username/repo from URL for GitHub | ||||
| get_username_repo() { | ||||
|     local url=$1 | ||||
|     if [[ "$url" == *"github.com"* ]]; then | ||||
|         # Extract username/repo from GitHub URL | ||||
|         echo "${url#*github.com/}" | sed 's/\.git$//' | ||||
|     elif [[ "$url" == *"gitlab.com"* ]]; then | ||||
|         # Extract username/repo from GitLab URL | ||||
|         echo "${url#*gitlab.com/}" | sed 's/\.git$//' | ||||
|     else | ||||
|         # For other URLs, just return the repo name | ||||
|         echo "$(get_repo_name "$url")" | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Function to run individual packaging script | ||||
| run_packaging_script() { | ||||
|     local url=$1 | ||||
|     local repo_name=$(get_repo_name "$url") | ||||
|     local username_repo=$(get_username_repo "$url") | ||||
|     local workspace_dir="$WORKSPACES_DIR/$repo_name" | ||||
|     local artifact_dir="$ARTIFACTS_DIR/$repo_name" | ||||
|     local packaging_script="$WORKSPACES_DIR/packaging-$repo_name.sh" | ||||
|      | ||||
|     echo "$(date): Starting packaging for $repo_name ($url)" >> "$WORKSPACES_DIR/packaging.log" | ||||
|      | ||||
|     # Update status to IN PROGRESS | ||||
|     update_status "$repo_name" "🔄 IN PROGRESS" "Packaging started" | ||||
|      | ||||
|     # Initialize workspace | ||||
|     mkdir -p "$workspace_dir" "$artifact_dir" | ||||
|      | ||||
|     # Clone repository | ||||
|     if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo")" ]; then | ||||
|         echo "Cloning $url to $workspace_dir/repo" | ||||
|         git clone "$url" "$workspace_dir/repo" | ||||
|     else | ||||
|         # Update repository | ||||
|         echo "Updating $url in $workspace_dir/repo" | ||||
|         (cd "$workspace_dir/repo" && git fetch && git reset --hard origin/main 2>/dev/null || git reset --hard origin/master 2>/dev/null || git pull) | ||||
|     fi | ||||
|      | ||||
|     # Attempt packaging with retries | ||||
|     local attempt=1 | ||||
|     local success=0 | ||||
|      | ||||
|     while [ $attempt -le $MAX_RETRIES ] && [ $success -eq 0 ]; do | ||||
|         echo "$(date): Attempt $attempt/$MAX_RETRIES for $repo_name" >> "$WORKSPACES_DIR/packaging.log" | ||||
|          | ||||
|         # Run the packaging process (this would call the specific packaging function) | ||||
|         if package_application "$repo_name" "$username_repo" "$workspace_dir" "$artifact_dir"; then | ||||
|             success=1 | ||||
|             update_status "$repo_name" "✅ COMPLETE" "Packaged successfully on attempt $attempt" | ||||
|             echo "$(date): Successfully packaged $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log" | ||||
|         else | ||||
|             echo "$(date): Failed to package $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log" | ||||
|             ((attempt++)) | ||||
|         fi | ||||
|     done | ||||
|      | ||||
|     if [ $success -eq 0 ]; then | ||||
|         # Mark as failed and create human help request | ||||
|         update_status "$repo_name" "🛑 FAILED" "Failed after $MAX_RETRIES attempts" | ||||
|         touch "$HUMAN_HELP_DIR/STATUS-HumanHelp-$repo_name" | ||||
|         echo "$(date): Marked $repo_name for human help after $MAX_RETRIES failed attempts" >> "$WORKSPACES_DIR/packaging.log" | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Function to package a specific application | ||||
| package_application() { | ||||
|     local repo_name=$1 | ||||
|     local username_repo=$2 | ||||
|     local workspace_dir=$3 | ||||
|     local artifact_dir=$4 | ||||
|      | ||||
|     local repo_path="$workspace_dir/repo" | ||||
|      | ||||
|     # Use the function library to detect and package the application | ||||
|     detect_and_package "$repo_name" "$repo_path" "$artifact_dir" | ||||
| } | ||||
|  | ||||
| # Function to create a Dockerfile based on the application type | ||||
| create_dockerfile() { | ||||
|     local repo_name=$1 | ||||
|     local repo_path=$2 | ||||
|      | ||||
|     # Detect application type and create appropriate Dockerfile | ||||
|     # This is a simplified approach - in reality, this would be much more complex | ||||
|      | ||||
|     if [ -f "$repo_path/package.json" ]; then | ||||
|         # Node.js application | ||||
|         cat > "$repo_path/Dockerfile" << EOF | ||||
| FROM node:18-alpine | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY package*.json ./ | ||||
| RUN npm install | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| EXPOSE 3000 | ||||
|  | ||||
| CMD ["npm", "start"] | ||||
| EOF | ||||
|     elif [ -f "$repo_path/requirements.txt" ]; then | ||||
|         # Python application | ||||
|         cat > "$repo_path/Dockerfile" << EOF | ||||
| FROM python:3.11-slim | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY requirements.txt . | ||||
| RUN pip install --no-cache-dir -r requirements.txt | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| EXPOSE 8000 | ||||
|  | ||||
| CMD ["python", "app.py"] | ||||
| EOF | ||||
|     elif [ -f "$repo_path/composer.json" ]; then | ||||
|         # PHP application | ||||
|         cat > "$repo_path/Dockerfile" << EOF | ||||
| FROM php:8.1-apache | ||||
|  | ||||
| RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli | ||||
|  | ||||
| COPY . /var/www/html/ | ||||
|  | ||||
| EXPOSE 80 | ||||
|  | ||||
| CMD ["apache2-foreground"] | ||||
| EOF | ||||
|     elif [ -f "$repo_path/Gemfile" ]; then | ||||
|         # Ruby application | ||||
|         cat > "$repo_path/Dockerfile" << EOF | ||||
| FROM ruby:3.0 | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY Gemfile Gemfile.lock ./ | ||||
| RUN bundle install | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| EXPOSE 3000 | ||||
|  | ||||
| CMD ["ruby", "app.rb"] | ||||
| EOF | ||||
|     else | ||||
|         # Default to a basic server | ||||
|         cat > "$repo_path/Dockerfile" << EOF | ||||
| FROM alpine:latest | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| RUN apk add --no-cache bash | ||||
|  | ||||
| EXPOSE 8080 | ||||
|  | ||||
| CMD ["sh", "-c", "while true; do sleep 30; done"] | ||||
| EOF | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Main function to process all applications | ||||
| main() { | ||||
|     echo "$(date): Starting Cloudron packaging process" >> "$WORKSPACES_DIR/packaging.log" | ||||
|      | ||||
|     # Read URLs from GitUrlList.txt | ||||
|     local urls=() | ||||
|     while IFS= read -r line; do | ||||
|         if [[ -n "$line" && ! "$line" =~ ^[[:space:]]*# ]]; then | ||||
|             urls+=("$line") | ||||
|         fi | ||||
|     done < "$GIT_URL_LIST" | ||||
|      | ||||
|     # Process applications in batches of 3 for parallel execution | ||||
|     local i=0 | ||||
|     local total=${#urls[@]} | ||||
|      | ||||
|     while [ $i -lt $total ]; do | ||||
|         # Process up to 3 applications in parallel | ||||
|         local end=$((i + 3)) | ||||
|         [ $end -gt $total ] && end=$total | ||||
|          | ||||
|         echo "$(date): Starting batch with applications $(printf '%s; ' "${urls[@]:i:3}")" >> "$WORKSPACES_DIR/packaging.log" | ||||
|          | ||||
|         for ((j = i; j < end; j++)); do | ||||
|             echo "$(date): Starting packaging for ${urls[$j]}" >> "$WORKSPACES_DIR/packaging.log" | ||||
|             run_packaging_script "${urls[$j]}" & | ||||
|         done | ||||
|          | ||||
|         # Wait for all background processes to complete | ||||
|         wait | ||||
|          | ||||
|         # Update i for the next batch | ||||
|         i=$end | ||||
|          | ||||
|         # Update progress summary in STATUS.md | ||||
|         local completed=$(grep -o "✅ COMPLETE" "$STATUS_FILE" | wc -l) | ||||
|         local failed=$(grep -o "🛑 FAILED" "$STATUS_FILE" | wc -l) | ||||
|         local in_progress=$(grep -o "🔄 IN PROGRESS" "$STATUS_FILE" | wc -l) | ||||
|         local pending=$((total - completed - failed - in_progress)) | ||||
|          | ||||
|         # Update summary section in STATUS.md | ||||
|         sed -i '/## Progress Summary/Q' "$STATUS_FILE" | ||||
|         cat >> "$STATUS_FILE" << EOF | ||||
| ## Progress Summary | ||||
| - Total Applications: $total | ||||
| - Completed: $completed ($(awk "BEGIN {printf \"%.0f\", $completed * 100 / $total}")%) | ||||
| - In Progress: $in_progress ($(awk "BEGIN {printf \"%.0f\", $in_progress * 100 / $total}")%) | ||||
| - Failed: $failed ($(awk "BEGIN {printf \"%.0f\", $failed * 100 / $total}")%) | ||||
| - Pending: $pending ($(awk "BEGIN {printf \"%.0f\", $pending * 100 / $total}")%) | ||||
|  | ||||
| ## Human Help Required | ||||
| $(ls -1 "$HUMAN_HELP_DIR" 2>/dev/null || echo "None at the moment.") | ||||
|  | ||||
| ## Last Updated | ||||
| $(date) | ||||
| EOF | ||||
|     done | ||||
|      | ||||
|     echo "$(date): Completed Cloudron packaging process" >> "$WORKSPACES_DIR/packaging.log" | ||||
| } | ||||
|  | ||||
| # Run the main function if script is executed directly | ||||
| if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then | ||||
|     main "$@" | ||||
| fi | ||||
							
								
								
									
										367
									
								
								CloudronStack/output/package-functions.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								CloudronStack/output/package-functions.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,367 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Function library for Cloudron packaging | ||||
| # Contains specific packaging functions for different application types | ||||
|  | ||||
| set -e  # Exit on any error | ||||
|  | ||||
| # Function to package generic Node.js application | ||||
| package_nodejs_app() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Create Cloudron manifest | ||||
|     cat > app.manifest << EOF | ||||
| { | ||||
|     "id": "com.$(echo "$app_name" | sed 's/[^a-zA-Z0-9]/./g').cloudron", | ||||
|     "title": "$app_name", | ||||
|     "version": "1.0.0", | ||||
|     "build": "1", | ||||
|     "description": "Cloudron package for $app_name", | ||||
|     "author": "Auto-generated", | ||||
|     "website": "https://github.com/$app_name", | ||||
|     "admin": false, | ||||
|     "tags": ["nodejs", "auto-generated"], | ||||
|     "logo": "https://github.com/fluidicon.png", | ||||
|     "documentation": "https://github.com/$app_name", | ||||
|     "changelog": "Initial packaging" | ||||
| } | ||||
| EOF | ||||
|      | ||||
|     # Create Dockerfile for Node.js | ||||
|     cat > Dockerfile << EOF | ||||
| FROM node:18-alpine | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY package*.json ./ | ||||
| RUN npm install --only=production | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| EXPOSE 3000 | ||||
|  | ||||
| CMD ["npm", "start"] | ||||
| EOF | ||||
|      | ||||
|     # Build Docker image | ||||
|     local docker_image="tsysdevstack-cloudron-buildtest-${app_name//[^a-zA-Z0-9]/-}:latest" | ||||
|     if ! docker build -t "$docker_image" .; then | ||||
|         echo "Failed to build Docker image for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Perform smoke test on the Docker image | ||||
|     if ! smoke_test_docker_image "$docker_image" "$app_name"; then | ||||
|         echo "Smoke test failed for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Save the Docker image as an artifact | ||||
|     docker save "$docker_image" | gzip > "$artifact_dir/${app_name//[^a-zA-Z0-9]/-}.tar.gz" | ||||
|     return 0 | ||||
| } | ||||
|  | ||||
| # Function to package generic Python application | ||||
| package_python_app() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Create Cloudron manifest | ||||
|     cat > app.manifest << EOF | ||||
| { | ||||
|     "id": "com.$(echo "$app_name" | sed 's/[^a-zA-Z0-9]/./g').cloudron", | ||||
|     "title": "$app_name", | ||||
|     "version": "1.0.0", | ||||
|     "build": "1", | ||||
|     "description": "Cloudron package for $app_name", | ||||
|     "author": "Auto-generated", | ||||
|     "website": "https://github.com/$app_name", | ||||
|     "admin": false, | ||||
|     "tags": ["python", "auto-generated"], | ||||
|     "logo": "https://github.com/fluidicon.png", | ||||
|     "documentation": "https://github.com/$app_name", | ||||
|     "changelog": "Initial packaging" | ||||
| } | ||||
| EOF | ||||
|      | ||||
|     # Create Dockerfile for Python | ||||
|     cat > Dockerfile << EOF | ||||
| FROM python:3.11-slim | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY requirements.txt . | ||||
| RUN pip install --no-cache-dir -r requirements.txt | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| EXPOSE 8000 | ||||
|  | ||||
| CMD ["python", "app.py"] | ||||
| EOF | ||||
|      | ||||
|     # Build Docker image | ||||
|     local docker_image="tsysdevstack-cloudron-buildtest-${app_name//[^a-zA-Z0-9]/-}:latest" | ||||
|     if ! docker build -t "$docker_image" .; then | ||||
|         echo "Failed to build Docker image for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Perform smoke test on the Docker image | ||||
|     if ! smoke_test_docker_image "$docker_image" "$app_name"; then | ||||
|         echo "Smoke test failed for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Save the Docker image as an artifact | ||||
|     docker save "$docker_image" | gzip > "$artifact_dir/${app_name//[^a-zA-Z0-9]/-}.tar.gz" | ||||
|     return 0 | ||||
| } | ||||
|  | ||||
| # Function to package generic PHP application | ||||
| package_php_app() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Create Cloudron manifest | ||||
|     cat > app.manifest << EOF | ||||
| { | ||||
|     "id": "com.$(echo "$app_name" | sed 's/[^a-zA-Z0-9]/./g').cloudron", | ||||
|     "title": "$app_name", | ||||
|     "version": "1.0.0", | ||||
|     "build": "1", | ||||
|     "description": "Cloudron package for $app_name", | ||||
|     "author": "Auto-generated", | ||||
|     "website": "https://github.com/$app_name", | ||||
|     "admin": false, | ||||
|     "tags": ["php", "auto-generated"], | ||||
|     "logo": "https://github.com/fluidicon.png", | ||||
|     "documentation": "https://github.com/$app_name", | ||||
|     "changelog": "Initial packaging" | ||||
| } | ||||
| EOF | ||||
|      | ||||
|     # Create Dockerfile for PHP | ||||
|     cat > Dockerfile << EOF | ||||
| FROM php:8.1-apache | ||||
|  | ||||
| RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli | ||||
|  | ||||
| COPY . /var/www/html/ | ||||
|  | ||||
| EXPOSE 80 | ||||
|  | ||||
| CMD ["apache2-foreground"] | ||||
| EOF | ||||
|      | ||||
|     # Build Docker image | ||||
|     local docker_image="tsysdevstack-cloudron-buildtest-${app_name//[^a-zA-Z0-9]/-}:latest" | ||||
|     if ! docker build -t "$docker_image" .; then | ||||
|         echo "Failed to build Docker image for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Perform smoke test on the Docker image | ||||
|     if ! smoke_test_docker_image "$docker_image" "$app_name"; then | ||||
|         echo "Smoke test failed for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Save the Docker image as an artifact | ||||
|     docker save "$docker_image" | gzip > "$artifact_dir/${app_name//[^a-zA-Z0-9]/-}.tar.gz" | ||||
|     return 0 | ||||
| } | ||||
|  | ||||
| # Function to package generic Go application | ||||
| package_go_app() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Create Cloudron manifest | ||||
|     cat > app.manifest << EOF | ||||
| { | ||||
|     "id": "com.$(echo "$app_name" | sed 's/[^a-zA-Z0-9]/./g').cloudron", | ||||
|     "title": "$app_name", | ||||
|     "version": "1.0.0", | ||||
|     "build": "1", | ||||
|     "description": "Cloudron package for $app_name", | ||||
|     "author": "Auto-generated", | ||||
|     "website": "https://github.com/$app_name", | ||||
|     "admin": false, | ||||
|     "tags": ["go", "auto-generated"], | ||||
|     "logo": "https://github.com/fluidicon.png", | ||||
|     "documentation": "https://github.com/$app_name", | ||||
|     "changelog": "Initial packaging" | ||||
| } | ||||
| EOF | ||||
|      | ||||
|     # Create Dockerfile for Go | ||||
|     cat > Dockerfile << EOF | ||||
| FROM golang:1.21-alpine AS builder | ||||
|  | ||||
| WORKDIR /app | ||||
| COPY . . | ||||
| RUN CGO_ENABLED=0 GOOS=linux go build -o myapp . | ||||
|  | ||||
| FROM alpine:latest | ||||
| RUN apk --no-cache add ca-certificates | ||||
| WORKDIR /root/ | ||||
| COPY --from=builder /app/myapp . | ||||
| EXPOSE 8080 | ||||
| CMD ["./myapp"] | ||||
| EOF | ||||
|      | ||||
|     # Build Docker image | ||||
|     local docker_image="tsysdevstack-cloudron-buildtest-${app_name//[^a-zA-Z0-9]/-}:latest" | ||||
|     if ! docker build -t "$docker_image" .; then | ||||
|         echo "Failed to build Docker image for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Perform smoke test on the Docker image | ||||
|     if ! smoke_test_docker_image "$docker_image" "$app_name"; then | ||||
|         echo "Smoke test failed for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Save the Docker image as an artifact | ||||
|     docker save "$docker_image" | gzip > "$artifact_dir/${app_name//[^a-zA-Z0-9]/-}.tar.gz" | ||||
|     return 0 | ||||
| } | ||||
|  | ||||
| # Function to perform smoke test on Docker images | ||||
| smoke_test_docker_image() { | ||||
|     local docker_image=$1 | ||||
|     local app_name=$2 | ||||
|      | ||||
|     echo "Performing smoke test on $docker_image for $app_name" | ||||
|      | ||||
|     # Run the container briefly to test if it starts correctly | ||||
|     local container_name="smoke-test-${app_name//[^a-zA-Z0-9]/-}-$(date +%s)" | ||||
|      | ||||
|     # Try to run the container and check if it starts without immediate failure | ||||
|     if docker run -d --name "$container_name" --health-cmd="curl -f http://localhost/ || exit 1" --health-interval=5s --health-timeout=3s --health-retries=3 "$docker_image"; then | ||||
|         # Wait a few seconds to see if the container stays running | ||||
|         sleep 10 | ||||
|          | ||||
|         # Check if the container is still running and healthy | ||||
|         if [ "$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null)" = "running" ]; then | ||||
|             echo "Smoke test passed for $app_name" | ||||
|             # Stop and remove the test container | ||||
|             docker stop "$container_name" > /dev/null 2>&1 | ||||
|             docker rm "$container_name" > /dev/null 2>&1 | ||||
|             return 0 | ||||
|         else | ||||
|             echo "Container for $app_name did not stay running during smoke test" | ||||
|             # Get logs for debugging | ||||
|             docker logs "$container_name" 2>&1 | head -20 | ||||
|             docker stop "$container_name" > /dev/null 2>&1 | ||||
|             docker rm "$container_name" > /dev/null 2>&1 | ||||
|             return 1 | ||||
|         fi | ||||
|     else | ||||
|         echo "Failed to start container for $app_name during smoke test" | ||||
|         docker rm "$container_name" > /dev/null 2>&1 | ||||
|         return 1 | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Generic function that detects application type and calls appropriate function | ||||
| detect_and_package() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Detect application type based on files | ||||
|     if [ -f "package.json" ]; then | ||||
|         echo "Detected Node.js application" | ||||
|         package_nodejs_app "$app_name" "$app_dir" "$artifact_dir" | ||||
|     elif [ -f "requirements.txt" ] || [ -f "setup.py" ]; then | ||||
|         echo "Detected Python application" | ||||
|         package_python_app "$app_name" "$app_dir" "$artifact_dir" | ||||
|     elif [ -f "composer.json" ]; then | ||||
|         echo "Detected PHP application" | ||||
|         package_php_app "$app_name" "$app_dir" "$artifact_dir" | ||||
|     elif [ -f "go.mod" ] || [ -f "*.go" ]; then | ||||
|         echo "Detected Go application" | ||||
|         package_go_app "$app_name" "$app_dir" "$artifact_dir" | ||||
|     else | ||||
|         # Default generic approach | ||||
|         echo "Application type not detected, using generic approach" | ||||
|         package_generic_app "$app_name" "$app_dir" "$artifact_dir" | ||||
|     fi | ||||
| } | ||||
|  | ||||
| # Generic packaging function for unknown application types | ||||
| package_generic_app() { | ||||
|     local app_name=$1 | ||||
|     local app_dir=$2 | ||||
|     local artifact_dir=$3 | ||||
|      | ||||
|     cd "$app_dir" | ||||
|      | ||||
|     # Create Cloudron manifest | ||||
|     cat > app.manifest << EOF | ||||
| { | ||||
|     "id": "com.$(echo "$app_name" | sed 's/[^a-zA-Z0-9]/./g').cloudron", | ||||
|     "title": "$app_name", | ||||
|     "version": "1.0.0", | ||||
|     "build": "1", | ||||
|     "description": "Cloudron package for $app_name", | ||||
|     "author": "Auto-generated", | ||||
|     "website": "https://github.com/$app_name", | ||||
|     "admin": false, | ||||
|     "tags": ["generic", "auto-generated"], | ||||
|     "logo": "https://github.com/fluidicon.png", | ||||
|     "documentation": "https://github.com/$app_name", | ||||
|     "changelog": "Initial packaging" | ||||
| } | ||||
| EOF | ||||
|      | ||||
|     # Create a basic Dockerfile | ||||
|     cat > Dockerfile << EOF | ||||
| FROM alpine:latest | ||||
|  | ||||
| WORKDIR /app | ||||
|  | ||||
| COPY . . | ||||
|  | ||||
| RUN apk add --no-cache bash curl tar | ||||
|  | ||||
| EXPOSE 8080 | ||||
|  | ||||
| CMD ["sh", "-c", "while true; do sleep 30; done"] | ||||
| EOF | ||||
|      | ||||
|     # Build Docker image | ||||
|     local docker_image="tsysdevstack-cloudron-buildtest-${app_name//[^a-zA-Z0-9]/-}:latest" | ||||
|     if ! docker build -t "$docker_image" .; then | ||||
|         echo "Failed to build Docker image for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Perform smoke test on the Docker image | ||||
|     if ! smoke_test_docker_image "$docker_image" "$app_name"; then | ||||
|         echo "Smoke test failed for $app_name" | ||||
|         return 1 | ||||
|     fi | ||||
|      | ||||
|     # Save the Docker image as an artifact | ||||
|     docker save "$docker_image" | gzip > "$artifact_dir/${app_name//[^a-zA-Z0-9]/-}.tar.gz" | ||||
|     return 0 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user