Files
test/gradle/win/scripts/pack_offline_bundle_airgap.ps1
2026-01-21 17:41:06 +09:00

673 lines
27 KiB
PowerShell
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# pack_offline_bundle_airgap.ps1
# ============================================================================
# Gradle Offline Bundle Packer
# ============================================================================
# Version: 4.0
#
# WORKFLOW:
# 1. [ONLINE] Build project (./gradlew.bat bootJar) - downloads all deps
# 2. [ONLINE] Test run (./gradlew.bat bootRun) - verify app works
# 3. [OFFLINE TEST] Verify offline build works
# 4. Create bundle with all cached dependencies
#
# REQUIREMENTS:
# - Internet connection (for initial build)
# - Project with gradlew.bat
# ============================================================================
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
# ============================================================================
# Configuration
# ============================================================================
$WRAPPER_SEED_PATH = "wrapper_jar_seed"
$OFFLINE_HOME_NAME = "_offline_gradle_home"
$BOOTRUN_TIMEOUT_SECONDS = 60
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Gradle Offline Bundle Packer v4.0" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host " This script will:" -ForegroundColor White
Write-Host " 1. Build project with internet (download dependencies)" -ForegroundColor Gray
Write-Host " 2. Test run application (verify it works)" -ForegroundColor Gray
Write-Host " 3. Test offline build (verify cache is complete)" -ForegroundColor Gray
Write-Host " 4. Create offline bundle for air-gapped environment" -ForegroundColor Gray
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
# ============================================================================
# [1/20] Check Current Directory
# ============================================================================
Write-Host "==[1/20] Check Current Directory ==" -ForegroundColor Yellow
$Root = (Get-Location).Path
Write-Host ("ROOT_DIR: " + $Root)
Write-Host ""
# ============================================================================
# [2/20] Check Required Files
# ============================================================================
Write-Host "==[2/20] Check Required Files ==" -ForegroundColor Yellow
if (!(Test-Path -LiteralPath ".\gradlew.bat")) {
throw "ERROR: gradlew.bat not found. Run from project root."
}
Write-Host "[OK] gradlew.bat" -ForegroundColor Green
$buildFile = $null
if (Test-Path -LiteralPath ".\build.gradle") { $buildFile = "build.gradle" }
elseif (Test-Path -LiteralPath ".\build.gradle.kts") { $buildFile = "build.gradle.kts" }
else { throw "ERROR: build.gradle(.kts) not found." }
Write-Host ("[OK] " + $buildFile) -ForegroundColor Green
$settingsFile = $null
if (Test-Path -LiteralPath ".\settings.gradle") { $settingsFile = "settings.gradle" }
elseif (Test-Path -LiteralPath ".\settings.gradle.kts") { $settingsFile = "settings.gradle.kts" }
if ($settingsFile) { Write-Host ("[OK] " + $settingsFile) -ForegroundColor Green }
Write-Host ""
# ============================================================================
# [3/20] Check Gradle Wrapper
# ============================================================================
Write-Host "==[3/20] Check Gradle Wrapper ==" -ForegroundColor Yellow
$WrapperDir = Join-Path $Root "gradle\wrapper"
$WrapperJar = Join-Path $WrapperDir "gradle-wrapper.jar"
$WrapperProp = Join-Path $WrapperDir "gradle-wrapper.properties"
New-Item -ItemType Directory -Force -Path $WrapperDir | Out-Null
if (!(Test-Path -LiteralPath $WrapperProp)) {
throw "ERROR: gradle-wrapper.properties not found."
}
if (!(Test-Path -LiteralPath $WrapperJar)) {
$SeedJar = Join-Path $Root "$WRAPPER_SEED_PATH\gradle-wrapper.jar"
if (Test-Path -LiteralPath $SeedJar) {
Copy-Item -Force -LiteralPath $SeedJar -Destination $WrapperJar
Write-Host "[OK] Wrapper jar injected from seed" -ForegroundColor Green
} else {
throw "ERROR: gradle-wrapper.jar missing"
}
} else {
Write-Host "[OK] gradle-wrapper.jar exists" -ForegroundColor Green
}
# Create seed backup
$SeedDir = Join-Path $Root $WRAPPER_SEED_PATH
if (!(Test-Path -LiteralPath $SeedDir)) {
New-Item -ItemType Directory -Force -Path $SeedDir | Out-Null
Copy-Item -Force -LiteralPath $WrapperJar -Destination (Join-Path $SeedDir "gradle-wrapper.jar")
}
Write-Host ""
# ============================================================================
# [4/20] Set GRADLE_USER_HOME (Project Local)
# ============================================================================
Write-Host "==[4/20] Set GRADLE_USER_HOME ==" -ForegroundColor Yellow
$OfflineHome = Join-Path $Root $OFFLINE_HOME_NAME
New-Item -ItemType Directory -Force -Path $OfflineHome | Out-Null
$env:GRADLE_USER_HOME = $OfflineHome
Write-Host ("GRADLE_USER_HOME = " + $env:GRADLE_USER_HOME) -ForegroundColor Cyan
Write-Host "[INFO] All dependencies will be cached in project folder" -ForegroundColor Gray
Write-Host ""
# ============================================================================
# [5/20] Check Internet Connection
# ============================================================================
Write-Host "==[5/20] Check Internet Connection ==" -ForegroundColor Yellow
$hasInternet = $false
$testHosts = @("plugins.gradle.org", "repo.maven.apache.org", "repo1.maven.org")
foreach ($testHost in $testHosts) {
try {
$result = Test-Connection -ComputerName $testHost -Count 1 -Quiet -TimeoutSeconds 3 -ErrorAction SilentlyContinue
if ($result) {
$hasInternet = $true
Write-Host ("[OK] Connected to " + $testHost) -ForegroundColor Green
break
}
} catch { }
}
if (-not $hasInternet) {
# Try DNS resolution as fallback
try {
[System.Net.Dns]::GetHostAddresses("google.com") | Out-Null
$hasInternet = $true
Write-Host "[OK] Internet available (DNS)" -ForegroundColor Green
} catch { }
}
if (-not $hasInternet) {
Write-Host ""
Write-Host "============================================================" -ForegroundColor Red
Write-Host " ERROR: No Internet Connection!" -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
Write-Host ""
Write-Host "This script requires internet for initial build." -ForegroundColor Yellow
Write-Host "Please connect to internet and run again." -ForegroundColor Yellow
Write-Host ""
throw "No internet connection"
}
Write-Host ""
# ============================================================================
# [6/20] Initial Gradle Setup
# ============================================================================
Write-Host "==[6/20] Initial Gradle Setup ==" -ForegroundColor Yellow
Write-Host "[INFO] Downloading Gradle distribution..." -ForegroundColor Gray
try {
$output = cmd /c ".\gradlew.bat --version 2>&1"
if ($LASTEXITCODE -eq 0) {
$gradleVersion = $output | Select-String "Gradle\s+(\d+\.\d+)" |
ForEach-Object { $_.Matches[0].Groups[1].Value }
Write-Host ("[OK] Gradle " + $gradleVersion) -ForegroundColor Green
} else {
throw "Gradle setup failed"
}
} catch {
Write-Host "[ERROR] Gradle setup failed" -ForegroundColor Red
throw $_
}
Write-Host ""
# ============================================================================
# [7/20] ONLINE BUILD - bootJar (Download All Dependencies)
# ============================================================================
Write-Host "==[7/20] ONLINE BUILD - bootJar ==" -ForegroundColor Yellow
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Building project (downloading all dependencies)" -ForegroundColor Cyan
Write-Host " This may take several minutes on first run..." -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
$buildSuccess = $false
try {
cmd /c ".\gradlew.bat clean bootJar --no-daemon"
if ($LASTEXITCODE -eq 0) {
$buildSuccess = $true
}
} catch { }
if (-not $buildSuccess) {
Write-Host ""
Write-Host "============================================================" -ForegroundColor Red
Write-Host " BUILD FAILED!" -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
Write-Host ""
Write-Host "Please fix build errors and run this script again." -ForegroundColor Yellow
throw "Build failed"
}
Write-Host ""
Write-Host "[OK] bootJar build SUCCESS" -ForegroundColor Green
Write-Host ""
# ============================================================================
# [8/20] ONLINE TEST - bootRun (Verify Application Works)
# ============================================================================
Write-Host "==[8/20] ONLINE TEST - bootRun ==" -ForegroundColor Yellow
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Starting application to verify it works..." -ForegroundColor Cyan
Write-Host " Will run for $BOOTRUN_TIMEOUT_SECONDS seconds then stop" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
$bootRunSuccess = $false
try {
# Start bootRun as background job
$job = Start-Job -ScriptBlock {
param($projectDir, $gradleHome)
Set-Location $projectDir
$env:GRADLE_USER_HOME = $gradleHome
cmd /c ".\gradlew.bat bootRun --no-daemon 2>&1"
} -ArgumentList $Root, $OfflineHome
Write-Host "[INFO] Application starting..." -ForegroundColor Gray
# Wait for startup (check for typical Spring Boot messages)
$startTime = Get-Date
$startupDetected = $false
while (((Get-Date) - $startTime).TotalSeconds -lt $BOOTRUN_TIMEOUT_SECONDS) {
Start-Sleep -Seconds 3
# Check if job has output
$jobOutput = Receive-Job -Job $job -Keep -ErrorAction SilentlyContinue
if ($jobOutput) {
$outputText = $jobOutput -join "`n"
# Check for Spring Boot startup success indicators
if ($outputText -match "Started .+ in .+ seconds" -or
$outputText -match "Tomcat started on port" -or
$outputText -match "Netty started on port" -or
$outputText -match "Application .+ started") {
$startupDetected = $true
Write-Host "[OK] Application started successfully!" -ForegroundColor Green
break
}
# Check for errors
if ($outputText -match "APPLICATION FAILED TO START" -or
$outputText -match "Error starting ApplicationContext") {
Write-Host "[ERROR] Application failed to start" -ForegroundColor Red
break
}
}
$elapsed = [math]::Round(((Get-Date) - $startTime).TotalSeconds)
Write-Host ("[INFO] Waiting... " + $elapsed + "s") -ForegroundColor Gray
}
# Stop the job
Write-Host "[INFO] Stopping application..." -ForegroundColor Gray
Stop-Job -Job $job -ErrorAction SilentlyContinue
Remove-Job -Job $job -Force -ErrorAction SilentlyContinue
# Also stop any remaining Gradle processes
cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null
if ($startupDetected) {
$bootRunSuccess = $true
}
} catch {
Write-Host "[WARN] bootRun test encountered error: $_" -ForegroundColor DarkYellow
}
# Cleanup any remaining processes
try {
Get-Process -Name "java" -ErrorAction SilentlyContinue |
Where-Object { $_.CommandLine -match "bootRun|spring" } |
Stop-Process -Force -ErrorAction SilentlyContinue
} catch { }
Write-Host ""
if ($bootRunSuccess) {
Write-Host "[OK] bootRun test PASSED" -ForegroundColor Green
} else {
Write-Host "[WARN] bootRun test could not verify startup" -ForegroundColor DarkYellow
Write-Host "[INFO] Continuing anyway - bootJar succeeded" -ForegroundColor Gray
}
Write-Host ""
# ============================================================================
# [9/20] Stop All Gradle Daemons
# ============================================================================
Write-Host "==[9/20] Stop Gradle Daemons ==" -ForegroundColor Yellow
cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null
Start-Sleep -Seconds 3
Write-Host "[OK] Daemons stopped" -ForegroundColor Green
Write-Host ""
# ============================================================================
# [10/20] OFFLINE TEST - Verify Offline Build Works
# ============================================================================
Write-Host "==[10/20] OFFLINE TEST - Verify Cache ==" -ForegroundColor Yellow
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Testing offline build (--offline flag)" -ForegroundColor Cyan
Write-Host " This verifies all dependencies are cached" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
$offlineSuccess = $false
try {
cmd /c ".\gradlew.bat --offline clean bootJar --no-daemon"
if ($LASTEXITCODE -eq 0) {
$offlineSuccess = $true
}
} catch { }
Write-Host ""
if ($offlineSuccess) {
Write-Host "[OK] Offline build SUCCESS - Cache is complete!" -ForegroundColor Green
} else {
Write-Host "============================================================" -ForegroundColor Red
Write-Host " OFFLINE BUILD FAILED!" -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
Write-Host ""
Write-Host "Some dependencies may not be cached properly." -ForegroundColor Yellow
Write-Host ""
$continue = Read-Host "Continue creating bundle anyway? (y/N)"
if ($continue -ne "y" -and $continue -ne "Y") {
throw "Offline verification failed"
}
}
Write-Host ""
# ============================================================================
# [11/20] Backup Original settings.gradle
# ============================================================================
Write-Host "==[11/20] Backup settings.gradle ==" -ForegroundColor Yellow
if ($settingsFile) {
$settingsPath = Join-Path $Root $settingsFile
$settingsBackup = Join-Path $Root "${settingsFile}.original.bak"
if (!(Test-Path -LiteralPath $settingsBackup)) {
Copy-Item -Force -LiteralPath $settingsPath -Destination $settingsBackup
Write-Host "[OK] Backup: ${settingsFile}.original.bak" -ForegroundColor Green
} else {
Write-Host "[OK] Backup exists" -ForegroundColor Green
}
}
Write-Host ""
# ============================================================================
# [12/20] Modify settings.gradle for Offline
# ============================================================================
Write-Host "==[12/20] Configure settings.gradle for Offline ==" -ForegroundColor Yellow
if ($settingsFile) {
$settingsPath = Join-Path $Root $settingsFile
$content = Get-Content -LiteralPath $settingsPath -Raw
# --- Always strip BOM if present (prevents Groovy 'Unexpected character: ')
$hadBom = $false
if ($content.Length -gt 0 -and $content[0] -eq [char]0xFEFF) {
$hadBom = $true
$content = $content -replace "^\uFEFF", ""
}
$isOfflineConfigured =
($content -match "mavenLocal\(\)") -and
($content -match "pluginManagement[\s\S]*repositories")
if ($isOfflineConfigured) {
# Even if already configured, re-save without BOM if needed
if ($hadBom) {
[System.IO.File]::WriteAllText(
$settingsPath,
$content,
(New-Object System.Text.UTF8Encoding($false))
)
Write-Host "[FIX] settings.gradle BOM removed (saved as UTF-8 without BOM)" -ForegroundColor Green
} else {
Write-Host "[OK] Already configured for offline" -ForegroundColor Green
}
} else {
$newHeader = @"
// ============================================================================
// OFFLINE BUILD CONFIGURATION (Auto-generated by pack script)
// Original backup: ${settingsFile}.original.bak
// ============================================================================
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
"@
# Remove existing pluginManagement
$cleaned = $content -replace '(?s)pluginManagement\s*\{[^{}]*(\{[^{}]*\}[^{}]*)*\}\s*', ''
$final = $newHeader + $cleaned.Trim()
# --- Write as UTF-8 WITHOUT BOM
[System.IO.File]::WriteAllText(
$settingsPath,
$final,
(New-Object System.Text.UTF8Encoding($false))
)
Write-Host "[OK] settings.gradle updated for offline (UTF-8 without BOM)" -ForegroundColor Green
}
}
Write-Host ""
# ============================================================================
# [13/20] Copy Maven Local Repository
# ============================================================================
Write-Host "==[13/20] Copy Maven Local (.m2) ==" -ForegroundColor Yellow
$m2Repo = Join-Path $env:USERPROFILE ".m2\repository"
$localM2 = Join-Path $OfflineHome "m2_repository"
if (Test-Path -LiteralPath $m2Repo) {
$m2Size = (Get-ChildItem -Path $m2Repo -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
if ($m2Size -gt 1MB) {
$m2SizeMB = [math]::Round($m2Size / 1MB, 2)
Write-Host ("[INFO] .m2 size: " + $m2SizeMB + " MB") -ForegroundColor Cyan
# Copy important plugin directories
$pluginDirs = @(
"org\springframework\boot",
"io\spring",
"com\diffplug"
)
foreach ($dir in $pluginDirs) {
$src = Join-Path $m2Repo $dir
if (Test-Path -LiteralPath $src) {
$dst = Join-Path $localM2 $dir
New-Item -ItemType Directory -Force -Path (Split-Path $dst -Parent) | Out-Null
if (!(Test-Path -LiteralPath $dst)) {
Copy-Item -Recurse -Force -LiteralPath $src -Destination $dst -ErrorAction SilentlyContinue
Write-Host ("[OK] Copied " + $dir) -ForegroundColor Green
}
}
}
}
} else {
Write-Host "[INFO] No .m2 repository found" -ForegroundColor Gray
}
Write-Host ""
# ============================================================================
# [14/20] Create Helper Scripts
# ============================================================================
Write-Host "==[14/20] Create Helper Scripts ==" -ForegroundColor Yellow
# run_offline_build.ps1
$runScript = @'
# run_offline_build.ps1 - Quick offline build script
$env:GRADLE_USER_HOME = Join-Path (Get-Location).Path "_offline_gradle_home"
Write-Host "GRADLE_USER_HOME = $env:GRADLE_USER_HOME" -ForegroundColor Cyan
Write-Host ""
.\gradlew.bat --offline bootJar --no-daemon
if ($LASTEXITCODE -eq 0) {
Write-Host ""
Write-Host "BUILD SUCCESS!" -ForegroundColor Green
Write-Host ""
Write-Host "JAR files:" -ForegroundColor Cyan
Get-ChildItem .\build\libs\*.jar | ForEach-Object { Write-Host (" " + $_.Name) }
} else {
Write-Host "BUILD FAILED" -ForegroundColor Red
}
'@
[System.IO.File]::WriteAllText((Join-Path $Root "run_offline_build.ps1"), $runScript, (New-Object System.Text.UTF8Encoding($false)))
Write-Host "[OK] run_offline_build.ps1" -ForegroundColor Green
# run_offline_bootrun.ps1
$bootRunScript = @'
# run_offline_bootrun.ps1 - Run application offline
$env:GRADLE_USER_HOME = Join-Path (Get-Location).Path "_offline_gradle_home"
Write-Host "GRADLE_USER_HOME = $env:GRADLE_USER_HOME" -ForegroundColor Cyan
Write-Host ""
Write-Host "Starting application (Ctrl+C to stop)..." -ForegroundColor Yellow
Write-Host ""
.\gradlew.bat --offline bootRun --no-daemon
'@
[System.IO.File]::WriteAllText((Join-Path $Root "run_offline_bootrun.ps1"), $bootRunScript, (New-Object System.Text.UTF8Encoding($false)))
Write-Host "[OK] run_offline_bootrun.ps1" -ForegroundColor Green
Write-Host ""
# ============================================================================
# [15/20] Stop Daemons Again
# ============================================================================
Write-Host "==[15/20] Final Daemon Cleanup ==" -ForegroundColor Yellow
cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null
Start-Sleep -Seconds 2
Write-Host "[OK] Daemons stopped" -ForegroundColor Green
Write-Host ""
# ============================================================================
# [16/20] Clean Lock Files
# ============================================================================
Write-Host "==[16/20] Clean Lock Files ==" -ForegroundColor Yellow
try {
$DaemonDir = Join-Path $OfflineHome "daemon"
if (Test-Path -LiteralPath $DaemonDir) {
Remove-Item -Recurse -Force -LiteralPath $DaemonDir -ErrorAction SilentlyContinue
}
Get-ChildItem -Path $OfflineHome -Recurse -Include "*.lock","*.log","*.tmp" -File -ErrorAction SilentlyContinue |
ForEach-Object { Remove-Item -Force -LiteralPath $_.FullName -ErrorAction SilentlyContinue }
Write-Host "[OK] Lock files cleaned" -ForegroundColor Green
} catch {
Write-Host "[WARN] Some files could not be cleaned" -ForegroundColor DarkYellow
}
Write-Host ""
# ============================================================================
# [17/20] Calculate Cache Size
# ============================================================================
Write-Host "==[17/20] Cache Summary ==" -ForegroundColor Yellow
$CachesDir = Join-Path $OfflineHome "caches"
$WrapperDists = Join-Path $OfflineHome "wrapper\dists"
$totalSize = 0
if (Test-Path -LiteralPath $CachesDir) {
$size = (Get-ChildItem -Path $CachesDir -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
$totalSize += $size
Write-Host ("[INFO] Dependencies: " + [math]::Round($size/1MB, 2) + " MB") -ForegroundColor Cyan
}
if (Test-Path -LiteralPath $WrapperDists) {
$size = (Get-ChildItem -Path $WrapperDists -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
$totalSize += $size
Write-Host ("[INFO] Gradle dist: " + [math]::Round($size/1MB, 2) + " MB") -ForegroundColor Cyan
}
Write-Host ("[INFO] Total cache: " + [math]::Round($totalSize/1MB, 2) + " MB") -ForegroundColor Cyan
Write-Host ""
# ============================================================================
# [18/20] Create Archive
# ============================================================================
Write-Host "==[18/20] Create Archive ==" -ForegroundColor Yellow
$BaseName = Split-Path $Root -Leaf
$Ts = Get-Date -Format "yyyyMMdd_HHmmss"
$Parent = Split-Path $Root -Parent
$ArchivePath = Join-Path $Parent "${BaseName}_offline_bundle_${Ts}.tar.gz"
Write-Host ("Archive: " + $ArchivePath)
$tar = Get-Command tar.exe -ErrorAction SilentlyContinue
if (-not $tar) { throw "ERROR: tar.exe not found" }
Write-Host "[INFO] Creating archive (this may take several minutes)..." -ForegroundColor Gray
& tar.exe -czf $ArchivePath `
--exclude ".git" `
--exclude ".idea" `
--exclude ".DS_Store" `
--exclude "*.log" `
--exclude "*.lock" `
--exclude "_offline_gradle_home/daemon" `
--exclude "_offline_gradle_home/native" `
--exclude "_offline_gradle_home/jdks" `
--exclude "build" `
--exclude "out" `
--exclude ".gradle" `
-C $Root .
if ($LASTEXITCODE -ne 0) { throw "ERROR: tar failed" }
$archiveSize = (Get-Item -LiteralPath $ArchivePath).Length
$archiveSizeMB = [math]::Round($archiveSize / 1MB, 2)
Write-Host ("[OK] Archive created: " + $archiveSizeMB + " MB") -ForegroundColor Green
Write-Host ""
# ============================================================================
# [19/20] Verify Archive
# ============================================================================
Write-Host "==[19/20] Verify Archive ==" -ForegroundColor Yellow
$listOutput = & tar.exe -tzf $ArchivePath 2>&1
$checks = @(
"gradle/wrapper/gradle-wrapper.jar",
"gradlew.bat",
"_offline_gradle_home/caches",
"run_offline_build.ps1"
)
foreach ($check in $checks) {
$found = $listOutput | Select-String -SimpleMatch $check
if ($found) {
Write-Host (" [OK] " + $check) -ForegroundColor Green
} else {
Write-Host (" [WARN] " + $check) -ForegroundColor DarkYellow
}
}
Write-Host ""
# ============================================================================
# [20/20] Complete
# ============================================================================
Write-Host "============================================================" -ForegroundColor Green
Write-Host " BUNDLE CREATION COMPLETE!" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Write-Host ("Archive: " + $ArchivePath) -ForegroundColor Cyan
Write-Host ("Size: " + $archiveSizeMB + " MB") -ForegroundColor Cyan
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " Test Results" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host (" Online build (bootJar): " + $(if($buildSuccess){"PASSED"}else{"FAILED"})) -ForegroundColor $(if($buildSuccess){"Green"}else{"Red"})
Write-Host (" Online test (bootRun): " + $(if($bootRunSuccess){"PASSED"}else{"SKIPPED"})) -ForegroundColor $(if($bootRunSuccess){"Green"}else{"Yellow"})
Write-Host (" Offline build test: " + $(if($offlineSuccess){"PASSED"}else{"FAILED"})) -ForegroundColor $(if($offlineSuccess){"Green"}else{"Red"})
Write-Host ""
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host " Usage in Air-gapped Environment" -ForegroundColor Yellow
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host ""
Write-Host "Option 1: Use unpack script" -ForegroundColor White
Write-Host " .\unpack_and_offline_build_airgap.ps1" -ForegroundColor Gray
Write-Host ""
Write-Host "Option 2: Manual extraction" -ForegroundColor White
Write-Host " tar -xzf <archive>.tar.gz" -ForegroundColor Gray
Write-Host " cd <project>" -ForegroundColor Gray
Write-Host " .\run_offline_build.ps1" -ForegroundColor Gray
Write-Host ""
Write-Host "Option 3: Direct commands" -ForegroundColor White
Write-Host ' $env:GRADLE_USER_HOME = ".\\_offline_gradle_home"' -ForegroundColor Gray
Write-Host " .\gradlew.bat --offline bootJar --no-daemon" -ForegroundColor Gray
Write-Host ""