name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] env: REGISTRY: docker.io IMAGE_NAME: t72chevy/vip-coordinator jobs: # Backend tests backend-tests: name: Backend Tests runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_USER: test_user POSTGRES_PASSWORD: test_password POSTGRES_DB: vip_coordinator_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: backend/package-lock.json - name: Install dependencies working-directory: ./backend run: npm ci - name: Run linter working-directory: ./backend run: npm run lint || true - name: Run type check working-directory: ./backend run: npx tsc --noEmit - name: Run tests working-directory: ./backend env: DATABASE_URL: postgresql://test_user:test_password@localhost:5432/vip_coordinator_test REDIS_URL: redis://localhost:6379 GOOGLE_CLIENT_ID: test_client_id GOOGLE_CLIENT_SECRET: test_client_secret GOOGLE_REDIRECT_URI: http://localhost:3000/auth/google/callback FRONTEND_URL: http://localhost:5173 JWT_SECRET: test_jwt_secret_minimum_32_characters_long NODE_ENV: test run: npm test - name: Upload coverage uses: actions/upload-artifact@v4 if: always() with: name: backend-coverage path: backend/coverage/ # Frontend tests frontend-tests: name: Frontend Tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install dependencies working-directory: ./frontend run: npm ci - name: Run linter working-directory: ./frontend run: npm run lint - name: Run type check working-directory: ./frontend run: npx tsc --noEmit - name: Run tests working-directory: ./frontend run: npm test -- --run - name: Build frontend working-directory: ./frontend run: npm run build - name: Upload coverage uses: actions/upload-artifact@v4 if: always() with: name: frontend-coverage path: frontend/coverage/ # Build Docker images build-images: name: Build Docker Images runs-on: ubuntu-latest needs: [backend-tests, frontend-tests] if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=sha,prefix={{branch}}- type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Backend uses: docker/build-push-action@v5 with: context: ./backend push: true tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:backend-${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:backend-latest cache-from: type=gha cache-to: type=gha,mode=max - name: Build and push Frontend uses: docker/build-push-action@v5 with: context: ./frontend push: true tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:frontend-${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:frontend-latest cache-from: type=gha cache-to: type=gha,mode=max # Security scan security-scan: name: Security Scan runs-on: ubuntu-latest needs: [backend-tests, frontend-tests] steps: - uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy scan results uses: github/codeql-action/upload-sarif@v2 if: always() with: sarif_file: 'trivy-results.sarif' # Deploy to staging (example) deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: [build-images] if: github.ref == 'refs/heads/develop' environment: name: staging url: https://staging.bsa.madeamess.online steps: - uses: actions/checkout@v4 - name: Deploy to staging run: | echo "Deploying to staging environment..." # Add your deployment script here # Example: ssh to server and docker-compose pull && up # Deploy to production deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: [build-images, security-scan] if: github.ref == 'refs/heads/main' environment: name: production url: https://bsa.madeamess.online steps: - uses: actions/checkout@v4 - name: Deploy to production run: | echo "Deploying to production environment..." # Add your deployment script here # Example: ssh to server and docker-compose pull && up