name: CI/CD Pipeline (Fixed & Reliable) on: push: branches: [ production ] env: NODE_VERSION: '20' DOCKER_IMAGE: portfolio-app CONTAINER_NAME: portfolio-app jobs: production: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run linting run: npm run lint - name: Run tests run: npm run test - name: Build application run: npm run build - name: Run security scan run: | echo "๐Ÿ” Running npm audit..." npm audit --audit-level=high || echo "โš ๏ธ Some vulnerabilities found, but continuing..." - name: Build Docker image run: | echo "๐Ÿ—๏ธ Building Docker image..." docker build -t ${{ env.DOCKER_IMAGE }}:latest . docker tag ${{ env.DOCKER_IMAGE }}:latest ${{ env.DOCKER_IMAGE }}:$(date +%Y%m%d-%H%M%S) echo "โœ… Docker image built successfully" - name: Deploy with fixed configuration run: | echo "๐Ÿš€ Deploying with fixed configuration..." # Export environment variables with defaults export NODE_ENV="${NODE_ENV:-production}" export LOG_LEVEL="${LOG_LEVEL:-info}" export NEXT_PUBLIC_BASE_URL="${NEXT_PUBLIC_BASE_URL:-https://dk0.dev}" export NEXT_PUBLIC_UMAMI_URL="${NEXT_PUBLIC_UMAMI_URL:-https://analytics.dk0.dev}" export NEXT_PUBLIC_UMAMI_WEBSITE_ID="${NEXT_PUBLIC_UMAMI_WEBSITE_ID:-b3665829-927a-4ada-b9bb-fcf24171061e}" export MY_EMAIL="${MY_EMAIL:-contact@dk0.dev}" export MY_INFO_EMAIL="${MY_INFO_EMAIL:-info@dk0.dev}" export MY_PASSWORD="${MY_PASSWORD:-your-email-password}" export MY_INFO_PASSWORD="${MY_INFO_PASSWORD:-your-info-email-password}" export ADMIN_BASIC_AUTH="${ADMIN_BASIC_AUTH:-admin:your_secure_password_here}" echo "๐Ÿ“ Environment variables configured:" echo " - NODE_ENV: ${NODE_ENV}" echo " - NEXT_PUBLIC_BASE_URL: ${NEXT_PUBLIC_BASE_URL}" echo " - MY_EMAIL: ${MY_EMAIL}" echo " - MY_INFO_EMAIL: ${MY_INFO_EMAIL}" echo " - MY_PASSWORD: [SET]" echo " - MY_INFO_PASSWORD: [SET]" echo " - ADMIN_BASIC_AUTH: [SET]" echo " - LOG_LEVEL: ${LOG_LEVEL}" # Stop old containers echo "๐Ÿ›‘ Stopping old containers..." docker compose down || true # Clean up orphaned containers echo "๐Ÿงน Cleaning up orphaned containers..." docker compose down --remove-orphans || true # Start new containers echo "๐Ÿš€ Starting new containers..." docker compose up -d echo "โœ… Deployment completed!" env: NODE_ENV: ${{ vars.NODE_ENV || 'production' }} LOG_LEVEL: ${{ vars.LOG_LEVEL || 'info' }} NEXT_PUBLIC_BASE_URL: ${{ vars.NEXT_PUBLIC_BASE_URL || 'https://dk0.dev' }} NEXT_PUBLIC_UMAMI_URL: ${{ vars.NEXT_PUBLIC_UMAMI_URL || 'https://analytics.dk0.dev' }} NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${{ vars.NEXT_PUBLIC_UMAMI_WEBSITE_ID || 'b3665829-927a-4ada-b9bb-fcf24171061e' }} MY_EMAIL: ${{ vars.MY_EMAIL || 'contact@dk0.dev' }} MY_INFO_EMAIL: ${{ vars.MY_INFO_EMAIL || 'info@dk0.dev' }} MY_PASSWORD: ${{ secrets.MY_PASSWORD || 'your-email-password' }} MY_INFO_PASSWORD: ${{ secrets.MY_INFO_PASSWORD || 'your-info-email-password' }} ADMIN_BASIC_AUTH: ${{ secrets.ADMIN_BASIC_AUTH || 'admin:your_secure_password_here' }} - name: Wait for containers to be ready run: | echo "โณ Waiting for containers to be ready..." sleep 30 # Check if all containers are running echo "๐Ÿ“Š Checking container status..." docker compose ps # Wait for application container to be healthy echo "๐Ÿฅ Waiting for application container to be healthy..." for i in {1..30}; do if docker exec portfolio-app curl -f http://localhost:3000/api/health > /dev/null 2>&1; then echo "โœ… Application container is healthy!" break fi echo "โณ Waiting for application container... ($i/30)" sleep 3 done - name: Health check run: | echo "๐Ÿ” Running comprehensive health checks..." # Check container status echo "๐Ÿ“Š Container status:" docker compose ps # Check application container echo "๐Ÿฅ Checking application container..." if docker exec portfolio-app curl -f http://localhost:3000/api/health; then echo "โœ… Application health check passed!" else echo "โŒ Application health check failed!" docker logs portfolio-app --tail=50 exit 1 fi # Check main page if curl -f http://localhost:3000/ > /dev/null; then echo "โœ… Main page is accessible!" else echo "โŒ Main page is not accessible!" exit 1 fi echo "โœ… All health checks passed! Deployment successful!" - name: Cleanup old images run: | echo "๐Ÿงน Cleaning up old images..." docker image prune -f docker system prune -f echo "โœ… Cleanup completed"