Skip to content

Commit 02aafb2

Browse files
authored
Add database seeding script (bash and powershell)
call server/seed_database to initialize the database. The script is idempotent it only seeds the data if the tables are empty. Code from the start-app has been extracted into a common module to be used both by the seeding script as well as the start-app
1 parent 1f13674 commit 02aafb2

File tree

6 files changed

+486
-116
lines changed

6 files changed

+486
-116
lines changed

scripts/common.ps1

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Define color codes for PowerShell
2+
$Script:Green = [System.ConsoleColor]::Green
3+
$Script:DefaultColor = [System.ConsoleColor]::White
4+
5+
# Get the project root directory
6+
function Get-ProjectRoot {
7+
return (Get-Item $PSScriptRoot).Parent.FullName
8+
}
9+
10+
# Create and activate virtual environment
11+
function Initialize-VirtualEnvironment {
12+
param(
13+
[string]$ProjectRoot
14+
)
15+
16+
$VenvPath = Join-Path $ProjectRoot "venv"
17+
18+
# Create virtual environment if it doesn't exist
19+
if (-not (Test-Path $VenvPath)) {
20+
Write-Host "Creating virtual environment..."
21+
python -m venv $VenvPath
22+
}
23+
24+
# Activate virtual environment
25+
try {
26+
if ($IsWindows) {
27+
& "$VenvPath/Scripts/Activate.ps1"
28+
} else {
29+
& bash -c 'source "'+$VenvPath+'/bin/activate"'
30+
}
31+
Write-Host "Virtual environment activated"
32+
return $true
33+
} catch {
34+
Write-Warning "Failed to activate virtual environment: $_"
35+
return $false
36+
}
37+
}
38+
39+
# Install Python dependencies
40+
function Install-PythonDependencies {
41+
param(
42+
[string]$ProjectRoot
43+
)
44+
45+
$RequirementsPath = Join-Path $ProjectRoot "server/requirements.txt"
46+
47+
if (Test-Path $RequirementsPath) {
48+
Write-Host "Installing Python dependencies..."
49+
pip install -r $RequirementsPath
50+
return $LASTEXITCODE -eq 0
51+
} else {
52+
Write-Warning "Requirements file not found at $RequirementsPath; skipping pip install."
53+
return $false
54+
}
55+
}
56+
57+
# Run Python script safely
58+
function Invoke-PythonScript {
59+
param(
60+
[string]$ScriptPath,
61+
[string]$WorkingDirectory = $null
62+
)
63+
64+
if (Test-Path $ScriptPath) {
65+
Write-Host "Running Python script: $ScriptPath"
66+
if ($WorkingDirectory) {
67+
$oldLocation = Get-Location
68+
Set-Location $WorkingDirectory
69+
}
70+
71+
try {
72+
& python $ScriptPath
73+
return $LASTEXITCODE -eq 0
74+
} finally {
75+
if ($WorkingDirectory) {
76+
Set-Location $oldLocation
77+
}
78+
}
79+
} else {
80+
Write-Warning "Python script not found at $ScriptPath; skipping execution."
81+
return $false
82+
}
83+
}
84+
85+
# Setup Flask environment variables
86+
function Set-FlaskEnvironment {
87+
$env:FLASK_DEBUG = 1
88+
$env:FLASK_PORT = 5100
89+
}
90+
91+
# Start a process with proper error handling
92+
function Start-ManagedProcess {
93+
param(
94+
[string]$FilePath,
95+
[string]$WorkingDirectory,
96+
[string[]]$ArgumentList,
97+
[string]$ProcessName
98+
)
99+
100+
try {
101+
Write-Host "Starting $ProcessName..."
102+
$process = Start-Process $FilePath `
103+
-WorkingDirectory $WorkingDirectory `
104+
-ArgumentList $ArgumentList `
105+
-PassThru `
106+
-NoNewWindow
107+
108+
return $process
109+
} catch {
110+
Write-Warning "Failed to start $ProcessName : $_"
111+
return $null
112+
}
113+
}
114+
115+
# Cleanup function for process management
116+
function Stop-ManagedProcesses {
117+
param(
118+
[System.Diagnostics.Process[]]$Processes,
119+
[string]$InitialDirectory
120+
)
121+
122+
Write-Host "Shutting down servers..."
123+
124+
foreach ($process in $Processes) {
125+
if ($process -and -not $process.HasExited) {
126+
try {
127+
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
128+
} catch {
129+
Write-Warning "Failed to stop process $($process.Id): $_"
130+
}
131+
}
132+
}
133+
134+
# Deactivate virtual environment if it exists
135+
if (Test-Path Function:\deactivate) {
136+
deactivate
137+
}
138+
139+
# Return to initial directory
140+
if ($InitialDirectory) {
141+
Set-Location $InitialDirectory
142+
}
143+
}
144+
145+
# Print colored success message
146+
function Write-Success {
147+
param([string]$Message)
148+
Write-Host $Message -ForegroundColor $Script:Green
149+
}
150+
151+
# Navigate to project root if in scripts directory
152+
function Set-ProjectRoot {
153+
if ((Split-Path -Path (Get-Location) -Leaf) -eq "scripts") {
154+
Set-Location ..
155+
}
156+
}
157+
158+
# Get appropriate NPM command based on OS
159+
function Get-NpmCommand {
160+
if ($IsWindows) {
161+
return "npm.cmd"
162+
} else {
163+
return "npm"
164+
}
165+
}
166+
167+
# Install Node.js dependencies
168+
function Install-NodeDependencies {
169+
param(
170+
[string]$Directory
171+
)
172+
173+
$oldLocation = Get-Location
174+
try {
175+
Set-Location $Directory -ErrorAction Stop
176+
Write-Host "Installing Node.js dependencies in $Directory..."
177+
npm install
178+
return $LASTEXITCODE -eq 0
179+
} catch {
180+
Write-Warning "Failed to install Node.js dependencies: $_"
181+
return $false
182+
} finally {
183+
Set-Location $oldLocation
184+
}
185+
}

scripts/common.sh

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#!/bin/bash
2+
3+
# Color codes
4+
export GREEN='\033[0;32m'
5+
export NC='\033[0m' # No Color
6+
7+
# Get the project root directory
8+
get_project_root() {
9+
local index="${1:-0}"
10+
local script_dir="$(cd "$(dirname "${BASH_SOURCE[$index]}")" && pwd)"
11+
echo "$script_dir/.."
12+
}
13+
14+
# Get the appropriate Python command based on OS
15+
get_python_command() {
16+
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
17+
echo "py"
18+
else
19+
echo "python3"
20+
fi
21+
}
22+
23+
# Create and activate virtual environment
24+
setup_virtual_env() {
25+
local project_root="$1"
26+
local python_cmd=$(get_python_command)
27+
28+
cd "$project_root" || {
29+
echo "Error: Could not navigate to project root: $project_root"
30+
return 1
31+
}
32+
33+
# Create virtual environment if it doesn't exist
34+
if [[ ! -d "venv" ]]; then
35+
echo "Creating virtual environment..."
36+
$python_cmd -m venv venv
37+
fi
38+
39+
# Activate virtual environment
40+
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
41+
source venv/Scripts/activate || . venv/Scripts/activate
42+
else
43+
source venv/bin/activate || . venv/bin/activate
44+
fi
45+
46+
if [[ $? -ne 0 ]]; then
47+
echo "Error: Could not activate virtual environment"
48+
return 1
49+
fi
50+
51+
echo "Virtual environment activated"
52+
return 0
53+
}
54+
55+
# Install Python dependencies
56+
install_python_deps() {
57+
local project_root="$1"
58+
59+
if [[ -f "$project_root/server/requirements.txt" ]]; then
60+
echo "Installing Python dependencies..."
61+
pip install -r "$project_root/server/requirements.txt"
62+
return $?
63+
else
64+
echo "Warning: requirements.txt not found at $project_root/server/requirements.txt"
65+
return 1
66+
fi
67+
}
68+
69+
# Navigate to server directory safely
70+
navigate_to_server() {
71+
local project_root="$1"
72+
local initial_dir="$2"
73+
74+
cd "$project_root/server" || {
75+
echo "Error: server directory not found"
76+
if [[ -n "$initial_dir" ]]; then
77+
cd "$initial_dir"
78+
fi
79+
return 1
80+
}
81+
return 0
82+
}
83+
84+
# Run Python script with appropriate command
85+
run_python_script() {
86+
local script_path="$1"
87+
local python_cmd=$(get_python_command)
88+
89+
if [[ -f "$script_path" ]]; then
90+
echo "Running Python script: $script_path"
91+
$python_cmd "$script_path"
92+
return $?
93+
else
94+
echo "Error: Python script not found: $script_path"
95+
return 1
96+
fi
97+
}
98+
99+
# Cleanup function for process management
100+
cleanup_processes() {
101+
local server_pid="$1"
102+
local client_pid="$2"
103+
local initial_dir="$3"
104+
105+
echo "Shutting down servers..."
106+
107+
# Kill processes and their child processes
108+
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
109+
[[ -n "$server_pid" ]] && taskkill //F //T //PID $server_pid 2>/dev/null
110+
[[ -n "$client_pid" ]] && taskkill //F //T //PID $client_pid 2>/dev/null
111+
else
112+
# Send SIGTERM first to allow graceful shutdown
113+
[[ -n "$server_pid" ]] && kill -TERM $server_pid 2>/dev/null
114+
[[ -n "$client_pid" ]] && kill -TERM $client_pid 2>/dev/null
115+
116+
# Wait briefly for graceful shutdown
117+
sleep 2
118+
119+
# Then force kill if still running
120+
if [[ -n "$server_pid" ]] && ps -p $server_pid > /dev/null 2>&1; then
121+
pkill -P $server_pid 2>/dev/null
122+
kill -9 $server_pid 2>/dev/null
123+
fi
124+
125+
if [[ -n "$client_pid" ]] && ps -p $client_pid > /dev/null 2>&1; then
126+
pkill -P $client_pid 2>/dev/null
127+
kill -9 $client_pid 2>/dev/null
128+
fi
129+
fi
130+
131+
# Deactivate virtual environment if active
132+
if [[ -n "${VIRTUAL_ENV}" ]]; then
133+
deactivate
134+
fi
135+
136+
# Return to initial directory
137+
if [[ -n "$initial_dir" ]]; then
138+
cd "$initial_dir"
139+
fi
140+
}
141+
142+
# Setup common environment variables for Flask
143+
setup_flask_env() {
144+
export FLASK_DEBUG=1
145+
export FLASK_PORT=5100
146+
}
147+
148+
# Print colored message
149+
print_success() {
150+
local message="$1"
151+
echo -e "${GREEN}${message}${NC}"
152+
}
153+
154+
# Check if running from scripts directory and navigate to project root
155+
ensure_project_root() {
156+
if [[ $(basename $(pwd)) == "scripts" ]]; then
157+
cd ..
158+
fi
159+
}

scripts/seed-database.ps1

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/pwsh
2+
3+
# Source common utilities
4+
. "$PSScriptRoot/common.ps1"
5+
6+
# Get project root
7+
$ProjectRoot = Get-ProjectRoot
8+
9+
# Initialize virtual environment
10+
if (-not (Initialize-VirtualEnvironment -ProjectRoot $ProjectRoot)) {
11+
Write-Error "Failed to initialize virtual environment"
12+
exit 1
13+
}
14+
15+
# Install Python dependencies
16+
if (-not (Install-PythonDependencies -ProjectRoot $ProjectRoot)) {
17+
Write-Warning "Failed to install Python dependencies"
18+
}
19+
20+
# Run seed database script
21+
try {
22+
$seedScript = Join-Path $ProjectRoot "server/utils/seed_database.py"
23+
Write-Host "Seeding database (idempotent)..."
24+
25+
if (-not (Invoke-PythonScript -ScriptPath $seedScript)) {
26+
Write-Warning "Seeding failed or script not found"
27+
exit 1
28+
}
29+
} catch {
30+
Write-Warning "Seeding failed: $_"
31+
exit 1
32+
}

0 commit comments

Comments
 (0)