-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun-on-release-push.ps1
More file actions
485 lines (370 loc) · 18.9 KB
/
run-on-release-push.ps1
File metadata and controls
485 lines (370 loc) · 18.9 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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# =============================================================================
#
# KETE │ Release Push
#
# Creates a production release:
# • All tests (unit, integration, end-to-end)
# • Package JAR with version imprinted in manifest
# • Push Docker images with version tag + :latest
# • Build documentation site
# • Create Git tag and GitHub Release
#
# Version format: yyyy.MM.dd.HH.mm (e.g., 2026.01.31.18.45)
#
# Usage: .\run-on-release-push.ps1
#
# =============================================================================
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
Set-Location $PSScriptRoot
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
$script:TotalSteps = 5
$script:Results = @{}
$script:StartTime = Get-Date
$script:Version = (Get-Date).ToString("yyyy.MM.dd.HH.mm")
$script:Registry = "ghcr.io/fortunen/kete"
$script:JarName = "kete.jar"
# -----------------------------------------------------------------------------
# Helper Functions
# -----------------------------------------------------------------------------
function Write-Banner {
param([string]$Title, [string]$Subtitle = "", [string]$Color = "Cyan")
$width = 80
Write-Host ""
Write-Host ("═" * $width) -ForegroundColor $Color
Write-Host ""
Write-Host " $Title" -ForegroundColor $Color
if ($Subtitle) {
Write-Host " $Subtitle" -ForegroundColor DarkGray
}
Write-Host ""
Write-Host ("═" * $width) -ForegroundColor $Color
}
function Write-StepHeader {
param([int]$Number, [string]$Name)
Write-Host ""
Write-Host ""
Write-Host " ┌──────────────────────────────────────────────────────────────────────────┐" -ForegroundColor DarkCyan
Write-Host " │ STEP $Number of $script:TotalSteps │ $($Name.ToUpper().PadRight(59))" -NoNewline -ForegroundColor DarkCyan
Write-Host " │" -ForegroundColor DarkCyan
Write-Host " └──────────────────────────────────────────────────────────────────────────┘" -ForegroundColor DarkCyan
Write-Host ""
}
function Write-Task {
param([string]$Message)
Write-Host " ► " -NoNewline -ForegroundColor DarkGray
Write-Host $Message -ForegroundColor Gray
}
function Write-TaskResult {
param([string]$Message, [bool]$Success, [string]$Duration = "")
$icon = if ($Success) { "✓" } else { "✗" }
$color = if ($Success) { "Green" } else { "Red" }
$suffix = if ($Duration) { " [$Duration]" } else { "" }
Write-Host " $icon " -NoNewline -ForegroundColor $color
Write-Host "$Message" -NoNewline -ForegroundColor White
Write-Host $suffix -ForegroundColor DarkGray
}
function Write-TaskSkipped {
param([string]$Message, [string]$Reason = "")
$suffix = if ($Reason) { " ($Reason)" } else { "" }
Write-Host " ○ " -NoNewline -ForegroundColor Yellow
Write-Host "$Message" -NoNewline -ForegroundColor Gray
Write-Host $suffix -ForegroundColor DarkGray
}
function Format-Duration {
param([TimeSpan]$Duration)
if ($Duration.TotalMinutes -ge 1) {
return "$([math]::Round($Duration.TotalMinutes, 1)) min"
} else {
return "$([math]::Round($Duration.TotalSeconds, 1)) sec"
}
}
function Write-SummaryTable {
param([hashtable]$Results)
$passed = @($Results.Values | Where-Object { $_ -eq $true }).Count
$failed = @($Results.Values | Where-Object { $_ -eq $false }).Count
Write-Host ""
Write-Host " ┌────────────────────────────────────────────┬──────────┐" -ForegroundColor DarkGray
Write-Host " │ Task │ Status │" -ForegroundColor DarkGray
Write-Host " ├────────────────────────────────────────────┼──────────┤" -ForegroundColor DarkGray
foreach ($key in $Results.Keys | Sort-Object) {
$success = $Results[$key]
$icon = if ($success) { " ✓ " } else { " ✗ " }
$color = if ($success) { "Green" } else { "Red" }
$paddedKey = (" " + $key).PadRight(44)
Write-Host "$paddedKey│" -NoNewline -ForegroundColor DarkGray
Write-Host $icon -NoNewline -ForegroundColor $color
Write-Host " │" -ForegroundColor DarkGray
}
Write-Host " └────────────────────────────────────────────┴──────────┘" -ForegroundColor DarkGray
Write-Host ""
Write-Host " Results: " -NoNewline -ForegroundColor Gray
Write-Host "$passed passed" -NoNewline -ForegroundColor Green
Write-Host ", " -NoNewline -ForegroundColor Gray
if ($failed -gt 0) {
Write-Host "$failed failed" -ForegroundColor Red
} else {
Write-Host "$failed failed" -ForegroundColor Green
}
}
function Test-PreviousStepsPassed {
return @($script:Results.Values | Where-Object { $_ -eq $false }).Count -eq 0
}
# -----------------------------------------------------------------------------
# Main Script
# -----------------------------------------------------------------------------
Write-Banner "KETE │ Release Push" "Creating production release $($script:Version)" "Green"
Write-Host ""
Write-Host " ┌─────────────────────────────────────────────────────────────────────────┐" -ForegroundColor DarkGreen
Write-Host " │ │" -ForegroundColor DarkGreen
Write-Host " │ VERSION: $($script:Version) │" -ForegroundColor DarkGreen
Write-Host " │ │" -ForegroundColor DarkGreen
Write-Host " └─────────────────────────────────────────────────────────────────────────┘" -ForegroundColor DarkGreen
Write-Host ""
Write-Host " Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor DarkGray
Write-Host " Branch: release" -ForegroundColor DarkGray
Write-Host " Commit: $(git rev-parse --short HEAD 2>$null)" -ForegroundColor DarkGray
# =============================================================================
# Step 1: Run All Tests (EXCLUDED — kept for reference)
# =============================================================================
# Write-StepHeader 1 "Run All Tests (with Coverage)"
#
# $stepStart = Get-Date
# Write-Task "Executing test suites (unit, integration, end-to-end) with JaCoCo coverage..."
# Write-Host ""
#
# & .\run-all-tests.ps1
# $testsPassed = $LASTEXITCODE -eq 0
# $duration = Format-Duration((Get-Date) - $stepStart)
#
# Write-Host ""
# Write-TaskResult "Test execution complete" $testsPassed $duration
# $script:Results["1. Tests"] = $testsPassed
#
# if ($testsPassed) {
# Write-Task "Generating coverage badge..."
# $coveragePercent = 0
# $csvPath = "target/site/jacoco/jacoco.csv"
# if (Test-Path $csvPath) {
# $csv = Import-Csv $csvPath
# $totalMissed = ($csv | Measure-Object -Property LINE_MISSED -Sum).Sum
# $totalCovered = ($csv | Measure-Object -Property LINE_COVERED -Sum).Sum
# $total = $totalMissed + $totalCovered
# if ($total -gt 0) {
# $coveragePercent = [math]::Round(($totalCovered / $total) * 100, 1)
# }
# }
# $color = if ($coveragePercent -ge 80) { "brightgreen" } elseif ($coveragePercent -ge 60) { "green" } elseif ($coveragePercent -ge 40) { "yellow" } else { "red" }
# $badgeJson = @{ schemaVersion = 1; label = "Coverage"; message = "$coveragePercent%"; color = $color } | ConvertTo-Json
# Set-Content -Path "coverage-badge.json" -Value $badgeJson -Encoding UTF8
# Write-TaskResult "Coverage: $coveragePercent% (badge updated)" $true
# }
#
# if (-not $testsPassed) {
# Write-Host ""
# Write-Host " ⚠ RELEASE ABORTED: Tests must pass before releasing" -ForegroundColor Red
# Write-Host ""
# exit 1
# }
$script:Results["1. Tests"] = $true
# =============================================================================
# Step 2: Package Versioned JAR
# =============================================================================
Write-StepHeader 2 "Package Versioned JAR"
$stepStart = Get-Date
Write-Task "Building JAR with version $($script:Version) imprinted..."
mvn package -DskipTests "-Drevision=$($script:Version)" -q 2>&1 | Out-Null
$buildSuccess = $LASTEXITCODE -eq 0
if ($buildSuccess -and (Test-Path "target/kete.jar")) {
$jarSuccess = $true
$jarSize = [math]::Round((Get-Item "target/kete.jar").Length / 1MB, 2)
Write-TaskResult "kete.jar ($jarSize MB)" $jarSuccess
Write-Task "Version $($script:Version) imprinted in META-INF/MANIFEST.MF"
} else {
$jarSuccess = $false
Write-TaskResult "Failed to create JAR" $false
}
$duration = Format-Duration((Get-Date) - $stepStart)
$script:Results["2. Package JAR"] = $jarSuccess
# =============================================================================
# Step 3: Build and Push Docker Images
# =============================================================================
# Build image list dynamically from quick-starts/$images folder
$script:QuickStartImages = @()
# Auto-discover all images from quick-starts/$images folder
Get-ChildItem -Path 'quick-starts/$images' -Directory | ForEach-Object {
$imageName = $_.Name
$dockerfile = "quick-starts/`$images/$imageName/Dockerfile"
# Keycloak needs repo root context for multi-stage maven build
$context = if ($imageName -eq "keycloak") { "." } else { "quick-starts/`$images/$imageName" }
$script:QuickStartImages += @{
Name = "quick-start-$imageName"
Dockerfile = $dockerfile
Context = $context
}
}
function Build-And-Push-Image {
param(
[string]$Name,
[string]$Dockerfile,
[string]$Context
)
$versionedImage = "$script:Registry/${Name}:$($script:Version)"
$latestImage = "$script:Registry/${Name}:latest"
Write-Task "Building $Name..."
docker build -q -t $versionedImage -t $latestImage -f $Dockerfile $Context 2>&1 | Out-Null
$buildSuccess = $LASTEXITCODE -eq 0
if ($buildSuccess) {
Write-Task "Pushing $versionedImage"
docker push $versionedImage 2>&1 | Out-Null
$push1 = $LASTEXITCODE -eq 0
Write-Task "Pushing $latestImage"
docker push $latestImage 2>&1 | Out-Null
$push2 = $LASTEXITCODE -eq 0
$success = $push1 -and $push2
Write-TaskResult "$Name [:$($script:Version) + :latest]" $success
return $true;
} else {
Write-TaskResult "$Name build failed" $false
return $false
}
}
Write-StepHeader 3 "Build and Push Docker Images"
if (-not (Test-PreviousStepsPassed)) {
Write-TaskSkipped "Docker operations" "previous step failed"
foreach ($image in $script:QuickStartImages) {
$script:Results["3. Push: $($image.Name)"] = $false
}
} else {
$stepStart = Get-Date
foreach ($image in $script:QuickStartImages) {
$success = Build-And-Push-Image -Name $image.Name -Dockerfile $image.Dockerfile -Context $image.Context
$script:Results["3. Push: $($image.Name)"] = $success
}
$duration = Format-Duration((Get-Date) - $stepStart)
Write-Host ""
Write-Host " Docker operations completed in $duration" -ForegroundColor DarkGray
}
# =============================================================================
# Step 4: Deploy Documentation Site
# =============================================================================
Write-StepHeader 4 "Build Documentation Site"
if (-not (Test-PreviousStepsPassed)) {
Write-TaskSkipped "Documentation build" "previous step failed"
$script:Results["4. Deploy Docs"] = $false
} else {
$stepStart = Get-Date
Write-Task "Building documentation site..."
python -m mkdocs build --strict 2>&1 | Out-Null
$buildSuccess = $LASTEXITCODE -eq 0
if ($buildSuccess) {
Write-TaskResult "Documentation site built successfully" $true
$script:Results["4. Deploy Docs"] = $true
} else {
Write-TaskResult "Documentation build failed" $false
$script:Results["4. Deploy Docs"] = $false
}
$duration = Format-Duration((Get-Date) - $stepStart)
Write-Host ""
Write-Host " Documentation completed in $duration" -ForegroundColor DarkGray
}
# =============================================================================
# Step 5: Create Git Tag and GitHub Release
# =============================================================================
Write-StepHeader 5 "Create Git Tag and GitHub Release"
if (-not (Test-PreviousStepsPassed)) {
Write-TaskSkipped "Release creation" "previous step failed"
$script:Results["5. Git Tag"] = $false
$script:Results["5. GitHub Release"] = $false
} else {
$stepStart = Get-Date
$tagName = "$($script:Version)"
Write-Task "Creating Git tag $tagName..."
$tagOutput = git tag -a $tagName -m "Release $tagName" 2>&1
$tagCreated = $LASTEXITCODE -eq 0
if (-not $tagCreated) {
Write-Host " Tag creation error: $tagOutput" -ForegroundColor Red
}
if ($tagCreated) {
Write-Task "Pushing tag to origin..."
$pushOutput = git push origin $tagName 2>&1
$tagPushed = $LASTEXITCODE -eq 0
if (-not $tagPushed) {
Write-Host " Tag push error: $pushOutput" -ForegroundColor Red
}
Write-TaskResult "Git tag $tagName" $tagPushed
$script:Results["5. Git Tag"] = $tagPushed
} else {
Write-TaskResult "Failed to create Git tag" $false
$script:Results["5. Git Tag"] = $false
}
if ($script:Results["5. Git Tag"]) {
Write-Task "Creating GitHub Release..."
$releaseNotes = ""
$releaseOutput = gh release create $tagName --title "$tagName" --notes $releaseNotes "target/$script:JarName" 2>&1
$releaseCreated = $LASTEXITCODE -eq 0
if (-not $releaseCreated) {
Write-Host " Release creation error: $releaseOutput" -ForegroundColor Red
}
Write-TaskResult "GitHub Release $tagName" $releaseCreated
$script:Results["5. GitHub Release"] = $releaseCreated
} else {
Write-TaskSkipped "GitHub Release" "tag creation failed"
$script:Results["5. GitHub Release"] = $false
}
$duration = Format-Duration((Get-Date) - $stepStart)
Write-Host ""
Write-Host " Release operations completed in $duration" -ForegroundColor DarkGray
}
# =============================================================================
# Summary
# =============================================================================
$totalDuration = Format-Duration((Get-Date) - $script:StartTime)
$failedCount = @($script:Results.Values | Where-Object { $_ -eq $false }).Count
Write-Host ""
Write-Host ""
Write-Host ("═" * 80) -ForegroundColor Green
Write-Host ""
Write-Host " RELEASE SUMMARY │ $($script:Version)" -ForegroundColor Green
Write-Host ""
Write-Host ("═" * 80) -ForegroundColor Green
Write-SummaryTable $script:Results
Write-Host " ─────────────────────────────────────────────────────────────" -ForegroundColor DarkGray
Write-Host ""
if ($failedCount -eq 0) {
Write-Host " Release Artifact:" -ForegroundColor White
Write-Host " kete.jar ($($script:Version))" -ForegroundColor Cyan
Write-Host ""
Write-Host " Docker Images Published:" -ForegroundColor DarkGray
foreach ($image in $script:QuickStartImages) {
Write-Host " $script:Registry/$($image.Name):$($script:Version)" -ForegroundColor DarkGray
}
Write-Host ""
Write-Host " Documentation:" -ForegroundColor DarkGray
Write-Host " https://fortunen.github.io/kete/" -ForegroundColor DarkGray
Write-Host ""
Write-Host " GitHub Release:" -ForegroundColor White
Write-Host " https://github.com/FortuneN/kete/releases/tag/$($script:Version)" -ForegroundColor Gray
Write-Host ""
Write-Host ""
Write-Host " ╔══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host " ║ ║" -ForegroundColor Green
Write-Host " ║ ✓ RELEASE $($script:Version) PUBLISHED SUCCESSFULLY ║" -ForegroundColor Green
Write-Host " ║ ║" -ForegroundColor Green
Write-Host " ╚══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Green
} else {
Write-Host " ╔══════════════════════════════════════════════════════════════════════╗" -ForegroundColor Red
Write-Host " ║ ║" -ForegroundColor Red
Write-Host " ║ ✗ RELEASE FAILED ║" -ForegroundColor Red
Write-Host " ║ ║" -ForegroundColor Red
Write-Host " ║ $failedCount step(s) failed. Release was not completed. ║" -ForegroundColor Red
Write-Host " ║ ║" -ForegroundColor Red
Write-Host " ╚══════════════════════════════════════════════════════════════════════╝" -ForegroundColor Red
}
Write-Host ""
Write-Host " Completed: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor DarkGray
Write-Host " Duration: $totalDuration" -ForegroundColor DarkGray
Write-Host ""
exit $(if ($failedCount -eq 0) { 0 } else { 1 })