- Replace Socket.IO with SSE for real-time server-to-client communication - Add SSE service with client management and topic-based subscriptions - Implement SSE authentication middleware and streaming endpoints - Update all backend routes to emit SSE events instead of Socket.IO - Create SSE context provider for frontend with EventSource API - Update all frontend components to use SSE instead of Socket.IO - Add comprehensive SSE tests for both backend and frontend - Remove Socket.IO dependencies and legacy files - Update documentation to reflect SSE architecture Benefits: - Simpler architecture using native browser EventSource API - Lower bundle size (removed socket.io-client dependency) - Better compatibility with reverse proxies and load balancers - Reduced resource usage for Raspberry Pi deployment - Standard HTTP-based real-time communication 🤖 Generated with [AI Assistant] Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
370 lines
13 KiB
Makefile
370 lines
13 KiB
Makefile
# Adopt-a-Street Makefile
|
|
# Provides convenient commands for building and running the application
|
|
|
|
.PHONY: help install build run dev test clean lint format docker-multiarch docker-multiarch-verify \
|
|
k8s-test-connection k8s-test-manifests k8s-test-deploy-dev k8s-namespace-create k8s-secret-create \
|
|
k8s-deploy k8s-deploy-dev k8s-deploy-staging k8s-deploy-prod k8s-status k8s-logs-backend \
|
|
k8s-logs-frontend k8s-health k8s-port-forward k8s-exec-backend k8s-rollback k8s-delete
|
|
|
|
# Kubernetes Configuration
|
|
K8S_NAMESPACE ?= adopt-a-street-dev
|
|
K8S_CONTEXT ?= k0s-cluster
|
|
REGISTRY ?= gitea-http.taildb3494.ts.net
|
|
GITEA_USERNAME ?= will
|
|
|
|
# Default target
|
|
help:
|
|
@echo "Adopt-a-Street Development Commands"
|
|
@echo ""
|
|
@echo "Setup & Installation:"
|
|
@echo " install Install dependencies for both frontend and backend"
|
|
@echo " clean Clean node_modules and build artifacts"
|
|
@echo ""
|
|
@echo "Development:"
|
|
@echo " dev Start both frontend and backend in development mode"
|
|
@echo " dev-frontend Start frontend development server only"
|
|
@echo " dev-backend Start backend development server only"
|
|
@echo ""
|
|
@echo "Building:"
|
|
@echo " build Build both frontend and backend for production"
|
|
@echo " build-frontend Build frontend for production"
|
|
@echo " build-backend Build backend for production"
|
|
@echo ""
|
|
@echo "Testing:"
|
|
@echo " test Run tests for both frontend and backend"
|
|
@echo " test-frontend Run frontend tests"
|
|
@echo " test-backend Run backend tests"
|
|
@echo " test-coverage Run tests with coverage reports"
|
|
@echo ""
|
|
@echo "Code Quality:"
|
|
@echo " lint Run linting for both frontend and backend"
|
|
@echo " lint-frontend Run frontend linting"
|
|
@echo " lint-backend Run backend linting"
|
|
@echo ""
|
|
@echo "Production:"
|
|
@echo " run Run production build"
|
|
@echo " start Start production servers"
|
|
@echo ""
|
|
@echo "Kubernetes Testing:"
|
|
@echo " k8s-test-connection Verify kubectl connectivity to cluster"
|
|
@echo " k8s-test-manifests Validate manifest syntax (dry-run)"
|
|
@echo " k8s-test-deploy-dev Deploy to dev namespace and verify"
|
|
@echo ""
|
|
@echo "Kubernetes Deployment:"
|
|
@echo " k8s-namespace-create Create namespace (K8S_NAMESPACE=name)"
|
|
@echo " k8s-deploy Deploy all manifests to namespace (includes registry secret)"
|
|
@echo " k8s-deploy-dev Deploy to adopt-a-street-dev"
|
|
@echo " k8s-deploy-staging Deploy to adopt-a-street-staging"
|
|
@echo " k8s-deploy-prod Deploy to adopt-a-street-prod"
|
|
@echo ""
|
|
@echo "Kubernetes Verification:"
|
|
@echo " k8s-status Show pods/services status"
|
|
@echo " k8s-logs-backend Tail backend logs"
|
|
@echo " k8s-logs-frontend Tail frontend logs"
|
|
@echo " k8s-health Check health endpoints"
|
|
@echo ""
|
|
@echo "Kubernetes Utilities:"
|
|
@echo " k8s-port-forward Port forward for local testing"
|
|
@echo " k8s-exec-backend Shell into backend pod"
|
|
@echo " k8s-rollback Rollback deployment"
|
|
@echo " k8s-delete Delete all resources from namespace"
|
|
|
|
# Installation
|
|
install:
|
|
@echo "Installing dependencies..."
|
|
cd backend && bun install
|
|
cd frontend && bun install
|
|
@echo "Dependencies installed successfully!"
|
|
|
|
clean:
|
|
@echo "Cleaning up..."
|
|
rm -rf backend/node_modules
|
|
rm -rf frontend/node_modules
|
|
rm -rf frontend/build
|
|
rm -rf backend/dist
|
|
@echo "Cleanup complete!"
|
|
|
|
# Development
|
|
dev:
|
|
@echo "Starting development servers..."
|
|
@echo "Backend will start on http://localhost:5000"
|
|
@echo "Frontend will start on http://localhost:3000"
|
|
@echo "Press Ctrl+C to stop both servers"
|
|
@make -j2 dev-frontend dev-backend
|
|
|
|
dev-frontend:
|
|
@echo "Starting frontend development server..."
|
|
cd frontend && bun start
|
|
|
|
dev-backend:
|
|
@echo "Starting backend development server..."
|
|
cd backend && node server.js
|
|
|
|
# Building
|
|
build: build-frontend build-backend
|
|
@echo "Build complete!"
|
|
|
|
build-frontend:
|
|
@echo "Building frontend for production..."
|
|
cd frontend && bun run build
|
|
@echo "Frontend build complete!"
|
|
|
|
build-backend:
|
|
@echo "Backend is ready for production (no build step required for Node.js)"
|
|
@echo "Backend production files are in backend/"
|
|
|
|
# Testing
|
|
test: test-frontend test-backend
|
|
@echo "All tests completed!"
|
|
|
|
test-frontend:
|
|
@echo "Running frontend tests..."
|
|
cd frontend && bun test -- --watchAll=false --coverage
|
|
|
|
test-backend:
|
|
@echo "Running backend tests..."
|
|
cd backend && bun test
|
|
|
|
test-coverage:
|
|
@echo "Running tests with coverage..."
|
|
@echo "Backend coverage:"
|
|
cd backend && bun run test:coverage
|
|
@echo ""
|
|
@echo "Frontend coverage:"
|
|
cd frontend && bun run test:coverage
|
|
|
|
# Code Quality
|
|
lint: lint-frontend lint-backend
|
|
@echo "Linting complete!"
|
|
|
|
lint-frontend:
|
|
@echo "Linting frontend..."
|
|
cd frontend && bun run lint 2>/dev/null || echo "Frontend linting not configured"
|
|
|
|
lint-backend:
|
|
@echo "Linting backend..."
|
|
cd backend && bunx eslint .
|
|
|
|
# Production
|
|
run: build
|
|
@echo "Starting production servers..."
|
|
@echo "Note: In production, you would typically use process managers like PM2"
|
|
@echo "or container orchestration like Kubernetes"
|
|
@echo "See deploy/ directory for Kubernetes deployment files"
|
|
|
|
start:
|
|
@echo "Starting production backend server..."
|
|
cd backend && NODE_ENV=production node server.js
|
|
|
|
# Docker (if needed)
|
|
docker-build:
|
|
@echo "Building Docker images..."
|
|
docker build -t adopt-a-street-frontend ./frontend
|
|
docker build -t adopt-a-street-backend ./backend
|
|
@echo "Docker images built!"
|
|
|
|
docker-run:
|
|
@echo "Running Docker containers..."
|
|
docker run -d -p 3000:3000 --name frontend adopt-a-street-frontend
|
|
docker run -d -p 5000:5000 --name backend adopt-a-street-backend
|
|
@echo "Docker containers running!"
|
|
|
|
# Multi-Architecture Docker
|
|
docker-multiarch-setup:
|
|
@echo "Setting up multi-architecture Docker builder..."
|
|
./scripts/setup-multiarch-builder.sh
|
|
|
|
docker-multiarch-build:
|
|
@echo "Building and pushing multi-architecture Docker images..."
|
|
./scripts/build-multiarch.sh
|
|
|
|
docker-multiarch-verify:
|
|
@echo "Verifying multi-architecture Docker images..."
|
|
./scripts/verify-multiarch.sh
|
|
|
|
docker-multiarch: docker-multiarch-setup docker-multiarch-build docker-multiarch-verify
|
|
@echo "Multi-architecture Docker workflow complete!"
|
|
|
|
# Database (for development)
|
|
db-setup:
|
|
@echo "Setting up MongoDB..."
|
|
@echo "Make sure MongoDB is installed and running on your system"
|
|
@echo "Or use Docker: docker run -d -p 27017:27017 --name mongodb mongo"
|
|
@echo "Create .env file in backend/ with MONGO_URI and JWT_SECRET"
|
|
|
|
# Environment setup
|
|
env-setup:
|
|
@echo "Setting up environment files..."
|
|
@if [ ! -f backend/.env ]; then \
|
|
echo "Creating backend/.env file..."; \
|
|
cp backend/.env.example backend/.env 2>/dev/null || echo "MONGO_URI=mongodb://localhost:27017/adopt-a-street\nJWT_SECRET=your-secret-key-here\nPORT=5000" > backend/.env; \
|
|
echo "Please edit backend/.env with your actual values"; \
|
|
else \
|
|
echo "backend/.env already exists"; \
|
|
fi
|
|
|
|
# Quick start for new developers
|
|
quick-start: install env-setup db-setup
|
|
@echo ""
|
|
@echo "Quick start complete!"
|
|
@echo ""
|
|
@echo "Next steps:"
|
|
@echo "1. Edit backend/.env with your MongoDB URI and JWT secret"
|
|
@echo "2. Run 'make dev' to start development servers"
|
|
@echo "3. Visit http://localhost:3000 to see the application"
|
|
@echo ""
|
|
@echo "For more commands, run 'make help'"
|
|
@echo ""
|
|
@echo "Docker Commands:"
|
|
@echo " docker-build Build single-architecture Docker images"
|
|
@echo " docker-run Run Docker containers"
|
|
@echo " docker-multiarch-setup Setup multi-architecture builder"
|
|
@echo " docker-multiarch-build Build and push multi-arch images"
|
|
@echo " docker-multiarch-verify Verify multi-arch images"
|
|
@echo " docker-multiarch Complete multi-arch workflow"
|
|
|
|
# ==================== Kubernetes Testing ====================
|
|
|
|
k8s-test-connection:
|
|
@echo "Testing kubectl connectivity to $(K8S_CONTEXT)..."
|
|
@kubectl cluster-info --context=$(K8S_CONTEXT)
|
|
@echo ""
|
|
@echo "Cluster nodes:"
|
|
@kubectl get nodes
|
|
@echo ""
|
|
@echo "Connection test successful!"
|
|
|
|
k8s-test-manifests:
|
|
@echo "Validating Kubernetes manifests (dry-run)..."
|
|
@kubectl apply -f deploy/k8s/ --dry-run=client -n $(K8S_NAMESPACE)
|
|
@echo ""
|
|
@echo "Manifest validation successful!"
|
|
|
|
k8s-test-deploy-dev:
|
|
@echo "Testing deployment to $(K8S_NAMESPACE)..."
|
|
@$(MAKE) K8S_NAMESPACE=adopt-a-street-dev k8s-namespace-create || true
|
|
@echo "Running manifest validation..."
|
|
@$(MAKE) K8S_NAMESPACE=adopt-a-street-dev k8s-test-manifests
|
|
@echo ""
|
|
@echo "Note: Run 'make k8s-deploy-dev' to deploy (includes registry secret)"
|
|
|
|
# ==================== Kubernetes Deployment ====================
|
|
|
|
k8s-namespace-create:
|
|
@echo "Creating namespace: $(K8S_NAMESPACE)..."
|
|
@kubectl create namespace $(K8S_NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
|
|
@echo "Namespace $(K8S_NAMESPACE) ready!"
|
|
|
|
k8s-secret-create:
|
|
ifndef GITEA_PASSWORD
|
|
@echo "Error: GITEA_PASSWORD environment variable not set"
|
|
@echo "Usage: make k8s-secret-create GITEA_PASSWORD=your-password K8S_NAMESPACE=namespace"
|
|
@exit 1
|
|
endif
|
|
@echo "Creating image pull secret in $(K8S_NAMESPACE)..."
|
|
@kubectl create secret docker-registry regcred \
|
|
--docker-server=$(REGISTRY) \
|
|
--docker-username=$(GITEA_USERNAME) \
|
|
--docker-password=$(GITEA_PASSWORD) \
|
|
--namespace=$(K8S_NAMESPACE) \
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
|
@echo "Image pull secret created successfully!"
|
|
|
|
k8s-deploy: k8s-namespace-create
|
|
@echo "Deploying to namespace: $(K8S_NAMESPACE)..."
|
|
@kubectl apply -f deploy/k8s/registry-secret.yaml -n $(K8S_NAMESPACE)
|
|
@kubectl apply -f deploy/k8s/configmap.yaml -n $(K8S_NAMESPACE)
|
|
@kubectl apply -f deploy/k8s/secrets.yaml -n $(K8S_NAMESPACE) 2>/dev/null || echo "Warning: secrets.yaml not found or already exists"
|
|
@kubectl apply -f deploy/k8s/couchdb-statefulset.yaml -n $(K8S_NAMESPACE)
|
|
@kubectl apply -f deploy/k8s/backend-deployment.yaml -n $(K8S_NAMESPACE)
|
|
@kubectl apply -f deploy/k8s/frontend-deployment.yaml -n $(K8S_NAMESPACE)
|
|
@echo ""
|
|
@echo "Deployment initiated! Waiting for pods to be ready..."
|
|
@sleep 5
|
|
@kubectl get pods -n $(K8S_NAMESPACE)
|
|
@echo ""
|
|
@echo "Deployment complete! Run 'make k8s-status K8S_NAMESPACE=$(K8S_NAMESPACE)' to check status"
|
|
|
|
k8s-deploy-dev:
|
|
@$(MAKE) K8S_NAMESPACE=adopt-a-street-dev k8s-deploy
|
|
|
|
k8s-deploy-staging:
|
|
@$(MAKE) K8S_NAMESPACE=adopt-a-street-staging k8s-deploy
|
|
|
|
k8s-deploy-prod:
|
|
@$(MAKE) K8S_NAMESPACE=adopt-a-street-prod k8s-deploy
|
|
@echo ""
|
|
@echo "WARNING: Deployed to PRODUCTION namespace!"
|
|
|
|
# ==================== Kubernetes Verification ====================
|
|
|
|
k8s-status:
|
|
@echo "Status for namespace: $(K8S_NAMESPACE)"
|
|
@echo ""
|
|
@echo "=== Pods ==="
|
|
@kubectl get pods -n $(K8S_NAMESPACE) -o wide
|
|
@echo ""
|
|
@echo "=== Services ==="
|
|
@kubectl get services -n $(K8S_NAMESPACE)
|
|
@echo ""
|
|
@echo "=== Deployments ==="
|
|
@kubectl get deployments -n $(K8S_NAMESPACE)
|
|
@echo ""
|
|
@echo "=== StatefulSets ==="
|
|
@kubectl get statefulsets -n $(K8S_NAMESPACE)
|
|
|
|
k8s-logs-backend:
|
|
@echo "Tailing backend logs in $(K8S_NAMESPACE)..."
|
|
@kubectl logs -f -n $(K8S_NAMESPACE) -l app=adopt-a-street-backend --tail=100
|
|
|
|
k8s-logs-frontend:
|
|
@echo "Tailing frontend logs in $(K8S_NAMESPACE)..."
|
|
@kubectl logs -f -n $(K8S_NAMESPACE) -l app=adopt-a-street-frontend --tail=100
|
|
|
|
k8s-health:
|
|
@echo "Checking health endpoints in $(K8S_NAMESPACE)..."
|
|
@echo ""
|
|
@echo "Backend health:"
|
|
@kubectl exec -n $(K8S_NAMESPACE) deployment/adopt-a-street-backend -- curl -s http://localhost:5000/api/health || echo "Backend health check failed"
|
|
@echo ""
|
|
@echo ""
|
|
@echo "Frontend health:"
|
|
@kubectl exec -n $(K8S_NAMESPACE) deployment/adopt-a-street-frontend -- curl -s http://localhost:80/health || echo "Frontend health check failed"
|
|
@echo ""
|
|
@echo ""
|
|
@echo "CouchDB health:"
|
|
@kubectl exec -n $(K8S_NAMESPACE) deployment/adopt-a-street-backend -- curl -s http://adopt-a-street-couchdb:5984/_up || echo "CouchDB connection failed"
|
|
|
|
# ==================== Kubernetes Utilities ====================
|
|
|
|
k8s-port-forward:
|
|
@echo "Port forwarding services in $(K8S_NAMESPACE)..."
|
|
@echo "Backend: http://localhost:5000"
|
|
@echo "Frontend: http://localhost:3000"
|
|
@echo ""
|
|
@echo "Press Ctrl+C to stop port forwarding"
|
|
@kubectl port-forward -n $(K8S_NAMESPACE) service/adopt-a-street-backend 5000:5000 & \
|
|
kubectl port-forward -n $(K8S_NAMESPACE) service/adopt-a-street-frontend 3000:80
|
|
|
|
k8s-exec-backend:
|
|
@echo "Opening shell in backend pod..."
|
|
@kubectl exec -it -n $(K8S_NAMESPACE) deployment/adopt-a-street-backend -- /bin/bash
|
|
|
|
k8s-rollback:
|
|
@echo "Rolling back deployments in $(K8S_NAMESPACE)..."
|
|
@kubectl rollout undo deployment/adopt-a-street-backend -n $(K8S_NAMESPACE)
|
|
@kubectl rollout undo deployment/adopt-a-street-frontend -n $(K8S_NAMESPACE)
|
|
@echo "Rollback initiated! Checking status..."
|
|
@kubectl rollout status deployment/adopt-a-street-backend -n $(K8S_NAMESPACE)
|
|
@kubectl rollout status deployment/adopt-a-street-frontend -n $(K8S_NAMESPACE)
|
|
|
|
k8s-delete:
|
|
@echo "WARNING: This will delete all resources in $(K8S_NAMESPACE)"
|
|
@echo "Press Ctrl+C within 5 seconds to cancel..."
|
|
@sleep 5
|
|
@echo "Deleting resources in $(K8S_NAMESPACE)..."
|
|
@kubectl delete -f deploy/k8s/ -n $(K8S_NAMESPACE) --ignore-not-found=true
|
|
@echo ""
|
|
@echo "Resources deleted from $(K8S_NAMESPACE)"
|
|
@echo "Note: The namespace itself still exists. Use 'kubectl delete namespace $(K8S_NAMESPACE)' to remove it."
|