519 lines
13 KiB
Bash
Executable File
519 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# gitea-deploy.sh - Gitea-specific deployment script
|
||
# Usage: ./gitea-deploy.sh [environment] [image-tag]
|
||
|
||
set -e # Exit on any error
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||
|
||
# Load environment variables from .env file if it exists
|
||
if [ -f "$PROJECT_DIR/.env" ]; then
|
||
export $(cat "$PROJECT_DIR/.env" | grep -v '^#' | grep -E '^[A-Z_]+=.*' | xargs)
|
||
fi
|
||
|
||
ENVIRONMENT=${1:-production}
|
||
IMAGE_TAG=${2:-latest}
|
||
REGISTRY=${GITEA_REGISTRY:-${CONTAINER_REGISTRY:-"ghcr.io"}}
|
||
IMAGE_NAME=${GITEA_REPOSITORY:-${CONTAINER_REPOSITORY:-"rxminder"}}
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
print_status() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
echo "🚀 Deploying RxMinder from Gitea to $ENVIRONMENT environment..."
|
||
|
||
# Check if running in Gitea Actions
|
||
if [ "$GITEA_ACTIONS" = "true" ]; then
|
||
print_status "Running in Gitea Actions environment"
|
||
|
||
# Load Gitea-specific environment variables
|
||
REGISTRY=${GITEA_SERVER_URL#https://}
|
||
IMAGE_NAME=${GITEA_REPOSITORY}
|
||
IMAGE_TAG=${GITEA_SHA:0:8}
|
||
|
||
print_status "Registry: $REGISTRY"
|
||
print_status "Image: $IMAGE_NAME:$IMAGE_TAG"
|
||
fi
|
||
|
||
# Check if .env file exists
|
||
if [ ! -f ".env" ]; then
|
||
print_warning ".env file not found, using defaults"
|
||
|
||
# Create minimal .env for Gitea deployment
|
||
cat > .env << EOF
|
||
COUCHDB_USER=admin
|
||
COUCHDB_PASSWORD=change-this-secure-password
|
||
VITE_COUCHDB_URL=http://couchdb:5984
|
||
VITE_COUCHDB_USER=admin
|
||
VITE_COUCHDB_PASSWORD=change-this-secure-password
|
||
APP_BASE_URL=http://localhost:8080
|
||
NODE_ENV=production
|
||
EOF
|
||
|
||
print_warning "Created default .env file - please update with your credentials"
|
||
fi
|
||
|
||
# Load environment variables
|
||
print_status "Loading environment variables from .env file..."
|
||
export $(cat .env | grep -v '^#' | xargs)
|
||
|
||
# Validate required environment variables
|
||
REQUIRED_VARS=("COUCHDB_USER" "COUCHDB_PASSWORD" "VITE_COUCHDB_URL")
|
||
for var in "${REQUIRED_VARS[@]}"; do
|
||
if [ -z "${!var}" ]; then
|
||
print_error "Required environment variable $var is not set"
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
print_success "Environment variables validated"
|
||
|
||
# Function to deploy via Docker Compose
|
||
deploy_compose() {
|
||
print_status "Deploying with Docker Compose..."
|
||
|
||
# Export image variables for compose
|
||
export IMAGE_TAG
|
||
export REGISTRY
|
||
export IMAGE_NAME
|
||
|
||
# Use the built image from registry if available
|
||
if [ "$GITEA_ACTIONS" = "true" ]; then
|
||
# Override the image in docker-compose
|
||
export FRONTEND_IMAGE="$REGISTRY/$IMAGE_NAME:$IMAGE_TAG"
|
||
print_status "Using Gitea Actions built image: $FRONTEND_IMAGE"
|
||
fi
|
||
|
||
# Pull the latest images
|
||
print_status "Pulling latest images..."
|
||
docker-compose -f docker/docker-compose.yaml pull || print_warning "Failed to pull some images"
|
||
|
||
# Start services
|
||
print_status "Starting services..."
|
||
docker-compose -f docker/docker-compose.yaml up -d
|
||
|
||
# Wait for services
|
||
print_status "Waiting for services to be ready..."
|
||
sleep 10
|
||
|
||
# Health check
|
||
print_status "Checking service health..."
|
||
if curl -f http://localhost:8080/health > /dev/null 2>&1; then
|
||
print_success "Frontend service is healthy"
|
||
else
|
||
print_warning "Frontend health check failed, checking logs..."
|
||
docker-compose -f docker/docker-compose.yaml logs frontend
|
||
fi
|
||
|
||
if curl -f http://localhost:5984/_up > /dev/null 2>&1; then
|
||
print_success "CouchDB service is healthy"
|
||
else
|
||
print_warning "CouchDB health check failed"
|
||
fi
|
||
}
|
||
|
||
# Function to deploy via Kubernetes
|
||
deploy_k8s() {
|
||
print_status "Deploying to Kubernetes..."
|
||
|
||
if ! command -v kubectl &> /dev/null; then
|
||
print_error "kubectl is not installed"
|
||
exit 1
|
||
fi
|
||
|
||
# Update image in k8s manifests
|
||
if [ "$GITEA_ACTIONS" = "true" ]; then
|
||
print_status "Updating Kubernetes manifests with new image..."
|
||
sed -i "s|image:.*rxminder.*|image: $REGISTRY/$IMAGE_NAME:$IMAGE_TAG|g" k8s/frontend-deployment.yaml
|
||
fi
|
||
|
||
# Apply manifests
|
||
print_status "Applying Kubernetes manifests..."
|
||
kubectl apply -f k8s/
|
||
|
||
# Wait for rollout
|
||
print_status "Waiting for deployment rollout..."
|
||
kubectl rollout status deployment/frontend-deployment
|
||
|
||
print_success "Kubernetes deployment completed"
|
||
}
|
||
|
||
# Main deployment logic
|
||
case "$ENVIRONMENT" in
|
||
"production"|"prod")
|
||
print_status "Deploying to production environment"
|
||
deploy_compose
|
||
;;
|
||
"kubernetes"|"k8s")
|
||
print_status "Deploying to Kubernetes environment"
|
||
deploy_k8s
|
||
;;
|
||
"staging")
|
||
print_status "Deploying to staging environment"
|
||
# Use staging-specific configurations
|
||
export APP_BASE_URL="http://staging.localhost:8080"
|
||
deploy_compose
|
||
;;
|
||
*)
|
||
print_error "Unknown environment: $ENVIRONMENT"
|
||
echo "Available environments: production, kubernetes, staging"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
print_success "Deployment to $ENVIRONMENT completed successfully! 🎉"
|
||
|
||
# Post-deployment tasks
|
||
print_status "Running post-deployment tasks..."
|
||
|
||
# Cleanup old images (optional)
|
||
if [ "$CLEANUP_OLD_IMAGES" = "true" ]; then
|
||
print_status "Cleaning up old Docker images..."
|
||
docker image prune -f --filter "until=72h" || print_warning "Image cleanup failed"
|
||
fi
|
||
|
||
# Send notification (if configured)
|
||
if [ -n "$DEPLOYMENT_WEBHOOK_URL" ]; then
|
||
print_status "Sending deployment notification..."
|
||
curl -X POST "$DEPLOYMENT_WEBHOOK_URL" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"text\":\"✅ RxMinder deployed to $ENVIRONMENT\", \"environment\":\"$ENVIRONMENT\", \"image\":\"$REGISTRY/$IMAGE_NAME:$IMAGE_TAG\"}" \
|
||
|| print_warning "Failed to send notification"
|
||
fi
|
||
|
||
print_success "All tasks completed! 🚀"
|
||
print_error "Docker is not installed"
|
||
exit 1
|
||
fi
|
||
|
||
# Check Docker Buildx
|
||
if ! docker buildx version >/dev/null 2>&1; then
|
||
print_error "Docker Buildx is not available"
|
||
exit 1
|
||
fi
|
||
|
||
# Check if in Gitea Actions environment
|
||
if [ "$GITEA_ACTIONS" = "true" ]; then
|
||
print_status "Running in Gitea Actions environment"
|
||
GITEA_REGISTRY=${GITEA_SERVER_URL#https://}
|
||
GITEA_REPOSITORY=${GITEA_REPOSITORY}
|
||
fi
|
||
|
||
print_success "All requirements met"
|
||
}
|
||
|
||
setup_buildx() {
|
||
print_status "Setting up Docker Buildx for Gitea..."
|
||
|
||
# Create builder if it doesn't exist
|
||
if ! docker buildx ls | grep -q "gitea-builder"; then
|
||
print_status "Creating Gitea buildx builder..."
|
||
docker buildx create \
|
||
--name gitea-builder \
|
||
--driver docker-container \
|
||
--bootstrap \
|
||
--use
|
||
print_success "Gitea builder created"
|
||
else
|
||
docker buildx use gitea-builder
|
||
print_success "Using existing Gitea builder"
|
||
fi
|
||
}
|
||
|
||
login_registry() {
|
||
print_status "Logging into Gitea registry..."
|
||
|
||
if [ -z "$GITEA_TOKEN" ]; then
|
||
print_error "GITEA_TOKEN environment variable is required"
|
||
print_status "Set it with: export GITEA_TOKEN=your_token"
|
||
exit 1
|
||
fi
|
||
|
||
# Login to Gitea registry
|
||
echo "$GITEA_TOKEN" | docker login "$GITEA_REGISTRY" -u "$GITEA_ACTOR" --password-stdin
|
||
print_success "Logged into Gitea registry"
|
||
}
|
||
|
||
build_local() {
|
||
print_status "Building for local development..."
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# Load environment variables
|
||
if [ -f ".env" ]; then
|
||
export $(cat .env | grep -v '^#' | xargs)
|
||
fi
|
||
|
||
# Build with Gitea bake file
|
||
docker buildx bake \
|
||
-f .gitea/gitea-bake.hcl \
|
||
--set="*.platform=linux/amd64" \
|
||
--load \
|
||
dev
|
||
|
||
print_success "Local build completed"
|
||
}
|
||
|
||
build_multiplatform() {
|
||
local tag=${1:-$DEFAULT_TAG}
|
||
print_status "Building multi-platform image with tag: $tag..."
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# Load environment variables
|
||
if [ -f ".env" ]; then
|
||
export $(cat .env | grep -v '^#' | xargs)
|
||
fi
|
||
|
||
# Export variables for bake
|
||
export TAG="$tag"
|
||
export GITEA_SHA=${GITEA_SHA:-$(git rev-parse --short HEAD 2>/dev/null || echo "dev")}
|
||
|
||
# Build with Gitea bake file
|
||
docker buildx bake \
|
||
-f .gitea/gitea-bake.hcl \
|
||
app-ci
|
||
|
||
print_success "Multi-platform build completed"
|
||
}
|
||
|
||
build_staging() {
|
||
print_status "Building staging image..."
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# Load environment variables
|
||
if [ -f ".env.staging" ]; then
|
||
export $(cat .env.staging | grep -v '^#' | xargs)
|
||
elif [ -f ".env" ]; then
|
||
export $(cat .env | grep -v '^#' | xargs)
|
||
fi
|
||
|
||
# Export variables for bake
|
||
export TAG="staging-$(date +%Y%m%d-%H%M%S)"
|
||
export GITEA_SHA=${GITEA_SHA:-$(git rev-parse --short HEAD 2>/dev/null || echo "staging")}
|
||
|
||
# Build staging target
|
||
docker buildx bake \
|
||
-f .gitea/gitea-bake.hcl \
|
||
staging
|
||
|
||
print_success "Staging build completed"
|
||
}
|
||
|
||
build_production() {
|
||
local tag=${1:-$DEFAULT_TAG}
|
||
print_status "Building production image with tag: $tag..."
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# Load production environment variables
|
||
if [ -f ".env.production" ]; then
|
||
export $(cat .env.production | grep -v '^#' | xargs)
|
||
elif [ -f ".env" ]; then
|
||
export $(cat .env | grep -v '^#' | xargs)
|
||
fi
|
||
|
||
# Export variables for bake
|
||
export TAG="$tag"
|
||
export GITEA_SHA=${GITEA_SHA:-$(git rev-parse --short HEAD 2>/dev/null || echo "prod")}
|
||
|
||
# Build production target with full attestations
|
||
docker buildx bake \
|
||
-f .gitea/gitea-bake.hcl \
|
||
prod
|
||
|
||
print_success "Production build completed"
|
||
}
|
||
|
||
test_local() {
|
||
print_status "Running tests locally..."
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
# Install dependencies if needed
|
||
if [ ! -d "node_modules" ]; then
|
||
print_status "Installing dependencies..."
|
||
bun install --frozen-lockfile
|
||
fi
|
||
|
||
# Run linting
|
||
print_status "Running linter..."
|
||
bun run lint
|
||
|
||
# Run type checking
|
||
print_status "Running type checker..."
|
||
bun run type-check
|
||
|
||
# Run tests
|
||
print_status "Running tests..."
|
||
bun run test
|
||
|
||
print_success "All tests passed"
|
||
}
|
||
|
||
deploy() {
|
||
local environment=${1:-production}
|
||
local tag=${2:-latest}
|
||
|
||
print_status "Deploying to $environment with tag $tag..."
|
||
|
||
# Use the gitea-deploy script
|
||
"$SCRIPT_DIR/gitea-deploy.sh" "$environment" "$tag"
|
||
}
|
||
|
||
cleanup() {
|
||
print_status "Cleaning up Gitea builder and images..."
|
||
|
||
# Remove builder
|
||
if docker buildx ls | grep -q "gitea-builder"; then
|
||
docker buildx rm gitea-builder
|
||
print_success "Gitea builder removed"
|
||
fi
|
||
|
||
# Clean up old images (keep last 3 tags)
|
||
print_status "Cleaning up old images..."
|
||
docker image prune -f --filter "until=72h" || print_warning "Image cleanup failed"
|
||
|
||
print_success "Cleanup completed"
|
||
}
|
||
|
||
show_status() {
|
||
print_status "Gitea CI/CD Status"
|
||
echo
|
||
|
||
# Check environment
|
||
if [ "$GITEA_ACTIONS" = "true" ]; then
|
||
echo "🏃 Running in Gitea Actions"
|
||
echo "📦 Registry: $GITEA_REGISTRY"
|
||
echo "📋 Repository: $GITEA_REPOSITORY"
|
||
echo "🏷️ SHA: ${GITEA_SHA:-unknown}"
|
||
echo "🌿 Branch: ${GITEA_REF_NAME:-unknown}"
|
||
else
|
||
echo "💻 Running locally"
|
||
echo "📦 Registry: $GITEA_REGISTRY"
|
||
echo "📋 Repository: $GITEA_REPOSITORY"
|
||
fi
|
||
|
||
echo
|
||
|
||
# Check Docker and buildx
|
||
echo "🐳 Docker version: $(docker --version)"
|
||
echo "🔧 Buildx version: $(docker buildx version)"
|
||
|
||
# Check builders
|
||
echo
|
||
echo "🏗️ Available builders:"
|
||
docker buildx ls
|
||
}
|
||
|
||
show_help() {
|
||
cat << EOF
|
||
Gitea CI/CD Helper for RxMinder
|
||
|
||
Usage: $0 [command] [options]
|
||
|
||
Commands:
|
||
setup - Setup buildx builder for Gitea
|
||
login - Login to Gitea registry
|
||
build-local - Build for local development
|
||
build-multi [tag] - Build multi-platform image
|
||
build-staging - Build staging image
|
||
build-prod [tag] - Build production image
|
||
test - Run tests locally
|
||
deploy [env] [tag] - Deploy to environment
|
||
cleanup - Cleanup builders and images
|
||
status - Show CI/CD status
|
||
help - Show this help
|
||
|
||
Examples:
|
||
$0 setup
|
||
$0 build-local
|
||
$0 build-multi v1.2.3
|
||
$0 build-staging
|
||
$0 build-prod v1.2.3
|
||
$0 test
|
||
$0 deploy production v1.2.3
|
||
$0 deploy staging
|
||
$0 status
|
||
|
||
Environment Variables:
|
||
GITEA_REGISTRY - Gitea registry URL (default: gitea.example.com)
|
||
GITEA_REPOSITORY - Repository name (default: user/rxminder)
|
||
GITEA_TOKEN - Gitea access token (required for registry)
|
||
GITEA_ACTOR - Gitea username (for registry login)
|
||
|
||
EOF
|
||
}
|
||
|
||
# Main command handling
|
||
case "${1:-help}" in
|
||
"setup")
|
||
check_requirements
|
||
setup_buildx
|
||
;;
|
||
"login")
|
||
check_requirements
|
||
login_registry
|
||
;;
|
||
"build-local")
|
||
check_requirements
|
||
setup_buildx
|
||
build_local
|
||
;;
|
||
"build-multi")
|
||
check_requirements
|
||
setup_buildx
|
||
login_registry
|
||
build_multiplatform "$2"
|
||
;;
|
||
"build-staging")
|
||
check_requirements
|
||
setup_buildx
|
||
login_registry
|
||
build_staging
|
||
;;
|
||
"build-prod")
|
||
check_requirements
|
||
setup_buildx
|
||
login_registry
|
||
build_production "$2"
|
||
;;
|
||
"test")
|
||
test_local
|
||
;;
|
||
"deploy")
|
||
deploy "$2" "$3"
|
||
;;
|
||
"cleanup")
|
||
cleanup
|
||
;;
|
||
"status")
|
||
show_status
|
||
;;
|
||
"help"|*)
|
||
show_help
|
||
;;
|
||
esac
|