- 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.
367 lines
10 KiB
Bash
367 lines
10 KiB
Bash
#!/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
|
|
} |