Files
adopt-a-street/Makefile
William Valentin bb9c8ec1c3 feat: Migrate from Socket.IO to Server-Sent Events (SSE)
- 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>
2025-12-05 22:49:22 -08:00

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."