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