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