-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.sh
More file actions
executable file
·272 lines (232 loc) · 8.87 KB
/
Copy pathsetup.sh
File metadata and controls
executable file
·272 lines (232 loc) · 8.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#!/usr/bin/env bash
set -euo pipefail
# ============================================
# Koulu Development Environment Setup
# One-time setup: prerequisites, env files,
# Docker, dependencies, migrations, seeding.
# ============================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/scripts/project-env.sh"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
# Check if a command exists
check_command() {
if ! command -v "$1" &> /dev/null; then
error "$1 is not installed. $2"
fi
}
# Compare versions (returns 0 if $1 >= $2)
version_gte() {
[ "$(printf '%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}
print_worktree_banner
echo "=========================================="
echo " Koulu Development Environment Setup"
echo "=========================================="
echo ""
# ============================================
# STEP 0: Install Missing Prerequisites
# ============================================
source "${SCRIPT_DIR}/scripts/install-prereqs.sh"
# ============================================
# STEP 1: Check Prerequisites
# ============================================
info "Checking prerequisites..."
# Check Python
check_command python3 "Please install Python 3.11+ from https://www.python.org/downloads/"
PYTHON_VERSION=$(python3 --version | grep -oE '[0-9]+\.[0-9]+')
if ! version_gte "$PYTHON_VERSION" "3.11"; then
error "Python 3.11+ required, found $PYTHON_VERSION. Please upgrade Python."
fi
success "Python $PYTHON_VERSION"
# Check pip
check_command pip3 "Please install pip: python3 -m ensurepip --upgrade"
success "pip installed"
# Check Node.js
check_command node "Please install Node.js 18+ from https://nodejs.org/"
NODE_VERSION=$(node --version | grep -oE '[0-9]+\.[0-9]+')
if ! version_gte "$NODE_VERSION" "18.0"; then
error "Node.js 18+ required, found $NODE_VERSION. Please upgrade Node.js."
fi
success "Node.js $NODE_VERSION"
# Check npm
check_command npm "Please install npm (comes with Node.js)"
success "npm installed"
# Check Docker
check_command docker "Please install Docker from https://docs.docker.com/get-docker/"
success "Docker installed"
# Check Docker Compose (v2 style)
if docker compose version &> /dev/null; then
success "Docker Compose (v2) installed"
COMPOSE_CMD="docker compose"
elif command -v docker-compose &> /dev/null; then
success "Docker Compose (v1) installed"
COMPOSE_CMD="docker-compose"
else
error "Docker Compose not found. Please install Docker Compose."
fi
# Check if Docker daemon is running
if ! docker info &> /dev/null; then
error "Docker daemon is not running. Please start Docker and try again."
fi
success "Docker daemon is running"
echo ""
# ============================================
# STEP 2: Setup Environment Files
# ============================================
info "Setting up environment files..."
# Generate .env with computed ports
if [ -f .env.example ]; then
if [ ! -f .env ]; then
cp .env.example .env
success "Created .env from .env.example"
else
success ".env already exists"
fi
# Patch port-dependent values in .env to match computed ports
sed -i "s|^KOULU_PG_PORT=.*|KOULU_PG_PORT=${KOULU_PG_PORT}|" .env
sed -i "s|^KOULU_REDIS_PORT=.*|KOULU_REDIS_PORT=${KOULU_REDIS_PORT}|" .env
sed -i "s|^KOULU_MAIL_SMTP_PORT=.*|KOULU_MAIL_SMTP_PORT=${KOULU_MAIL_SMTP_PORT}|" .env
sed -i "s|^KOULU_MAIL_WEB_PORT=.*|KOULU_MAIL_WEB_PORT=${KOULU_MAIL_WEB_PORT}|" .env
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgresql+asyncpg://koulu:koulu_dev_password@localhost:${KOULU_PG_PORT}/koulu|" .env
sed -i "s|^REDIS_URL=.*|REDIS_URL=redis://localhost:${KOULU_REDIS_PORT}/0|" .env
sed -i "s|^MAIL_PORT=.*|MAIL_PORT=${KOULU_MAIL_SMTP_PORT}|" .env
sed -i "s|^FRONTEND_URL=.*|FRONTEND_URL=http://localhost:${KOULU_FRONTEND_PORT}|" .env
success "Patched .env with computed ports (PG:${KOULU_PG_PORT} Redis:${KOULU_REDIS_PORT} Mail:${KOULU_MAIL_SMTP_PORT}/${KOULU_MAIL_WEB_PORT} Frontend:${KOULU_FRONTEND_PORT})"
else
error ".env.example not found. Cannot create .env file."
fi
if [ -f frontend/.env.example ]; then
if [ ! -f frontend/.env ]; then
cp frontend/.env.example frontend/.env
success "Created frontend/.env from frontend/.env.example"
else
success "frontend/.env already exists"
fi
# Patch frontend .env with correct backend API URL and project name
sed -i "s|^VITE_API_URL=.*|VITE_API_URL=http://localhost:${KOULU_BACKEND_PORT}/api/v1|" frontend/.env
# Add or update project name for UI display
if grep -q "^VITE_PROJECT_NAME=" frontend/.env 2>/dev/null; then
sed -i "s|^VITE_PROJECT_NAME=.*|VITE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}|" frontend/.env
else
echo "VITE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}" >> frontend/.env
fi
success "Patched frontend/.env with backend URL (http://localhost:${KOULU_BACKEND_PORT}/api/v1) and project name (${COMPOSE_PROJECT_NAME})"
else
warn "frontend/.env.example not found. Skipping frontend .env setup."
fi
echo ""
# ============================================
# STEP 3: Start Docker Containers
# ============================================
info "Starting Docker containers (project: ${COMPOSE_PROJECT_NAME})..."
# Remove any stale containers with our names (e.g., left over from E2E tests or a different compose project).
# Data is preserved in named volumes — only the container instances are removed.
VOLUME_PREFIX="${KOULU_VOLUME_PREFIX:-koulu}"
for svc in postgres redis mailhog; do
cname="${VOLUME_PREFIX}_${svc}"
if docker container inspect "$cname" &>/dev/null 2>&1; then
warn "Removing stale container: $cname"
docker rm -f "$cname" 2>/dev/null || true
fi
done
$COMPOSE_CMD up -d --remove-orphans
success "Containers started"
# Wait for PostgreSQL to be healthy
info "Waiting for PostgreSQL to be ready..."
MAX_RETRIES=30
RETRY_COUNT=0
until $COMPOSE_CMD exec -T postgres pg_isready -U koulu &> /dev/null; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
error "PostgreSQL failed to start after $MAX_RETRIES attempts"
fi
sleep 1
done
success "PostgreSQL is ready"
# Wait for Redis to be healthy
info "Waiting for Redis to be ready..."
RETRY_COUNT=0
until $COMPOSE_CMD exec -T redis redis-cli ping &> /dev/null; do
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
error "Redis failed to start after $MAX_RETRIES attempts"
fi
sleep 1
done
success "Redis is ready"
success "All containers are running"
echo ""
# ============================================
# STEP 4: Install Python Dependencies
# ============================================
info "Installing Python dependencies..."
# Check if we're in a virtual environment
if [ -z "${VIRTUAL_ENV:-}" ]; then
warn "No virtual environment detected. Consider using one:"
warn " eval \"\$(pyenv init -)\" && eval \"\$(pyenv virtualenv-init -)\" && pyenv activate koulu"
fi
pip3 install -e ".[dev]" --quiet
success "Python dependencies installed"
echo ""
# ============================================
# STEP 5: Run Database Migrations
# ============================================
info "Running database migrations..."
if command -v alembic &> /dev/null; then
alembic upgrade head
success "Database migrations complete"
else
# Try with python -m
python3 -m alembic upgrade head
success "Database migrations complete"
fi
echo ""
# ============================================
# STEP 6: Seed Database (optional)
# ============================================
if [ -f scripts/seed_db.py ]; then
read -p "$(echo -e "${YELLOW}[INFO]${NC} Seed database with sample data? [y/N] ")" -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
info "Seeding database..."
# Export .env vars so seed_db.py can read DATABASE_URL via os.getenv
set -a
source .env
set +a
python3 scripts/seed_db.py
success "Database seeded"
else
info "Skipping database seeding"
fi
echo ""
fi
# ============================================
# STEP 7: Install Frontend Dependencies
# ============================================
info "Installing frontend dependencies..."
cd frontend
npm install --silent
cd ..
success "Frontend dependencies installed"
echo ""
# ============================================
# DONE
# ============================================
echo "=========================================="
echo -e "${GREEN} Setup Complete!${NC}"
echo "=========================================="
print_worktree_banner
echo "To start the application, run:"
echo ""
echo -e " ${BLUE}./start.sh${NC}"
echo ""