-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrun.sh
More file actions
executable file
·307 lines (264 loc) · 9.36 KB
/
run.sh
File metadata and controls
executable file
·307 lines (264 loc) · 9.36 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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#!/bin/bash
# POS Application Runner
# Runs all services in Docker containers
set -e
# Function to show help
show_help() {
cat << EOF
POS Application Runner
Usage: ./run.sh [OPTIONS]
Options:
-h, --help Show this help message
-dev, --dev Start in development mode (hot reload + LAN access)
Default: production mode (build and serve static files)
-c, --clean Remove all containers, volumes, and data
--remove-all Same as --clean
--fix-perm Fix file permissions in back/uploads
--migrate Run database migrations only (services must be running)
--no-migrate Skip automatic migration on startup
Examples:
./run.sh Start in production mode (build and serve)
./run.sh -dev Start in development mode (hot reload + LAN access)
./run.sh --clean Remove all containers and volumes
./run.sh --migrate Run pending database migrations
Development Mode:
- Frontend runs with 'ng serve' (hot reload enabled)
- Backend runs with auto-reload
- All services run in Docker containers
- Migrations run automatically on startup
Production Mode:
- Frontend is built and served as static files via nginx
- Backend runs in container
- Optimized for performance
- Migrations run automatically on startup
EOF
exit 0
}
# Function to cleanup background processes
cleanup() {
echo ""
echo "Shutting down services..."
if [ "$DEV_MODE" = true ]; then
docker compose $ENV_FILE down
else
docker compose $ENV_FILE -f docker-compose.yml -f docker-compose.prod.yml down
fi
exit 0
}
# Function to remove everything including volumes
remove_all() {
echo "Removing all POS containers, volumes, and data..."
# Check if config.env exists
if [ ! -f "config.env" ]; then
echo "WARNING: config.env not found, using defaults..."
ENV_FILE=""
else
ENV_FILE="--env-file config.env"
fi
# Stop and remove containers with volumes
echo "Stopping and removing containers..."
docker compose $ENV_FILE down -v 2>/dev/null || true
docker compose $ENV_FILE -f docker-compose.prod.yml down -v 2>/dev/null || true
# Remove all POS-related volumes (more robust)
echo "Removing volumes..."
VOLUMES=$(docker volume ls --format "{{.Name}}" | grep -E "^pos_" || true)
if [ -n "$VOLUMES" ]; then
echo "$VOLUMES" | xargs docker volume rm 2>/dev/null || true
fi
# Remove any orphaned containers
echo "Cleaning up orphaned containers..."
CONTAINERS=$(docker ps -a --filter "name=pos-" --format "{{.ID}}" || true)
if [ -n "$CONTAINERS" ]; then
echo "$CONTAINERS" | xargs docker rm -f 2>/dev/null || true
fi
echo ""
echo "All POS containers and volumes removed."
echo "All data has been deleted. You'll need to recreate your database on next start."
exit 0
}
# Function to fix upload permissions
fix_permissions() {
echo "Fixing permissions for back/uploads..."
if [ -d "back/uploads" ]; then
# Check for any files owned by root (UID 0) recursively
ROOT_OWNED=$(find back/uploads -user 0 2>/dev/null | head -1)
if [ -n "$ROOT_OWNED" ]; then
echo "Found files owned by root. Fixing ownership (may prompt for sudo password)..."
sudo chown -R "$USER:$USER" back/uploads || {
echo "ERROR: Failed to change ownership. Please run: sudo chown -R \$USER:\$USER back/uploads"
exit 1
}
echo "Permissions fixed."
else
echo "back/uploads is already owned by $USER"
echo "No permission issues found."
fi
else
echo "Creating back/uploads/providers with correct ownership..."
mkdir -p back/uploads/providers
echo "Directories created."
fi
exit 0
}
# Function to run database migrations
run_migrations() {
echo "Running database migrations..."
# Check if config.env exists
if [ ! -f "config.env" ]; then
echo "WARNING: config.env not found, using defaults..."
ENV_FILE=""
else
ENV_FILE="--env-file config.env"
fi
# Check if backend container is running
if ! docker compose $ENV_FILE ps --status=running --services 2>/dev/null | grep -q "^back$"; then
echo "ERROR: Backend container (pos-back) is not running."
echo "Start the services first with: ./run.sh or ./run.sh -dev"
exit 1
fi
# Run migrations inside the backend container
docker compose $ENV_FILE exec back python -m app.migrate
echo "Migrations complete."
}
# Function to run migrations only (standalone command)
run_migrations_only() {
run_migrations
exit 0
}
# Function to wait for database and run migrations in background
run_migrations_background() {
local ENV_FILE="$1"
echo "⏳ Waiting for backend to be ready..."
# Wait for backend health endpoint (max 60 seconds)
local max_attempts=30
local attempt=0
local wait_seconds=2
local max_wait=$((max_attempts * wait_seconds))
local elapsed=0
while [ $attempt -lt $max_attempts ]; do
# Use curl to check the health endpoint through HAProxy
if curl -sf http://localhost:4202/api/health > /dev/null 2>&1; then
echo "✅ Backend is ready!"
break
fi
attempt=$((attempt + 1))
elapsed=$((attempt * wait_seconds))
echo "Still waiting for backend... ${elapsed}s elapsed of ${max_wait}s"
sleep "$wait_seconds"
done
if [ $attempt -eq $max_attempts ]; then
echo "⚠️ Timeout waiting for backend. Migrations may need to be run manually."
echo "💡 Run: ./run.sh --migrate"
return 1
fi
# Run migrations
echo "🗄️ Running database migrations..."
if docker compose $ENV_FILE exec -T pos-back python -m app.migrate 2>/dev/null; then
echo "✅ Migrations applied successfully!"
else
echo "⚠️ Migration failed or already applied. Check logs if needed."
fi
}
# Parse command line arguments
DEV_MODE=false
ENV_FILE=""
SKIP_MIGRATE=false
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
;;
-dev|--dev)
DEV_MODE=true
shift
;;
-c|--clean|--remove-all)
remove_all
;;
--fix-perm|--fix-permissions)
fix_permissions
;;
--migrate)
run_migrations_only
;;
--no-migrate)
SKIP_MIGRATE=true
shift
;;
*)
echo "ERROR: Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
# Set trap to cleanup on script exit
trap cleanup SIGINT SIGTERM
# Check if config.env exists
if [ ! -f "config.env" ]; then
echo "ERROR: config.env not found. Copy config.env.example to config.env and edit if needed."
exit 1
fi
ENV_FILE="--env-file config.env"
# Export UID and GID for Docker Compose (using different names because UID is readonly in bash)
# This ensures the backend container runs as the host user
export DOCKER_UID=$(id -u)
export DOCKER_GID=$(id -g)
# Pre-create upload directories with correct ownership
# This prevents Docker from creating them as root
if [ ! -d "back/uploads/providers" ]; then
echo "Pre-creating back/uploads/providers directory..."
mkdir -p back/uploads/providers
fi
# Determine which compose file to use
if [ "$DEV_MODE" = true ]; then
echo "Starting POS Application in DEVELOPMENT mode..."
COMPOSE_FILE=""
MODE_DESC="Development (hot reload + LAN access)"
echo "📱 LAN access enabled for mobile testing"
export CORS_ORIGINS="*"
else
echo "Starting POS Application in PRODUCTION mode..."
COMPOSE_FILE="-f docker-compose.yml -f docker-compose.prod.yml"
MODE_DESC="Production (optimized build)"
fi
# Start all services with Docker Compose
echo "Starting all services in containers..."
echo "📋 Mode: $MODE_DESC"
if [ "$SKIP_MIGRATE" = true ]; then
echo "Migrations: Skipped (--no-migrate)"
else
echo "Migrations: Auto-run on startup"
fi
echo ""
# Start services in detached mode first, run migrations, then attach to logs
docker compose $ENV_FILE $COMPOSE_FILE up --build -d
# Run migrations automatically unless skipped
if [ "$SKIP_MIGRATE" = false ]; then
run_migrations_background "$ENV_FILE"
fi
echo ""
if [ "$DEV_MODE" = true ]; then
echo "POS Application started."
echo "Frontend: http://localhost:4202"
echo "Backend API: http://localhost:4202/api"
echo "Health check: http://localhost:4202/api/health"
echo "DB Health check: http://localhost:4202/api/health/db"
echo "API Docs: http://localhost:4202/api/docs"
else
echo "POS Application started."
echo "Frontend: http://localhost:4200"
echo "Backend API: http://localhost:4200/api"
echo "Health check: http://localhost:4200/api/health"
echo "DB Health check: http://localhost:4200/api/health/db"
echo "API Docs: http://localhost:4200/api/docs"
fi
echo ""
echo "Press Ctrl+C to stop all services"
echo ""
echo "Tips:"
echo " ./run.sh --clean Remove all containers and volumes"
echo " ./run.sh --migrate Run database migrations manually"
echo ""
# Now attach to logs (this will run in foreground)
docker compose $ENV_FILE $COMPOSE_FILE logs -f