- Add IndexNow submit script + state tracking - Update deploy script to notify IndexNow after healthy deploy - Publish IndexNow verification file in public - Update sitemaps and add env placeholders - Pass analytics/ads/IndexNow env vars into frontend build
134 lines
4.3 KiB
Bash
134 lines
4.3 KiB
Bash
#!/bin/bash
|
|
# deploy.sh — Production deployment script for Dociva
|
|
set -euo pipefail
|
|
|
|
echo "========================================="
|
|
echo " Dociva Production Deployment"
|
|
echo "========================================="
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
# Check Docker
|
|
if ! command -v docker &> /dev/null; then
|
|
echo -e "${RED}Docker is not installed.${NC}"
|
|
exit 1
|
|
fi
|
|
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
|
echo -e "${RED}Docker Compose is not installed.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check .env
|
|
if [ ! -f ".env" ]; then
|
|
echo -e "${RED}.env file not found! Copy .env.example and configure it.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
read_env_value() {
|
|
local key="$1"
|
|
local fallback="${2:-}"
|
|
local shell_value="${!key-}"
|
|
local file_value
|
|
|
|
file_value="$(grep -E "^${key}=" .env 2>/dev/null | tail -n 1 | cut -d= -f2- || true)"
|
|
|
|
if [ -n "$shell_value" ]; then
|
|
printf '%s' "$shell_value"
|
|
elif [ -n "$file_value" ]; then
|
|
printf '%s' "$file_value"
|
|
else
|
|
printf '%s' "$fallback"
|
|
fi
|
|
}
|
|
|
|
normalize_bool() {
|
|
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
|
|
}
|
|
|
|
INDEXNOW_AUTO_SUBMIT_VALUE="$(normalize_bool "$(read_env_value INDEXNOW_AUTO_SUBMIT 1)")"
|
|
INDEXNOW_STRICT_VALUE="$(normalize_bool "$(read_env_value INDEXNOW_STRICT false)")"
|
|
|
|
echo -e "${YELLOW}1/8 — Pulling latest code...${NC}"
|
|
git pull origin main 2>/dev/null || echo "Not a git repo or no remote, skipping pull."
|
|
|
|
echo -e "${YELLOW}2/8 — Building Docker images...${NC}"
|
|
docker compose -f docker-compose.prod.yml build --no-cache
|
|
|
|
echo -e "${YELLOW}3/8 — Stopping old containers...${NC}"
|
|
docker compose -f docker-compose.prod.yml down --remove-orphans
|
|
|
|
echo -e "${YELLOW}4/8 — Starting services...${NC}"
|
|
docker compose -f docker-compose.prod.yml up -d
|
|
|
|
if [ "${SKIP_AI_RUNTIME_CHECKS:-0}" != "1" ]; then
|
|
echo -e "${YELLOW}5/8 — Verifying AI runtime in backend + worker...${NC}"
|
|
for service in backend celery_worker; do
|
|
if ! docker compose -f docker-compose.prod.yml exec -T "$service" python - <<'PY'
|
|
import importlib.util
|
|
import os
|
|
import sys
|
|
|
|
issues = []
|
|
api_key = os.getenv("OPENROUTER_API_KEY", "").strip()
|
|
if not api_key or api_key.startswith("replace-with-"):
|
|
issues.append("OPENROUTER_API_KEY is missing or still set to a placeholder")
|
|
if importlib.util.find_spec("vtracer") is None:
|
|
issues.append("vtracer is not installed in this container")
|
|
|
|
if issues:
|
|
print("; ".join(issues))
|
|
sys.exit(1)
|
|
|
|
print("AI runtime OK")
|
|
PY
|
|
then
|
|
echo -e "${RED}✗ AI runtime check failed in ${service}.${NC}"
|
|
echo " Fix the container env/dependencies, then redeploy backend and celery_worker."
|
|
echo " Do not redeploy the frontend alone when backend routes, Celery tasks, or AI dependencies changed."
|
|
exit 1
|
|
fi
|
|
done
|
|
else
|
|
echo -e "${YELLOW}5/8 — Skipping AI runtime checks (SKIP_AI_RUNTIME_CHECKS=1).${NC}"
|
|
fi
|
|
|
|
echo -e "${YELLOW}6/8 — Waiting for health check...${NC}"
|
|
sleep 10
|
|
|
|
# Health check
|
|
if curl -sf http://localhost/api/health > /dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ Deployment successful! Service is healthy.${NC}"
|
|
else
|
|
echo -e "${RED}✗ Health check failed. Check logs:${NC}"
|
|
echo " docker compose -f docker-compose.prod.yml logs backend"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${INDEXNOW_AUTO_SUBMIT_VALUE:-1}" = "1" ] || [ "${INDEXNOW_AUTO_SUBMIT_VALUE:-true}" = "true" ]; then
|
|
echo -e "${YELLOW}7/8 — Submitting URLs to IndexNow...${NC}"
|
|
if docker compose -f docker-compose.prod.yml run --rm frontend_build_step node scripts/submit-indexnow.mjs; then
|
|
echo -e "${GREEN}✓ IndexNow notification completed.${NC}"
|
|
else
|
|
if [ "$INDEXNOW_STRICT_VALUE" = "1" ] || [ "$INDEXNOW_STRICT_VALUE" = "true" ]; then
|
|
echo -e "${RED}✗ IndexNow notification failed and INDEXNOW_STRICT is enabled.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${YELLOW}! IndexNow notification failed; deployment will continue.${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}7/8 — Skipping IndexNow notification (INDEXNOW_AUTO_SUBMIT=0).${NC}"
|
|
fi
|
|
|
|
echo -e "${YELLOW}8/8 — Current containers:${NC}"
|
|
docker compose -f docker-compose.prod.yml ps
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Deployment complete!${NC}"
|
|
echo " App: http://localhost"
|
|
echo " Logs: docker compose -f docker-compose.prod.yml logs -f"
|