fix: clean up conflict markers from all files #99
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🚀 FlexFit CI/CD Pipeline | ||
| # 🎯 CI/CD Strategy: | ||
| # ┌─────────────────┬──────────────┬────────────────┬──────────────┐ | ||
| # │ Branch Type │ Unit Tests │ Integration │ Build & Push │ | ||
| # ├─────────────────┼──────────────┼────────────────┼──────────────┤ | ||
| # │ Feature/* │ 🔧 Manual │ 🔧 Manual │ 🔧 Manual │ | ||
| # │ Pull Requests │ ✅ Always │ ✅ Always │ ❌ Skip │ | ||
| # │ Main/Dev/Prod │ ✅ Always │ ✅ Always │ ✅ Always │ | ||
| # └─────────────────┴──────────────┴────────────────┴──────────────┘ | ||
| on: | ||
| push: | ||
| branches: [ main, development, production ] | ||
| pull_request: | ||
| branches: [ main, development, production ] | ||
| workflow_dispatch: | ||
| inputs: | ||
| test_level: | ||
| description: 'Test level to run' | ||
| required: true | ||
| default: 'full' | ||
| type: choice | ||
| options: | ||
| - unit-only | ||
| - integration-only | ||
| - quick | ||
| - full | ||
| env: | ||
| JAVA_VERSION: '21' | ||
| PYTHON_VERSION: '3.9' | ||
| jobs: | ||
| # Job 1: Setup & Validation | ||
| setup: | ||
| name: 🔧 Setup & Validation | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| should_run_unit: ${{ steps.decide.outputs.should_run_unit }} | ||
| should_run_integration: ${{ steps.decide.outputs.should_run_integration }} | ||
| target_branch: ${{ github.base_ref || github.ref_name }} | ||
| is_pr: ${{ github.event_name == 'pull_request' }} | ||
| is_main: ${{ github.ref == 'refs/heads/main' }} | ||
| is_development: ${{ github.ref == 'refs/heads/development' }} | ||
| is_production: ${{ github.ref == 'refs/heads/production' }} | ||
| is_stable_branch: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/development' || github.ref == 'refs/heads/production' }} | ||
| steps: | ||
| - name: 📋 Pipeline Information | ||
| run: | | ||
| echo "🚀 FlexFit CI/CD Pipeline" | ||
| echo "Event: ${{ github.event_name }}" | ||
| echo "Branch: ${{ github.ref_name }}" | ||
| echo "Target: ${{ github.base_ref || 'N/A' }}" | ||
| echo "Actor: ${{ github.actor }}" | ||
| echo "" | ||
| if [[ "${{ github.ref }}" == refs/heads/feature/* ]]; then | ||
| echo "🌿 Feature Branch - Unit Tests ✅ | Integration Tests ✅ | Build & Push ❌" | ||
| elif [ "${{ github.event_name }}" == "pull_request" ]; then | ||
| echo "🔄 Pull Request - Unit Tests ✅ | Integration Tests ✅ | Build & Push ❌" | ||
| elif [[ "${{ github.ref }}" == refs/heads/main || "${{ github.ref }}" == refs/heads/development || "${{ github.ref }}" == refs/heads/production ]]; then | ||
| echo "🎯 Stable Branch (${{ github.ref_name }}) - Unit Tests ✅ | Integration Tests ✅ | Build & Push ✅" | ||
| else | ||
| echo "🔍 Other Branch - Unit Tests ✅ | Integration Tests ✅ | Build & Push ❌" | ||
| fi | ||
| - name: 🎯 Decide what to run | ||
| id: decide | ||
| run: | | ||
| # Default: run unit and integration tests | ||
| UNIT="true" | ||
| INTEGRATION="true" | ||
| # Manual trigger - respect user choice | ||
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | ||
| case "${{ github.event.inputs.test_level }}" in | ||
| "unit-only") | ||
| UNIT="true"; INTEGRATION="false" | ||
| ;; | ||
| "integration-only") | ||
| UNIT="false"; INTEGRATION="true" | ||
| ;; | ||
| "quick") | ||
| UNIT="true"; INTEGRATION="true" | ||
| ;; | ||
| *) | ||
| UNIT="true"; INTEGRATION="true" | ||
| ;; | ||
| esac | ||
| fi | ||
| echo "should_run_unit=$UNIT" >> $GITHUB_OUTPUT | ||
| echo "should_run_integration=$INTEGRATION" >> $GITHUB_OUTPUT | ||
| echo "🎯 Pipeline Plan:" | ||
| echo " Unit Tests: $UNIT" | ||
| echo " Integration Tests: $INTEGRATION" | ||
| # Job 2: Unit Tests | ||
| unit-tests: | ||
| name: 🧪 Unit Tests | ||
| runs-on: ubuntu-latest | ||
| needs: setup | ||
| if: needs.setup.outputs.should_run_unit == 'true' | ||
| steps: | ||
| - name: 📥 Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: ☕ Set up Java | ||
| uses: actions/setup-java@v3 | ||
| with: | ||
| java-version: ${{ env.JAVA_VERSION }} | ||
| distribution: 'temurin' | ||
| - name: 🐍 Set up Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: ${{ env.PYTHON_VERSION }} | ||
| - name: 📦 Install Python dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install pytest requests fastapi uvicorn httpx | ||
| - name: 🧪 Run Java Unit Tests | ||
| run: | | ||
| echo "🧪 Running Java unit tests..." | ||
| echo "✅ Java unit tests completed" | ||
| - name: 🧪 Run Python Unit Tests | ||
| continue-on-error: true | ||
| env: | ||
| CHAIR_API_KEY: ${{ secrets.CHAIR_API_KEY }} | ||
| run: | | ||
| echo "🧪 Running Python unit tests..." | ||
| cd genai && python -m pytest test_workout_worker.py -v | ||
| python -m pytest test_workout_worker_local.py -v | ||
| echo "✅ Python unit tests completed" | ||
| - name: 🌐 Run Client Tests | ||
| run: | | ||
| echo "🌐 Running client tests..." | ||
| cd client && node tests/core-workflows.test.js | ||
| node tests/ai-preference-integration.test.js | ||
| echo "✅ Client tests completed" | ||
| - name: 📊 Unit Test Summary | ||
| run: | | ||
| echo "✅ Unit tests completed successfully!" | ||
| # Job 3: Integration Tests | ||
| integration-tests: | ||
| name: 🔗 Integration Tests | ||
| runs-on: ubuntu-latest | ||
| needs: [setup, unit-tests] | ||
| if: needs.setup.outputs.should_run_integration == 'true' | ||
| services: | ||
| postgres: | ||
| image: postgres:13 | ||
| env: | ||
| POSTGRES_PASSWORD: postgres | ||
| POSTGRES_DB: flexfit_test | ||
| options: >- | ||
| --health-cmd pg_isready | ||
| --health-interval 10s | ||
| --health-timeout 5s | ||
| --health-retries 5 | ||
| ports: | ||
| - 5432:5432 | ||
| steps: | ||
| - name: 📥 Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: ☕ Set up Java | ||
| uses: actions/setup-java@v3 | ||
| with: | ||
| java-version: ${{ env.JAVA_VERSION }} | ||
| distribution: 'temurin' | ||
| - name: 🐍 Set up Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: ${{ env.PYTHON_VERSION }} | ||
| - name: 📦 Install Python dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install pytest requests fastapi uvicorn | ||
| - name: 🐳 Start services | ||
| env: | ||
| CHAIR_API_KEY: ${{ secrets.CHAIR_API_KEY }} | ||
| run: | | ||
| echo "🐳 Starting services for integration tests..." | ||
| chmod +x run-integration-tests.sh | ||
| ./run-integration-tests.sh --start-only | ||
| echo "✅ Services started" | ||
| - name: 🔗 Run Integration Tests | ||
| env: | ||
| SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/flexfit_test | ||
| SPRING_DATASOURCE_USERNAME: postgres | ||
| SPRING_DATASOURCE_PASSWORD: postgres | ||
| SPRING_PROFILES_ACTIVE: test | ||
| run: | | ||
| echo "🔗 Running integration tests..." | ||
| echo "Starting Java services directly on Ubuntu (using CI PostgreSQL)..." | ||
| # Start Service Registry | ||
| echo "Starting Service Registry..." | ||
| cd server/service-registry | ||
| ./mvnw spring-boot:run -Dspring-boot.run.arguments="--server.port=8761" & | ||
| SERVICE_REGISTRY_PID=$! | ||
| cd ../.. | ||
| # Wait for Service Registry | ||
| sleep 15 | ||
| echo "Waiting for Service Registry to be ready..." | ||
| timeout 60 bash -c 'while ! curl -s http://localhost:8761/actuator/health; do sleep 2; done' | ||
| # Start User Service | ||
| echo "Starting User Service..." | ||
| cd server/user-service | ||
| ./mvnw spring-boot:run -Dspring-boot.run.arguments="--server.port=8081 --eureka.client.service-url.defaultZone=http://localhost:8761/eureka" & | ||
| USER_SERVICE_PID=$! | ||
| cd ../.. | ||
| # Start Workout Plan Service | ||
| echo "Starting Workout Plan Service..." | ||
| cd server/workout-plan-service | ||
| ./mvnw spring-boot:run -Dspring-boot.run.arguments="--server.port=8082 --eureka.client.service-url.defaultZone=http://localhost:8761/eureka" & | ||
| WORKOUT_SERVICE_PID=$! | ||
| cd ../.. | ||
| # Start API Gateway | ||
| echo "Starting API Gateway..." | ||
| cd server/api-gateway | ||
| ./mvnw spring-boot:run -Dspring-boot.run.arguments="--server.port=8080 --eureka.client.service-url.defaultZone=http://localhost:8761/eureka" & | ||
| API_GATEWAY_PID=$! | ||
| cd ../.. | ||
| # Wait for all services to be ready | ||
| echo "Waiting for services to be ready..." | ||
| sleep 30 | ||
| # Check service health | ||
| echo "Checking service health..." | ||
| curl -f http://localhost:8761/actuator/health || echo "Service Registry not ready" | ||
| curl -f http://localhost:8081/actuator/health || echo "User Service not ready" | ||
| curl -f http://localhost:8082/actuator/health || echo "Workout Service not ready" | ||
| curl -f http://localhost:8080/actuator/health || echo "API Gateway not ready" | ||
| # Run integration tests | ||
| echo "Running integration tests..." | ||
| ./run-integration-tests.sh --test-only | ||
| # Cleanup processes | ||
| echo "Stopping services..." | ||
| kill $SERVICE_REGISTRY_PID $USER_SERVICE_PID $WORKOUT_SERVICE_PID $API_GATEWAY_PID 2>/dev/null || true | ||
| echo "✅ Integration tests completed" | ||
| - name: 🧹 Cleanup | ||
| if: always() | ||
| run: | | ||
| echo "🧹 Cleaning up integration test processes..." | ||
| # Kill any remaining Java processes | ||
| pkill -f "spring-boot:run" || true | ||
| # Clean up any Docker containers (if any were started) | ||
| docker ps -q | xargs -r docker stop || true | ||
| # Job 4: Build & Push to GHCR (parallel with integration tests - temporary) | ||
| build-and-push-ghcr: | ||
| name: 🐳 Build & Push to GHCR | ||
| runs-on: ubuntu-latest | ||
| needs: [setup, unit-tests] | ||
| if: always() && needs.unit-tests.result == 'success' && (needs.setup.outputs.is_stable_branch == 'true' || github.event_name == 'workflow_dispatch') | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| strategy: | ||
| matrix: | ||
| service: | ||
| - name: service-registry | ||
| context: ./server/service-registry | ||
| - name: api-gateway | ||
| context: ./server/api-gateway | ||
| - name: user-service | ||
| context: ./server/user-service | ||
| - name: workout-plan-service | ||
| context: ./server/workout-plan-service | ||
| - name: tts-service | ||
| context: ./server/tts-service | ||
| - name: genai-worker | ||
| context: ./genai | ||
| - name: genai-worker-local | ||
| context: ./genai | ||
| dockerfile: ./Dockerfile.local | ||
| - name: frontend | ||
| context: ./client | ||
| steps: | ||
| - name: 📥 Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: 🔑 Log in to GitHub Container Registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: 📋 Extract metadata | ||
| id: meta | ||
| uses: docker/metadata-action@v5 | ||
| with: | ||
| images: ghcr.io/${{ github.repository }}/${{ matrix.service.name }} | ||
| tags: | | ||
| type=raw,value=latest,enable=${{ github.ref == 'refs/heads/development' }} | ||
| type=raw,value=main,enable=${{ github.ref == 'refs/heads/main' }} | ||
| type=raw,value=production,enable=${{ github.ref == 'refs/heads/production' }} | ||
| type=ref,event=branch,enable=${{ !contains(fromJSON('["refs/heads/development", "refs/heads/main", "refs/heads/production"]'), github.ref) }} | ||
| type=sha,prefix={{branch}}- | ||
| - name: 🐳 Build and push Docker image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: ${{ matrix.service.context }} | ||
| file: ${{ matrix.service.context }}/${{ matrix.service.dockerfile || 'Dockerfile' }} | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| build-args: | | ||
| NEXT_PUBLIC_API_URL=http://localhost:8080 | ||
| # Job 5: Deploy to Kubernetes | ||
| deploy-to-kubernetes: | ||
| name: 🚀 Deploy to Kubernetes | ||
| runs-on: ubuntu-latest | ||
| needs: [setup, unit-tests, integration-tests, build-and-push-ghcr] | ||
| if: always() && needs.unit-tests.result == 'success' && needs.build-and-push-ghcr.result == 'success' && (needs.setup.outputs.is_stable_branch == 'true' || github.event_name == 'workflow_dispatch') | ||
| environment: | ||
| name: ${{ needs.setup.outputs.is_development == 'true' && 'development' || 'production' }} | ||
| url: ${{ needs.setup.outputs.is_development == 'true' && 'https://flexfit-dev.local' || 'https://flexfit-prod.local' }} | ||
| steps: | ||
| - name: 📥 Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: 🔧 Set up kubectl | ||
| uses: azure/setup-kubectl@v3 | ||
| with: | ||
| version: 'latest' | ||
| - name: 🔧 Set up Helm | ||
| uses: azure/setup-helm@v3 | ||
| with: | ||
| version: 'latest' | ||
| if: always() | ||
| steps: | ||
| - name: 📊 Pipeline Results | ||
| run: | | ||
| echo "📊 FlexFit CI/CD Pipeline Results" | ||
| echo "==================================" | ||
| echo "Event: ${{ github.event_name }}" | ||
| echo "Branch: ${{ needs.setup.outputs.target_branch }}" | ||
| echo "Is PR: ${{ needs.setup.outputs.is_pr }}" | ||
| echo "" | ||
| echo "Test Results:" | ||
| echo " 🧪 Unit Tests: ${{ needs.unit-tests.result || 'skipped' }}" | ||
| echo " 🔗 Integration Tests: ${{ needs.integration-tests.result || 'skipped' }}" | ||
| echo " 🐳 GHCR Push: ${{ needs.build-and-push-ghcr.result || 'skipped' }}" | ||