#!/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