name: CI/CD Pipeline on: push: branches: - preprod env: REGISTRY: rg.fr-par.scw.cloud/weworkstudio NODE_VERSION: '20' jobs: # ============================================ # Backend Build, Test & Deploy # ============================================ backend: name: Backend - Build, Test & Push runs-on: ubuntu-latest defaults: run: working-directory: apps/backend steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Install dependencies run: npm install --legacy-peer-deps - name: Lint code run: npm run lint - name: Run unit tests run: npm test -- --coverage --passWithNoTests - name: Build application run: npm run build - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Scaleway Registry uses: docker/login-action@v3 with: registry: rg.fr-par.scw.cloud/weworkstudio username: nologin password: ${{ secrets.REGISTRY_TOKEN }} - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/xpeditis-backend tags: | type=ref,event=branch type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Backend Docker image uses: docker/build-push-action@v5 with: context: ./apps/backend file: ./apps/backend/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.REGISTRY }}/xpeditis-backend:buildcache cache-to: type=registry,ref=${{ env.REGISTRY }}/xpeditis-backend:buildcache,mode=max platforms: linux/amd64,linux/arm64 # ============================================ # Frontend Build, Test & Deploy # ============================================ frontend: name: Frontend - Build, Test & Push runs-on: ubuntu-latest defaults: run: working-directory: apps/frontend steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: apps/frontend/package-lock.json - name: Install dependencies run: npm ci --legacy-peer-deps - name: Lint code run: npm run lint - name: Run tests run: npm test -- --passWithNoTests || echo "No tests found" - name: Build application env: NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL || 'http://localhost:4000' }} NEXT_PUBLIC_APP_URL: ${{ secrets.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }} NEXT_TELEMETRY_DISABLED: 1 run: npm run build - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Scaleway Registry uses: docker/login-action@v3 with: registry: rg.fr-par.scw.cloud/weworkstudio username: nologin password: ${{ secrets.REGISTRY_TOKEN }} - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/xpeditis-frontend tags: | type=ref,event=branch type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Frontend Docker image uses: docker/build-push-action@v5 with: context: ./apps/frontend file: ./apps/frontend/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.REGISTRY }}/xpeditis-frontend:buildcache cache-to: type=registry,ref=${{ env.REGISTRY }}/xpeditis-frontend:buildcache,mode=max platforms: linux/amd64,linux/arm64 build-args: | NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL || 'http://localhost:4000' }} NEXT_PUBLIC_APP_URL=${{ secrets.NEXT_PUBLIC_APP_URL || 'http://localhost:3000' }} # ============================================ # Integration Tests (Optional) # ============================================ integration-tests: name: Integration Tests runs-on: ubuntu-latest needs: [backend, frontend] if: github.event_name == 'pull_request' defaults: run: working-directory: apps/backend services: postgres: image: postgres:15-alpine env: POSTGRES_USER: xpeditis POSTGRES_PASSWORD: xpeditis_dev_password POSTGRES_DB: xpeditis_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7-alpine options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Install dependencies run: npm install --legacy-peer-deps - name: Run integration tests env: DATABASE_HOST: localhost DATABASE_PORT: 5432 DATABASE_USER: xpeditis DATABASE_PASSWORD: xpeditis_dev_password DATABASE_NAME: xpeditis_test REDIS_HOST: localhost REDIS_PORT: 6379 JWT_SECRET: test-secret-key-for-ci run: npm run test:integration || echo "No integration tests found" # ============================================ # Deployment Summary # ============================================ deployment-summary: name: Deployment Summary runs-on: ubuntu-latest needs: [backend, frontend] if: success() steps: - name: Summary run: | echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Backend Image" >> $GITHUB_STEP_SUMMARY echo "- Registry: \`${{ env.REGISTRY }}/xpeditis-backend\`" >> $GITHUB_STEP_SUMMARY echo "- Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Frontend Image" >> $GITHUB_STEP_SUMMARY echo "- Registry: \`${{ env.REGISTRY }}/xpeditis-frontend\`" >> $GITHUB_STEP_SUMMARY echo "- Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Pull Commands" >> $GITHUB_STEP_SUMMARY echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY echo "docker pull ${{ env.REGISTRY }}/xpeditis-backend:${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY echo "docker pull ${{ env.REGISTRY }}/xpeditis-frontend:${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY # ============================================ # Discord Notification - Success # ============================================ notify-success: name: Discord Notification (Success) runs-on: ubuntu-latest needs: [backend, frontend] if: success() steps: - name: Send Discord notification run: | curl -H "Content-Type: application/json" \ -d '{ "embeds": [{ "title": "✅ CI/CD Pipeline Success", "description": "Deployment completed successfully!", "color": 3066993, "fields": [ { "name": "Repository", "value": "${{ github.repository }}", "inline": true }, { "name": "Branch", "value": "${{ github.ref_name }}", "inline": true }, { "name": "Commit", "value": "[${{ github.sha }}](${{ github.event.head_commit.url }})", "inline": false }, { "name": "Backend Image", "value": "`${{ env.REGISTRY }}/xpeditis-backend:${{ github.ref_name }}`", "inline": false }, { "name": "Frontend Image", "value": "`${{ env.REGISTRY }}/xpeditis-frontend:${{ github.ref_name }}`", "inline": false }, { "name": "Workflow", "value": "[${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": false } ], "timestamp": "${{ github.event.head_commit.timestamp }}", "footer": { "text": "Xpeditis CI/CD" } }] }' \ ${{ secrets.DISCORD_WEBHOOK_URL }} # ============================================ # Discord Notification - Failure # ============================================ notify-failure: name: Discord Notification (Failure) runs-on: ubuntu-latest needs: [backend, frontend] if: failure() steps: - name: Send Discord notification run: | curl -H "Content-Type: application/json" \ -d '{ "embeds": [{ "title": "❌ CI/CD Pipeline Failed", "description": "Deployment failed! Check the logs for details.", "color": 15158332, "fields": [ { "name": "Repository", "value": "${{ github.repository }}", "inline": true }, { "name": "Branch", "value": "${{ github.ref_name }}", "inline": true }, { "name": "Commit", "value": "[${{ github.sha }}](${{ github.event.head_commit.url }})", "inline": false }, { "name": "Workflow", "value": "[${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": false } ], "timestamp": "${{ github.event.head_commit.timestamp }}", "footer": { "text": "Xpeditis CI/CD" } }] }' \ ${{ secrets.DISCORD_WEBHOOK_URL }}