#!/bin/bash set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Cleanup function cleanup() { echo -e "\n${YELLOW}Cleaning up...${NC}" docker stop p1ctos4ve-postgres p1ctos4ve-redis p1ctos4ve-seaweedfs-master p1ctos4ve-seaweedfs-volume p1ctos4ve-seaweedfs-filer p1ctos4ve-seaweedfs-s3 2>/dev/null || true docker rm p1ctos4ve-postgres p1ctos4ve-redis p1ctos4ve-seaweedfs-master p1ctos4ve-seaweedfs-volume p1ctos4ve-seaweedfs-filer p1ctos4ve-seaweedfs-s3 2>/dev/null || true docker network rm p1ctos4ve-network 2>/dev/null || true exit 0 } # Trap Ctrl+C trap cleanup SIGINT SIGTERM # Get the project root directory PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$PROJECT_ROOT" echo -e "${GREEN}๐Ÿš€ Starting p1ctos4ve backend setup...${NC}" # Step 1: Create network echo -e "${YELLOW}๐ŸŒ Step 1: Creating Docker network...${NC}" docker network create p1ctos4ve-network 2>/dev/null || echo "Network already exists" NETWORK_NAME="p1ctos4ve-network" # Step 2: Start PostgreSQL echo -e "${YELLOW}๐Ÿ“ฆ Step 2: Starting PostgreSQL...${NC}" docker run -d \ --name p1ctos4ve-postgres \ --network "${NETWORK_NAME}" \ -p 5432:5432 \ -e POSTGRES_USER=p1ctos4ve \ -e POSTGRES_PASSWORD=p1ctos4ve_password \ -e POSTGRES_DB=p1ctos4ve \ -v p1ctos4ve-postgres-data:/var/lib/postgresql/data \ postgres:16 # Step 3: Start Redis echo -e "${YELLOW}๐Ÿ“ฆ Step 3: Starting Redis...${NC}" docker run -d \ --name p1ctos4ve-redis \ --network "${NETWORK_NAME}" \ -p 6379:6379 \ -v p1ctos4ve-redis-data:/data \ redis:7-alpine # Step 4: Start SeaweedFS Master echo -e "${YELLOW}๐Ÿ“ฆ Step 4: Starting SeaweedFS Master...${NC}" docker run -d \ --name p1ctos4ve-seaweedfs-master \ --network "${NETWORK_NAME}" \ -p 9333:9333 \ -p 19333:19333 \ -v p1ctos4ve-seaweedfs-master-data:/data \ chrislusf/seaweedfs:latest \ master -ip=p1ctos4ve-seaweedfs-master # Step 5: Start SeaweedFS Volume echo -e "${YELLOW}๐Ÿ“ฆ Step 5: Starting SeaweedFS Volume...${NC}" docker run -d \ --name p1ctos4ve-seaweedfs-volume \ --network "${NETWORK_NAME}" \ -p 8080:8080 \ -v p1ctos4ve-seaweedfs-volume-data:/data \ chrislusf/seaweedfs:latest \ volume -mserver=p1ctos4ve-seaweedfs-master:9333 -port=8080 # Step 6: Start SeaweedFS Filer echo -e "${YELLOW}๐Ÿ“ฆ Step 6: Starting SeaweedFS Filer...${NC}" docker run -d \ --name p1ctos4ve-seaweedfs-filer \ --network "${NETWORK_NAME}" \ -p 8888:8888 \ -v p1ctos4ve-seaweedfs-filer-data:/data \ chrislusf/seaweedfs:latest \ filer -master=p1ctos4ve-seaweedfs-master:9333 # Step 7: Start SeaweedFS S3 echo -e "${YELLOW}๐Ÿ“ฆ Step 7: Starting SeaweedFS S3...${NC}" docker run -d \ --name p1ctos4ve-seaweedfs-s3 \ --network "${NETWORK_NAME}" \ -p 8333:8333 \ -v p1ctos4ve-seaweedfs-s3-data:/data \ --entrypoint /bin/sh \ chrislusf/seaweedfs:latest \ -c 'mkdir -p /data && cat > /data/s3.json << '\''EOF'\'' { "identities": [ { "name": "anonymous", "credentials": [ { "accessKey": "", "secretKey": "" } ], "actions": ["Read:p1ctos4ve"] }, { "name": "any", "credentials": [ { "accessKey": "any", "secretKey": "any" } ], "actions": ["Admin", "Read", "Write"] } ] } EOF exec /entrypoint.sh s3 -filer=p1ctos4ve-seaweedfs-filer:8888 -port=8333 -ip.bind=0.0.0.0 -config=/data/s3.json' # Wait for services to be healthy echo -e "${YELLOW}โณ Waiting for services to be ready...${NC}" # Wait for PostgreSQL echo -n "Waiting for PostgreSQL..." for i in {1..30}; do if docker exec p1ctos4ve-postgres pg_isready -U p1ctos4ve > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" # Wait for Redis echo -n "Waiting for Redis..." for i in {1..30}; do if docker exec p1ctos4ve-redis redis-cli ping > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" # Wait for SeaweedFS master echo -n "Waiting for SeaweedFS master..." for i in {1..30}; do if curl -s http://localhost:9333/cluster/status > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" # Wait for SeaweedFS filer echo -n "Waiting for SeaweedFS filer..." for i in {1..30}; do if curl -s http://localhost:8888 > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" # Wait for SeaweedFS S3 echo -n "Waiting for SeaweedFS S3..." for i in {1..30}; do if curl -s http://localhost:8333 > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" sleep 2 # Create S3 bucket in SeaweedFS if it doesn't exist echo -e "${YELLOW}๐Ÿ“ฆ Creating S3 bucket in SeaweedFS...${NC}" BUCKET_NAME="p1ctos4ve" if ! curl -s -X PUT "http://localhost:8333/${BUCKET_NAME}" > /dev/null 2>&1; then curl -X PUT "http://localhost:8888/buckets/${BUCKET_NAME}" > /dev/null 2>&1 || true fi echo -e "${GREEN}โœ“ Bucket ready${NC}" # Step 8: Build backend echo -e "${YELLOW}๐Ÿ”จ Step 8: Building backend...${NC}" docker build -t p1ctos4ve-backend:latest -f apps/backend/Dockerfile . # Step 9: Run migrations echo -e "${YELLOW}๐Ÿ—„๏ธ Step 9: Running database migrations...${NC}" docker run --rm \ --network "${NETWORK_NAME}" \ -e DATABASE_URL="postgresql://p1ctos4ve:p1ctos4ve_password@p1ctos4ve-postgres:5432/p1ctos4ve" \ -e REDIS_URL="redis://p1ctos4ve-redis:6379" \ -e S3_ENDPOINT="http://p1ctos4ve-seaweedfs-s3:8333" \ -e S3_REGION="us-east-1" \ -e S3_BUCKET="${BUCKET_NAME}" \ -e S3_ACCESS_KEY_ID="any" \ -e S3_SECRET_ACCESS_KEY="any" \ -e S3_FORCE_PATH_STYLE="true" \ -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ -e BETTER_AUTH_URL="http://localhost:3000" \ -e BASE_URL="http://localhost:3000" \ -e NODE_ENV="production" \ -e PORT="3000" \ p1ctos4ve-backend:latest \ bun run db:migrate # Step 10: Run unit tests echo -e "${YELLOW}๐Ÿงช Step 10: Running unit tests...${NC}" docker run --rm \ --network "${NETWORK_NAME}" \ -e DATABASE_URL="postgresql://p1ctos4ve:p1ctos4ve_password@p1ctos4ve-postgres:5432/p1ctos4ve" \ -e REDIS_URL="redis://p1ctos4ve-redis:6379" \ -e S3_ENDPOINT="http://p1ctos4ve-seaweedfs-s3:8333" \ -e S3_REGION="us-east-1" \ -e S3_BUCKET="${BUCKET_NAME}" \ -e S3_ACCESS_KEY_ID="any" \ -e S3_SECRET_ACCESS_KEY="any" \ -e S3_FORCE_PATH_STYLE="true" \ -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ -e BETTER_AUTH_URL="http://localhost:3000" \ -e BASE_URL="http://localhost:3000" \ -e NODE_ENV="test" \ -e PORT="3000" \ p1ctos4ve-backend:latest \ bun test src/tests/unit/ UNIT_EXIT_CODE=$? if [ $UNIT_EXIT_CODE -eq 0 ]; then echo -e "${GREEN}โœ“ Unit tests passed${NC}" else echo -e "${RED}โœ— Unit tests failed${NC}" exit 1 fi # Step 11: Run integration tests echo -e "${YELLOW}๐Ÿ”— Step 11: Running integration tests...${NC}" echo -e "${YELLOW}Starting backend server for e2e tests...${NC}" BACKEND_CONTAINER=$(docker run -d \ --name p1ctos4ve-backend-test \ --network "${NETWORK_NAME}" \ -p 3000:3000 \ -e DATABASE_URL="postgresql://p1ctos4ve:p1ctos4ve_password@p1ctos4ve-postgres:5432/p1ctos4ve" \ -e REDIS_URL="redis://p1ctos4ve-redis:6379" \ -e S3_ENDPOINT="http://p1ctos4ve-seaweedfs-s3:8333" \ -e S3_REGION="us-east-1" \ -e S3_BUCKET="${BUCKET_NAME}" \ -e S3_ACCESS_KEY_ID="any" \ -e S3_SECRET_ACCESS_KEY="any" \ -e S3_FORCE_PATH_STYLE="true" \ -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ -e BETTER_AUTH_URL="http://localhost:3000" \ -e BASE_URL="http://localhost:3000" \ -e NODE_ENV="test" \ -e PORT="3000" \ p1ctos4ve-backend:latest) # Wait for server to be ready echo -n "Waiting for backend server to start..." for i in {1..30}; do if curl -s http://localhost:3000 > /dev/null 2>&1; then break fi echo -n "." sleep 1 done echo -e " ${GREEN}โœ“${NC}" # Run e2e tests docker exec p1ctos4ve-backend-test sh -c "bun test --preload ./src/tests/setup.ts src/tests/e2e/" || \ docker run --rm \ --network "${NETWORK_NAME}" \ -e DATABASE_URL="postgresql://p1ctos4ve:p1ctos4ve_password@p1ctos4ve-postgres:5432/p1ctos4ve" \ -e REDIS_URL="redis://p1ctos4ve-redis:6379" \ -e S3_ENDPOINT="http://p1ctos4ve-seaweedfs-s3:8333" \ -e S3_REGION="us-east-1" \ -e S3_BUCKET="${BUCKET_NAME}" \ -e S3_ACCESS_KEY_ID="any" \ -e S3_SECRET_ACCESS_KEY="any" \ -e S3_FORCE_PATH_STYLE="true" \ -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ -e BETTER_AUTH_URL="http://p1ctos4ve-backend-test:3000" \ -e BASE_URL="http://p1ctos4ve-backend-test:3000" \ -e NODE_ENV="test" \ -e PORT="3000" \ p1ctos4ve-backend:latest \ sh -c "find src/tests/e2e -name '*.test.ts' -exec sed -i 's|http://localhost:3000|http://p1ctos4ve-backend-test:3000|g' {} \; && bun test --preload ./src/tests/setup.ts src/tests/e2e/" TEST_EXIT_CODE=$? echo -e "${YELLOW}Stopping test backend server...${NC}" docker stop p1ctos4ve-backend-test > /dev/null 2>&1 || true docker rm p1ctos4ve-backend-test > /dev/null 2>&1 || true if [ $TEST_EXIT_CODE -eq 0 ]; then echo -e "${GREEN}โœ“ Integration tests passed${NC}" else echo -e "${RED}โœ— Integration tests failed${NC}" exit 1 fi # Step 12: Start the application echo -e "${YELLOW}๐Ÿš€ Step 12: Starting the application...${NC}" echo -e "${GREEN}Application will be available at http://localhost:3000${NC}" echo -e "${YELLOW}Press Ctrl+C to stop${NC}" docker run --rm \ --network "${NETWORK_NAME}" \ -p 3000:3000 \ -e DATABASE_URL="postgresql://p1ctos4ve:p1ctos4ve_password@p1ctos4ve-postgres:5432/p1ctos4ve" \ -e REDIS_URL="redis://p1ctos4ve-redis:6379" \ -e S3_ENDPOINT="http://p1ctos4ve-seaweedfs-s3:8333" \ -e S3_REGION="us-east-1" \ -e S3_BUCKET="${BUCKET_NAME}" \ -e S3_ACCESS_KEY_ID="any" \ -e S3_SECRET_ACCESS_KEY="any" \ -e S3_FORCE_PATH_STYLE="true" \ -e BETTER_AUTH_SECRET="$(openssl rand -hex 32)" \ -e BETTER_AUTH_URL="http://localhost:3000" \ -e BASE_URL="http://localhost:3000" \ -e NODE_ENV="production" \ -e PORT="3000" \ p1ctos4ve-backend:latest