# ============================================================================= # MiChangarrito - CI/CD Pipeline # ============================================================================= # Triggers: Push to main/develop, Pull Requests # ============================================================================= name: CI/CD Pipeline on: push: branches: [main, develop] pull_request: branches: [main, develop] env: NODE_VERSION: '20' REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: # =========================================================================== # BACKEND - Lint, Test, Build # =========================================================================== backend: name: Backend CI runs-on: ubuntu-latest defaults: run: working-directory: apps/backend steps: - name: Checkout repository 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/backend/package-lock.json - name: Install dependencies run: npm ci - name: Run linter run: npm run lint - name: Run tests run: npm run test -- --passWithNoTests - name: Build application run: npm run build - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: backend-dist path: apps/backend/dist retention-days: 1 # =========================================================================== # FRONTEND - Lint, Build # =========================================================================== frontend: name: Frontend CI runs-on: ubuntu-latest defaults: run: working-directory: apps/frontend steps: - name: Checkout repository 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 - name: Run linter run: npm run lint || true - name: Build application run: npm run build env: VITE_API_URL: ${{ vars.VITE_API_URL || 'http://localhost:3141/api/v1' }} - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: frontend-dist path: apps/frontend/dist retention-days: 1 # =========================================================================== # WHATSAPP SERVICE - Lint, Build # =========================================================================== whatsapp-service: name: WhatsApp Service CI runs-on: ubuntu-latest defaults: run: working-directory: apps/whatsapp-service steps: - name: Checkout repository 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/whatsapp-service/package-lock.json - name: Install dependencies run: npm ci - name: Run linter run: npm run lint || true - name: Build application run: npm run build # =========================================================================== # MOBILE - Type Check # =========================================================================== mobile: name: Mobile CI runs-on: ubuntu-latest defaults: run: working-directory: apps/mobile steps: - name: Checkout repository 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/mobile/package-lock.json - name: Install dependencies run: npm ci - name: Type check run: npx tsc --noEmit # =========================================================================== # DOCKER BUILD (only on main/develop push) # =========================================================================== docker-build: name: Docker Build runs-on: ubuntu-latest needs: [backend, frontend, whatsapp-service] if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') permissions: contents: read packages: write strategy: matrix: service: [backend, frontend, whatsapp-service] include: - service: backend context: ./apps/backend dockerfile: ./apps/backend/Dockerfile - service: frontend context: ./apps/frontend dockerfile: ./apps/frontend/Dockerfile - service: whatsapp-service context: ./apps/whatsapp-service dockerfile: ./apps/whatsapp-service/Dockerfile steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.service }} tags: | type=ref,event=branch type=sha,prefix= type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max target: production # =========================================================================== # DEPLOY (only on main push) # =========================================================================== deploy: name: Deploy to Production runs-on: ubuntu-latest needs: [docker-build] if: github.ref == 'refs/heads/main' environment: production steps: - name: Checkout repository uses: actions/checkout@v4 - name: Deploy to server uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SERVER_SSH_KEY }} script: | cd /opt/michangarrito docker-compose pull docker-compose up -d --remove-orphans docker system prune -f - name: Notify deployment if: success() run: | echo "Deployment successful!" # Add Slack/Discord notification here if needed