name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: test: runs-on: ubuntu-latest services: postgres: image: postgres:14 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: test_db 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: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install Python dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Install Frontend dependencies run: | cd frontend npm ci - name: Run Backend tests env: DEBUG: True SECRET_KEY: test-secret-key DB_NAME: test_db DB_USER: postgres DB_PASSWORD: postgres DB_HOST: localhost DB_PORT: 5432 REDIS_URL: redis://localhost:6379/0 run: | python manage.py test - name: Run Frontend tests run: | cd frontend npm run test:ci - name: Run linting run: | # Backend linting pip install flake8 black isort black --check . isort --check-only . flake8 . # Frontend linting cd frontend npm run lint build: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - 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 }} 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 image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Build and push Frontend image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile.frontend push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:latest cache-from: type=gha cache-to: type=gha,mode=max deploy: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Configure kubectl uses: azure/k8s-set-context@v3 with: method: kubeconfig kubeconfig: ${{ secrets.KUBE_CONFIG }} - name: Deploy to Kubernetes run: | # Update image tags in k8s files sed -i "s|dubai-analytics:latest|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest|g" k8s/backend.yaml sed -i "s|dubai-analytics-frontend:latest|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend:latest|g" k8s/frontend.yaml # Apply Kubernetes manifests kubectl apply -f k8s/namespace.yaml kubectl apply -f k8s/configmap.yaml kubectl apply -f k8s/secret.yaml kubectl apply -f k8s/postgres.yaml kubectl apply -f k8s/redis.yaml kubectl apply -f k8s/backend.yaml kubectl apply -f k8s/frontend.yaml kubectl apply -f k8s/ingress.yaml # Wait for deployment to be ready kubectl rollout status deployment/backend -n dubai-analytics kubectl rollout status deployment/frontend -n dubai-analytics - name: Run database migrations run: | kubectl exec -n dubai-analytics deployment/backend -- python manage.py migrate kubectl exec -n dubai-analytics deployment/backend -- python manage.py import_csv_data --data-dir sample\ data