Skip to content

Commit 46b18db

Browse files
Merge pull request #70 from ithsjava25/issue/69
Startup script
2 parents d1411f2 + cc7323b commit 46b18db

2 files changed

Lines changed: 237 additions & 0 deletions

File tree

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@ Spring Boot application for case management with a Thymeleaf UI, PostgreSQL, and
1010

1111
## Start the application (local development)
1212

13+
<<<<<<< issue/69
14+
### Quick start (recommended on Windows)
15+
16+
Run one command to perform all startup steps:
17+
18+
```powershell
19+
.\start-local.ps1
20+
```
21+
22+
Show full command output instead of fun/quiet mode:
23+
24+
```powershell
25+
.\start-local.ps1 --serious
26+
```
27+
28+
The script will:
29+
- Verify Docker is available and the engine is running
30+
- Start infrastructure with `docker compose up -d`
31+
- Start Spring Boot with profile `local`
32+
33+
=======
34+
>>>>>>> main
1335
### 0) Verify Docker is running (Windows)
1436

1537
Before running `docker compose up -d`, make sure Docker Desktop is started and the Linux engine is running.
@@ -112,8 +134,14 @@ docker compose up -d
112134
```
113135

114136
- If you want to keep your local PostgreSQL running, map Docker PostgreSQL to another host port:
137+
<<<<<<< issue/69
138+
1. Edit `docker-compose.yml` PostgreSQL ports from `"5432:5432"` to `"5433:5432"`.
139+
2. Edit `src/main/resources/application.properties` database URL from `localhost:5432` to `localhost:5433`.
140+
3. Run `docker compose up -d` again.
141+
=======
115142
1. Edit `docker-compose.yml` PostgreSQL ports from `"5432:5432"` to `"5433:5432"`.
116143
2. Edit `src/main/resources/application.properties` database URL from `localhost:5432` to `localhost:5433`.
117144
3. Run `docker compose up -d` again.
145+
>>>>>>> main
118146
- App starts but login fails:
119147
- Confirm you started Spring with profile `local` so `data-local.sql` is loaded.

start-local.ps1

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
param(
2+
[switch]$NoDockerCheck,
3+
[switch]$Serious
4+
)
5+
6+
$ErrorActionPreference = "Stop"
7+
8+
if ($args -contains "--serious") {
9+
$Serious = $true
10+
}
11+
12+
function Assert-CommandExists {
13+
param([string]$CommandName)
14+
15+
if (-not (Get-Command $CommandName -ErrorAction SilentlyContinue)) {
16+
throw "Command '$CommandName' was not found. Install it and try again."
17+
}
18+
}
19+
20+
function Invoke-CommandWithMode {
21+
param(
22+
[scriptblock]$Command
23+
)
24+
25+
$previousErrorActionPreference = $ErrorActionPreference
26+
$tempLog = $null
27+
28+
try {
29+
$ErrorActionPreference = "Continue"
30+
31+
if ($Serious) {
32+
& $Command 2>&1
33+
}
34+
else {
35+
$tempLog = [System.IO.Path]::GetTempFileName()
36+
& $Command *> $tempLog
37+
38+
if ($LASTEXITCODE -ne 0) {
39+
Write-Host "Command failed in quiet mode (exit code: $LASTEXITCODE)." -ForegroundColor Red
40+
Write-Host "Recent output from $tempLog:" -ForegroundColor DarkRed
41+
Get-Content -Path $tempLog -Tail 25 | ForEach-Object { Write-Host $_ -ForegroundColor DarkGray }
42+
}
43+
}
44+
45+
return $LASTEXITCODE
46+
}
47+
finally {
48+
if ($tempLog -and (Test-Path $tempLog)) {
49+
Remove-Item -Path $tempLog -Force -ErrorAction SilentlyContinue
50+
}
51+
$ErrorActionPreference = $previousErrorActionPreference
52+
}
53+
}
54+
55+
function Write-FunStatus {
56+
param(
57+
[string[]]$Messages,
58+
[ConsoleColor]$Color = [ConsoleColor]::Cyan
59+
)
60+
61+
if ($Messages -and $Messages.Count -gt 0) {
62+
$index = Get-Random -Minimum 0 -Maximum $Messages.Count
63+
Write-Host $Messages[$index] -ForegroundColor $Color
64+
}
65+
}
66+
67+
function Pause-ForEnjoyment {
68+
if (-not $Serious) {
69+
Start-Sleep -Seconds 2
70+
}
71+
}
72+
73+
if ($Serious) {
74+
Write-Host "Starting local development environment (serious mode)..." -ForegroundColor Cyan
75+
}
76+
else {
77+
Write-FunStatus -Messages @(
78+
"Waking up the dev servers..."
79+
"Turning caffeine into deployment energy..."
80+
"Calibrating keyboard clicks and backend magic..."
81+
) -Color Cyan
82+
}
83+
Pause-ForEnjoyment
84+
85+
Assert-CommandExists -CommandName "docker"
86+
87+
if (-not $NoDockerCheck) {
88+
if ($Serious) {
89+
Write-Host "Checking Docker engine..." -ForegroundColor Yellow
90+
}
91+
else {
92+
Write-FunStatus -Messages @(
93+
"Knocking on Docker's front door..."
94+
"Asking Docker politely to wake up..."
95+
"Reading Docker's morning mood..."
96+
) -Color Yellow
97+
}
98+
Pause-ForEnjoyment
99+
$engineReady = $false
100+
$maxAttempts = 12
101+
102+
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
103+
$dockerInfoExitCode = Invoke-CommandWithMode -Command { docker info }
104+
if ($dockerInfoExitCode -eq 0) {
105+
$engineReady = $true
106+
break
107+
}
108+
109+
if ($attempt -lt $maxAttempts) {
110+
Write-FunStatus -Messages @(
111+
"Fetching coffee for the engineers... Docker not ready yet ($attempt/$maxAttempts). Retrying in 5 seconds..."
112+
"Asking the marketing department to leave... Docker still booting ($attempt/$maxAttempts). Retrying in 5 seconds..."
113+
"Negotiating with the container gods... still waiting ($attempt/$maxAttempts). Retrying in 5 seconds..."
114+
) -Color DarkYellow
115+
Start-Sleep -Seconds 5
116+
}
117+
}
118+
119+
if (-not $engineReady) {
120+
throw @"
121+
Docker engine is not available yet.
122+
Start Docker Desktop, wait until 'Engine running', then run this script again.
123+
Tip: verify manually with 'docker info' (it should return without daemon errors).
124+
"@
125+
}
126+
}
127+
128+
if ($Serious) {
129+
Write-Host "Starting infrastructure services (PostgreSQL + MinIO)..." -ForegroundColor Yellow
130+
}
131+
else {
132+
Write-FunStatus -Messages @(
133+
"Summoning PostgreSQL and MinIO..."
134+
"Spinning up databases and object storage wizardry..."
135+
"Hiring tiny container elves for infrastructure..."
136+
) -Color Yellow
137+
}
138+
Pause-ForEnjoyment
139+
$composeExitCode = Invoke-CommandWithMode -Command { docker compose up -d }
140+
141+
if ($composeExitCode -ne 0) {
142+
throw "docker compose failed. Fix the error above and retry."
143+
}
144+
145+
if ($Serious) {
146+
Write-Host "Starting Spring Boot with profile 'local'..." -ForegroundColor Yellow
147+
}
148+
else {
149+
Write-FunStatus -Messages @(
150+
"Launching Spring Boot thrusters..."
151+
"Convincing Java to do something useful..."
152+
"Whispering encouragement to the JVM..."
153+
) -Color Yellow
154+
}
155+
Write-Host "App URL: http://localhost:8080" -ForegroundColor Green
156+
Write-Host "Press Ctrl+C to stop the application." -ForegroundColor Green
157+
Write-Host "Admin login (local profile):" -ForegroundColor Magenta
158+
Write-Host "Username: admin@traumateam.com" -ForegroundColor Magenta
159+
Write-Host "Password: password" -ForegroundColor Magenta
160+
Write-Host "Starting web browser for your lazy a**" -ForegroundColor Green
161+
Write-Host "Opening browser at http://localhost:8080 ..." -ForegroundColor Green
162+
if (-not $Serious) {
163+
Write-Host "Quiet mode active: app logs are hidden while running." -ForegroundColor DarkGreen
164+
Write-Host "If the prompt does not return, the app is still running in this terminal." -ForegroundColor DarkGreen
165+
Write-Host "Use --serious to see full startup logs." -ForegroundColor DarkGreen
166+
}
167+
Pause-ForEnjoyment
168+
169+
$browserOpenTimeoutSeconds = 90
170+
$browserPollIntervalSeconds = 2
171+
$browserReadyJob = Start-Job -ScriptBlock {
172+
param(
173+
[int]$TimeoutSeconds,
174+
[int]$PollIntervalSeconds
175+
)
176+
177+
$uri = "http://localhost:8080"
178+
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
179+
180+
while ((Get-Date) -lt $deadline) {
181+
try {
182+
$response = Invoke-WebRequest -Uri $uri -Method GET -TimeoutSec 3 -ErrorAction Stop
183+
if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 400) {
184+
Start-Process $uri
185+
return
186+
}
187+
}
188+
catch {
189+
# App not ready yet; continue polling until timeout.
190+
}
191+
192+
Start-Sleep -Seconds $PollIntervalSeconds
193+
}
194+
} -ArgumentList $browserOpenTimeoutSeconds, $browserPollIntervalSeconds
195+
196+
$mavenExitCode = Invoke-CommandWithMode -Command { .\mvnw spring-boot:run "-Dspring-boot.run.profiles=local" }
197+
198+
if ($mavenExitCode -ne 0) {
199+
if ($browserReadyJob) {
200+
Stop-Job -Job $browserReadyJob -ErrorAction SilentlyContinue
201+
Remove-Job -Job $browserReadyJob -Force -ErrorAction SilentlyContinue
202+
}
203+
if ($mavenExitCode -in @(130, 1)) {
204+
Write-Warning "Spring Boot terminated by user (Ctrl+C)"
205+
}
206+
else {
207+
throw "Spring Boot failed with exit code $mavenExitCode. Re-run with --serious to see detailed logs."
208+
}
209+
}

0 commit comments

Comments
 (0)