diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml new file mode 100644 index 0000000..2865f4b --- /dev/null +++ b/.github/workflows/deploy-backend.yml @@ -0,0 +1,76 @@ +name: Deploy to Elastic Beanstalk + +on: + push: + branches: + - main + paths: + - 'server/**' + workflow_dispatch: # Allow manual trigger + +jobs: + deploy: + runs-on: ubuntu-latest + name: Deploy Backend to AWS Elastic Beanstalk + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build Spring Boot application + run: | + cd server + ./mvnw clean package -DskipTests + + - name: Verify build output + run: | + cd server + ls -la target/ + if [ ! -f "target/relational-data-access-complete-0.0.1-SNAPSHOT.jar" ]; then + echo "Build failed - JAR file not found!" + exit 1 + fi + + - name: Prepare deployment package + run: | + cd server + mkdir -p deploy-package + cp target/relational-data-access-complete-0.0.1-SNAPSHOT.jar deploy-package/ + cp deploy/Procfile deploy-package/ + cp -r deploy/.ebextensions deploy-package/ + + - name: Create deployment zip + run: | + cd server/deploy-package + zip -r ../deploy-${{ github.sha }}.zip . + + - name: Deploy to Elastic Beanstalk + uses: einaregilsson/beanstalk-deploy@v22 + with: + aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + application_name: customer-management-api # Replace with your EB app name + environment_name: customer-management-api-env # Replace with your EB env name + region: eu-north-1 # Replace with your AWS region + version_label: ${{ github.sha }} + deployment_package: server/deploy-${{ github.sha }}.zip + + - name: Upload deployment artifact + uses: actions/upload-artifact@v4 + if: always() + with: + name: deployment-package-${{ github.sha }} + path: server/deploy-${{ github.sha }}.zip \ No newline at end of file diff --git a/server/DEPLOYMENT.md b/server/DEPLOYMENT.md new file mode 100644 index 0000000..d83f448 --- /dev/null +++ b/server/DEPLOYMENT.md @@ -0,0 +1,198 @@ +# 🚀 Deployment Guide - Customer Management API + +This guide covers multiple deployment methods for the Spring Boot backend to AWS Elastic Beanstalk. + +## 📋 Prerequisites + +### Required Tools +- **Java 17+**: `java -version` +- **Maven**: Already included via `./mvnw` +- **AWS CLI** (for CLI deployment): [Install Guide](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) +- **AWS Account** with Elastic Beanstalk access + +### AWS Setup +1. **Create Elastic Beanstalk Application**: + ```bash + # Via AWS Console or CLI + aws elasticbeanstalk create-application \ + --application-name customer-management-api \ + --description "Customer Management REST API" + ``` + +2. **Create Environment**: + ```bash + aws elasticbeanstalk create-environment \ + --application-name customer-management-api \ + --environment-name customer-management-api-env \ + --platform-arn "arn:aws:elasticbeanstalk:eu-north-1::platform/Java 17 running on 64bit Amazon Linux 2/3.x.x" + ``` + +## 🎯 Deployment Methods + +### Method 1: Manual Build & Deploy (Beginner Friendly) + +**Step 1**: Build the deployment package +```bash +cd server +./build-and-deploy.sh +``` + +**Step 2**: Upload via AWS Console +1. Go to [AWS Elastic Beanstalk Console](https://console.aws.amazon.com/elasticbeanstalk/) +2. Select your application → Environment +3. Click "Upload and Deploy" +4. Upload the generated zip file from `deploy/deploy-YYYYMMDD-HHMMSS.zip` +5. Click "Deploy" + +### Method 2: AWS CLI Deployment (Recommended for Development) + +**Prerequisites**: +```bash +# Install AWS CLI +aws --version + +# Configure credentials +aws configure +``` + +**Deploy**: +```bash +cd server +./deploy-aws-cli.sh [environment-name] + +# Example +./deploy-aws-cli.sh customer-management-api-env +``` + +### Method 3: GitHub Actions CI/CD (Recommended for Production) + +**Step 1**: Set up GitHub Secrets +Go to your repository → Settings → Secrets and variables → Actions + +Add these secrets: +- `AWS_ACCESS_KEY_ID`: Your AWS access key +- `AWS_SECRET_ACCESS_KEY`: Your AWS secret key + +**Step 2**: Update workflow configuration +Edit `.github/workflows/deploy-backend.yml`: +```yaml +application_name: your-eb-application-name +environment_name: your-eb-environment-name +region: your-aws-region +``` + +**Step 3**: Deploy +Push changes to `main` branch: +```bash +git add . +git commit -m "Deploy: Update backend" +git push origin main +``` + +## 🔧 Configuration + +### Environment Variables (Set in AWS EB Console) + +**Database Configuration**: +``` +DB_HOST=your-rds-endpoint.amazonaws.com +DB_PORT=5432 +DB_NAME=customerdb +DB_USERNAME=your-username +DB_PASSWORD=your-secure-password +``` + +**CORS Configuration**: +``` +CORS_ALLOWED_ORIGINS=https://main.d123456789.amplifyapp.com,https://your-frontend-domain.com +``` + +**Application Settings**: +``` +SPRING_PROFILES_ACTIVE=production +JPA_DDL_AUTO=validate +LOG_LEVEL=INFO +``` + +## 🏥 Health Checks + +Elastic Beanstalk will use these endpoints: +- **Health Check**: `/api/health` +- **Ping Test**: `/api/ping` + +## 📊 Monitoring + +### CloudWatch Logs +Logs are automatically streamed to CloudWatch: +```bash +# View logs via CLI +aws logs describe-log-groups --log-group-name-prefix "/aws/elasticbeanstalk" +``` + +### Application Metrics +- **Health Dashboard**: AWS EB Console → Environment Health +- **Application Logs**: AWS EB Console → Logs +- **Monitoring**: CloudWatch metrics for requests, latency, errors + +## 🚨 Troubleshooting + +### Common Issues + +**1. Health Check Failures** +```bash +# Check if health endpoint responds +curl https://your-app-url.elasticbeanstalk.com/api/health +``` + +**2. Database Connection Issues** +- Verify RDS security groups allow EB connections +- Check environment variables are set correctly +- Ensure database exists and credentials are valid + +**3. CORS Issues** +- Update `CORS_ALLOWED_ORIGINS` with your frontend URL +- Verify frontend is using correct backend URL + +### Debugging Commands +```bash +# Check environment status +aws elasticbeanstalk describe-environments \ + --application-name customer-management-api + +# Download logs +aws elasticbeanstalk request-environment-info \ + --environment-name customer-management-api-env \ + --info-type tail + +# View recent events +aws elasticbeanstalk describe-events \ + --environment-name customer-management-api-env +``` + +## 🔄 Rollback + +If deployment fails: +```bash +# List previous versions +aws elasticbeanstalk describe-application-versions \ + --application-name customer-management-api + +# Rollback to previous version +aws elasticbeanstalk update-environment \ + --environment-name customer-management-api-env \ + --version-label previous-version-label +``` + +## 🎯 Best Practices + +1. **Test Locally First**: Always test with `./mvnw spring-boot:run` +2. **Database Migrations**: Use `validate` in production, `update` only in development +3. **Environment Variables**: Never commit secrets to git +4. **Monitoring**: Set up CloudWatch alarms for error rates +5. **Blue/Green Deployments**: Use EB's deployment policies for zero-downtime deploys + +## 🔗 Useful Links + +- [AWS EB Java Guide](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-se-platform.html) +- [Spring Boot EB Guide](https://spring.io/guides/gs/spring-boot-docker/) +- [EB CLI Documentation](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3.html) \ No newline at end of file diff --git a/server/build-and-deploy.sh b/server/build-and-deploy.sh new file mode 100755 index 0000000..a9b4ba0 --- /dev/null +++ b/server/build-and-deploy.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Build and Deploy Script for Elastic Beanstalk +# Usage: ./build-and-deploy.sh + +set -e # Exit on any error + +echo "🏗️ Building Spring Boot Application..." + +# Clean and build the application +echo "Cleaning previous builds..." +./mvnw clean + +echo "Building JAR file..." +./mvnw package -DskipTests + +# Check if build was successful +if [ ! -f "target/relational-data-access-complete-0.0.1-SNAPSHOT.jar" ]; then + echo "❌ Build failed - JAR file not found!" + exit 1 +fi + +echo "✅ Build successful!" + +# Prepare deployment directory +echo "📦 Preparing deployment package..." + +# Clean deploy directory +rm -rf deploy/temp +mkdir -p deploy/temp + +# Copy JAR file to deploy directory +cp target/relational-data-access-complete-0.0.1-SNAPSHOT.jar deploy/temp/ + +# Copy Procfile and .ebextensions +cp deploy/Procfile deploy/temp/ +cp -r deploy/.ebextensions deploy/temp/ + +# Create deployment zip +echo "Creating deployment zip..." +cd deploy/temp +zip -r ../deploy-$(date +%Y%m%d-%H%M%S).zip . +cd ../.. + +# Clean up temp directory +rm -rf deploy/temp + +echo "✅ Deployment package created: deploy/deploy-$(date +%Y%m%d-%H%M%S).zip" +echo "" +echo "📋 Next steps:" +echo "1. Go to AWS Elastic Beanstalk Console" +echo "2. Select your application environment" +echo "3. Click 'Upload and Deploy'" +echo "4. Upload the zip file: deploy/deploy-$(date +%Y%m%d-%H%M%S).zip" +echo "5. Deploy!" \ No newline at end of file diff --git a/server/deploy-aws-cli.sh b/server/deploy-aws-cli.sh new file mode 100755 index 0000000..b014a9a --- /dev/null +++ b/server/deploy-aws-cli.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# AWS CLI Deployment Script for Elastic Beanstalk +# Prerequisites: AWS CLI installed and configured +# Usage: ./deploy-aws-cli.sh [environment-name] + +set -e + +# Configuration - Update these values +APPLICATION_NAME="customer-management-api" +DEFAULT_ENVIRONMENT="customer-management-api-env" +REGION="eu-north-1" + +# Use provided environment name or default +ENVIRONMENT_NAME=${1:-$DEFAULT_ENVIRONMENT} + +echo "🚀 Deploying to Elastic Beanstalk..." +echo "Application: $APPLICATION_NAME" +echo "Environment: $ENVIRONMENT_NAME" +echo "Region: $REGION" +echo "" + +# Check if AWS CLI is installed and configured +if ! command -v aws &> /dev/null; then + echo "❌ AWS CLI is not installed. Please install it first:" + echo " https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" + exit 1 +fi + +# Verify AWS credentials +if ! aws sts get-caller-identity &> /dev/null; then + echo "❌ AWS credentials not configured. Run 'aws configure' first." + exit 1 +fi + +# Build the application +echo "🏗️ Building application..." +./mvnw clean package -DskipTests + +# Prepare deployment package +echo "📦 Creating deployment package..." +TIMESTAMP=$(date +%Y%m%d-%H%M%S) +VERSION_LABEL="v$TIMESTAMP-$(git rev-parse --short HEAD 2>/dev/null || echo 'local')" +DEPLOY_ZIP="deploy-$VERSION_LABEL.zip" + +mkdir -p deploy/temp +cp target/relational-data-access-complete-0.0.1-SNAPSHOT.jar deploy/temp/ +cp deploy/Procfile deploy/temp/ +cp -r deploy/.ebextensions deploy/temp/ + +cd deploy/temp +zip -r "../$DEPLOY_ZIP" . +cd ../.. +rm -rf deploy/temp + +echo "✅ Created deployment package: deploy/$DEPLOY_ZIP" + +# Upload to S3 (Elastic Beanstalk requirement) +echo "⬆️ Uploading to S3..." +S3_BUCKET="elasticbeanstalk-$REGION-$(aws sts get-caller-identity --query Account --output text)" +S3_KEY="$APPLICATION_NAME/$DEPLOY_ZIP" + +aws s3 cp "deploy/$DEPLOY_ZIP" "s3://$S3_BUCKET/$S3_KEY" --region $REGION + +# Create application version +echo "📝 Creating application version..." +aws elasticbeanstalk create-application-version \ + --application-name "$APPLICATION_NAME" \ + --version-label "$VERSION_LABEL" \ + --source-bundle "S3Bucket=$S3_BUCKET,S3Key=$S3_KEY" \ + --region $REGION + +# Deploy to environment +echo "🚀 Deploying to environment..." +aws elasticbeanstalk update-environment \ + --application-name "$APPLICATION_NAME" \ + --environment-name "$ENVIRONMENT_NAME" \ + --version-label "$VERSION_LABEL" \ + --region $REGION + +echo "" +echo "✅ Deployment initiated!" +echo "📊 Monitor deployment status:" +echo " aws elasticbeanstalk describe-environments --application-name $APPLICATION_NAME --environment-names $ENVIRONMENT_NAME --region $REGION" +echo "" +echo "🌐 Environment URL will be available once deployment completes." + +# Wait for deployment to complete (optional) +read -p "🔄 Wait for deployment to complete? (y/N): " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "⏳ Waiting for deployment..." + aws elasticbeanstalk wait environment-updated \ + --application-name "$APPLICATION_NAME" \ + --environment-names "$ENVIRONMENT_NAME" \ + --region $REGION + + # Get environment info + ENV_INFO=$(aws elasticbeanstalk describe-environments \ + --application-name "$APPLICATION_NAME" \ + --environment-names "$ENVIRONMENT_NAME" \ + --region $REGION \ + --query 'Environments[0].{Health:Health,Status:Status,URL:CNAME}' \ + --output table) + + echo "🎉 Deployment completed!" + echo "$ENV_INFO" +fi \ No newline at end of file diff --git a/server/deploy/.ebextensions/app-config.config b/server/deploy/.ebextensions/app-config.config index f9c6c01..bf9da2a 100644 --- a/server/deploy/.ebextensions/app-config.config +++ b/server/deploy/.ebextensions/app-config.config @@ -1,77 +1,39 @@ -option_settings:option_settings: - - aws:elasticbeanstalk:application:environment: aws:elasticbeanstalk:application:environment: - - # Spring Boot configuration # Spring Boot configuration - - SPRING_PROFILES_ACTIVE: production SPRING_PROFILES_ACTIVE: production - - - - # Port configuration for Elastic Beanstalk # Port configuration for Elastic Beanstalk - - PORT: 5000 PORT: 5000 - - - - # AWS RDS Database configuration (set these in EB Console) # AWS RDS Database configuration (set these in EB Console) - - # RDS_HOSTNAME: your-rds-endpoint.amazonaws.com # RDS_HOSTNAME: your-rds-endpoint.amazonaws.com - - # RDS_PORT: 5432 # RDS_PORT: 5432 - - # RDS_DB_NAME: customerdb # RDS_DB_NAME: customerdb - - # RDS_USERNAME: your-username # RDS_USERNAME: your-username - - # RDS_PASSWORD: your-password # RDS_PASSWORD: your-password - - - - # CORS configuration - set FRONTEND_URL in EB Console # CORS configuration - set FRONTEND_URL in EB Console - - # CORS_ALLOWED_ORIGINS: https://main.d123456789.amplifyapp.com # CORS_ALLOWED_ORIGINS: https://main.d123456789.amplifyapp.com - - - - # Application configuration # Application configuration - - JPA_DDL_AUTO: validate JPA_DDL_AUTO: validate - - JPA_SHOW_SQL: false JPA_SHOW_SQL: false - - LOG_LEVEL: INFO LOG_LEVEL: INFO - - SPRING_LOG_LEVEL: INFO SPRING_LOG_LEVEL: INFO - - - - aws:elasticbeanstalk:environment:process:default: aws:elasticbeanstalk:environment:process:default: - - Port: '5000' Port: '5000' - - Protocol: HTTP Protocol: HTTP - - HealthCheckPath: /api/health HealthCheckPath: /api/health - - HealthCheckTimeout: 15 HealthCheckTimeout: 15 - - HealthyThresholdCount: 3 HealthyThresholdCount: 3 - - UnhealthyThresholdCount: 5 UnhealthyThresholdCount: 5 - - - - aws:elasticbeanstalk:healthreporting:system: aws:elasticbeanstalk:healthreporting:system: - - SystemType: enhanced SystemType: enhanced - - - - aws:elasticbeanstalk:cloudwatch:logs: aws:elasticbeanstalk:cloudwatch:logs: - - StreamLogs: true StreamLogs: true - - DeleteOnTerminate: false DeleteOnTerminate: false - - RetentionInDays: 7 RetentionInDays: 7 \ No newline at end of file +option_settings: + aws:elasticbeanstalk:application:environment: + # Spring Boot configuration + SPRING_PROFILES_ACTIVE: production + + # Port configuration for Elastic Beanstalk + PORT: 5000 + + # AWS RDS Database configuration (set these in EB Console) + # RDS_HOSTNAME: your-rds-endpoint.amazonaws.com + # RDS_PORT: 5432 + # RDS_DB_NAME: customerdb + # RDS_USERNAME: your-username + # RDS_PASSWORD: your-password + + # CORS configuration - set FRONTEND_URL in EB Console + # CORS_ALLOWED_ORIGINS: https://main.d123456789.amplifyapp.com + + # Application configuration + JPA_DDL_AUTO: validate + JPA_SHOW_SQL: false + LOG_LEVEL: INFO + SPRING_LOG_LEVEL: INFO + + aws:elasticbeanstalk:environment:process:default: + Port: '5000' + Protocol: HTTP + HealthCheckPath: /api/health + HealthCheckTimeout: 15 + HealthyThresholdCount: 3 + UnhealthyThresholdCount: 5 + + aws:elasticbeanstalk:healthreporting:system: + SystemType: enhanced + + aws:elasticbeanstalk:cloudwatch:logs: + StreamLogs: true + DeleteOnTerminate: false + RetentionInDays: 7 \ No newline at end of file