132 lines
3.8 KiB
Bash
Executable File
132 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
echo "🚀 VoxBlog Deployment Script"
|
|
echo "=============================="
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
fetch_env_from_infisical() {
|
|
if [ -z "${INFISICAL_TOKEN:-}" ]; then
|
|
echo -e "${RED}❌ INFISICAL_TOKEN is not set${NC}"
|
|
echo "Provide an Infisical service token or create a .env file for local use."
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${YELLOW}🔐 Retrieving secrets from Infisical...${NC}"
|
|
local tmp_env
|
|
tmp_env=$(mktemp)
|
|
local cli_image
|
|
cli_image="${INFISICAL_CLI_IMAGE:-infisical/cli:latest}"
|
|
|
|
# shellcheck disable=SC2206
|
|
local docker_cmd=(docker run --rm -e INFISICAL_TOKEN="${INFISICAL_TOKEN}")
|
|
if [ -n "${INFISICAL_SITE_URL:-}" ]; then
|
|
docker_cmd+=(-e INFISICAL_SITE_URL="${INFISICAL_SITE_URL}")
|
|
fi
|
|
if [ -n "${INFISICAL_API_URL:-}" ]; then
|
|
docker_cmd+=(-e INFISICAL_API_URL="${INFISICAL_API_URL}")
|
|
elif [ -n "${INFISICAL_SITE_URL:-}" ]; then
|
|
local api_url
|
|
api_url="${INFISICAL_SITE_URL%/}/api"
|
|
docker_cmd+=(-e INFISICAL_API_URL="${api_url}")
|
|
fi
|
|
docker_cmd+=("${cli_image}" export --format=dotenv)
|
|
|
|
if ! "${docker_cmd[@]}" >"${tmp_env}"; then
|
|
echo -e "${RED}❌ Failed to export secrets from Infisical${NC}"
|
|
rm -f "${tmp_env}"
|
|
exit 1
|
|
fi
|
|
|
|
set -o allexport
|
|
# shellcheck source=/dev/null
|
|
source "${tmp_env}"
|
|
set +o allexport
|
|
rm -f "${tmp_env}"
|
|
}
|
|
|
|
load_environment() {
|
|
if [ -n "${INFISICAL_TOKEN:-}" ]; then
|
|
fetch_env_from_infisical
|
|
elif [ -f .env ]; then
|
|
echo -e "${YELLOW}⚠️ Using local .env file (not recommended for production)...${NC}"
|
|
set -o allexport
|
|
# shellcheck source=/dev/null
|
|
source .env
|
|
set +o allexport
|
|
else
|
|
echo -e "${RED}❌ No environment configuration found${NC}"
|
|
echo "Provide INFISICAL_TOKEN (preferred) or create a local .env for testing."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
load_environment
|
|
|
|
# Pull latest code
|
|
echo -e "${YELLOW}📥 Pulling latest code...${NC}"
|
|
git pull origin main
|
|
|
|
# Stop existing containers
|
|
echo -e "${YELLOW}🛑 Stopping existing containers...${NC}"
|
|
docker-compose down
|
|
|
|
# Build new images
|
|
echo -e "${YELLOW}🔨 Building new images...${NC}"
|
|
docker-compose build --no-cache
|
|
|
|
# Start containers
|
|
echo -e "${YELLOW}▶️ Starting containers...${NC}"
|
|
docker-compose up -d
|
|
|
|
# Wait for services to be ready
|
|
echo -e "${YELLOW}⏳ Waiting for services to start...${NC}"
|
|
sleep 15
|
|
|
|
# Run database migrations
|
|
echo -e "${YELLOW}🗄️ Running database migrations...${NC}"
|
|
docker-compose exec -T api pnpm run drizzle:migrate || echo "Migration skipped or failed"
|
|
|
|
# Health check
|
|
echo -e "${YELLOW}🏥 Performing health checks...${NC}"
|
|
|
|
API_HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3301/api/health || echo "000")
|
|
if [ "$API_HEALTH" = "200" ]; then
|
|
echo -e "${GREEN}✅ API is healthy${NC}"
|
|
else
|
|
echo -e "${RED}❌ API health check failed (HTTP $API_HEALTH)${NC}"
|
|
echo "Checking API logs:"
|
|
docker-compose logs --tail=50 api
|
|
exit 1
|
|
fi
|
|
|
|
ADMIN_HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3300 || echo "000")
|
|
if [ "$ADMIN_HEALTH" = "200" ]; then
|
|
echo -e "${GREEN}✅ Admin is healthy${NC}"
|
|
else
|
|
echo -e "${RED}❌ Admin health check failed (HTTP $ADMIN_HEALTH)${NC}"
|
|
echo "Checking Admin logs:"
|
|
docker-compose logs --tail=50 admin
|
|
exit 1
|
|
fi
|
|
|
|
# Clean up old images
|
|
echo -e "${YELLOW}🧹 Cleaning up old Docker images...${NC}"
|
|
docker image prune -af --filter "until=24h"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}✅ Deployment complete!${NC}"
|
|
echo ""
|
|
echo "Services running:"
|
|
echo " - API: http://localhost:3301"
|
|
echo " - Admin: http://localhost:3300"
|
|
echo ""
|
|
echo "To view logs: docker-compose logs -f"
|
|
echo "To stop: docker-compose down"
|