diff --git a/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz b/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz new file mode 100755 index 00000000..bcc4932f Binary files /dev/null and b/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz differ diff --git a/gradle/win/scripts/Readme.txt b/gradle/win/scripts/Readme.txt new file mode 100755 index 00000000..03c24ff4 --- /dev/null +++ b/gradle/win/scripts/Readme.txt @@ -0,0 +1,14 @@ +How to Use + +[1] Move The Two scripts to a Last location +1. pack_offline_bundle_airgap.ps1 +2. unpack_and_offline_build_airgap.ps1 + +[2] Packing Scripts Start --Options: Internet connect Require when you packing, after then you will get all gradle File +command on powershell: powershell -ExecutionPolicy Bypass -File .\pack_offline_bundle_airgap.ps1 + +[3] UnPacking Scripts Start --Options: The JPA Spring boot Project All gradle, gradle cache File, Build File etc (Check using .\gradlew.bat bootRun --offline) +command on powershell: powershell -ExecutionPolicy Bypass -File .\unpack_and_offline_build_airgap.ps1 .\kamco-dabeeo-backoffice_offline_bundle_20260121_145830.tar.gz (The tar File name have to be changed) + + +PS. You can check the ALL Gradle Backup File location Users/d-pn-0071/Desktop/lala/kamco-dabeeo-backoffice/gradle/win/kamco-dabeeo-backoffice_gradle.tar.gz \ No newline at end of file diff --git a/gradle/win/scripts/pack_offline_bundle_airgap.ps1 b/gradle/win/scripts/pack_offline_bundle_airgap.ps1 new file mode 100755 index 00000000..35e2b995 --- /dev/null +++ b/gradle/win/scripts/pack_offline_bundle_airgap.ps1 @@ -0,0 +1,672 @@ +# 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 .tar.gz" -ForegroundColor Gray +Write-Host " cd " -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 "" diff --git a/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 b/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 new file mode 100755 index 00000000..9342a2fe --- /dev/null +++ b/gradle/win/scripts/unpack_and_offline_build_airgap.ps1 @@ -0,0 +1,355 @@ +# unpack_and_offline_build_airgap.ps1 +# ============================================================================ +# Execution Environment: OFFLINE (Air-gapped, No Internet) +# Purpose: Extract bundle and run offline build +# ============================================================================ +# Windows PowerShell Only +# Version: 3.1 +# +# IMPORTANT: This script automatically: +# 1. Extracts the archive +# 2. Sets GRADLE_USER_HOME to project local cache +# 3. Configures settings.gradle for offline resolution +# 4. Runs build with --offline flag +# ============================================================================ + +$ErrorActionPreference = "Stop" +$ProgressPreference = "SilentlyContinue" + +# ============================================================================ +# Configuration +# ============================================================================ +$WRAPPER_SEED_PATH = "wrapper_jar_seed" +$OFFLINE_HOME_NAME = "_offline_gradle_home" + +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Gradle Offline Build Runner" -ForegroundColor Cyan +Write-Host " Environment: AIR-GAPPED (No Internet)" -ForegroundColor Cyan +Write-Host " Mode: Fully Offline (--offline enforced)" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +# ============================================================================ +# [1/16] Check Current Directory +# ============================================================================ +Write-Host "==[1/16] Check Current Directory ==" -ForegroundColor Yellow +$Start = (Get-Location).Path +Write-Host ("PWD: " + $Start) +Write-Host "" + +# ============================================================================ +# [2/16] Select Archive +# ============================================================================ +Write-Host "==[2/16] Select Archive ==" -ForegroundColor Yellow + +$Archive = $null +if ($args.Count -ge 1) { + $Archive = $args[0].Trim().Trim('"').Trim("'") +} + +if ([string]::IsNullOrWhiteSpace($Archive)) { + $candidates = Get-ChildItem -Path $Start -File -ErrorAction SilentlyContinue | + Where-Object { $_.Name -match "\.(tar\.gz|tgz)$" } | + Sort-Object LastWriteTime -Descending + + if (-not $candidates -or $candidates.Count -eq 0) { + Write-Host "[ERROR] No archive found" -ForegroundColor Red + Get-ChildItem -Path $Start -File | Format-Table Name, Length -AutoSize + throw "ERROR: No .tar.gz file found" + } + + $Archive = $candidates[0].FullName + Write-Host ("[AUTO] " + (Split-Path $Archive -Leaf)) -ForegroundColor Cyan +} else { + if (-not [System.IO.Path]::IsPathRooted($Archive)) { + $Archive = Join-Path $Start $Archive + } + Write-Host ("[USER] " + (Split-Path $Archive -Leaf)) -ForegroundColor Cyan +} + +if (-not (Test-Path -LiteralPath $Archive)) { + throw "ERROR: Archive not found: $Archive" +} + +$archiveSizeMB = [math]::Round((Get-Item -LiteralPath $Archive).Length / 1MB, 2) +Write-Host ("Size: " + $archiveSizeMB + " MB") +Write-Host "" + +# ============================================================================ +# [3/16] Check tar.exe +# ============================================================================ +Write-Host "==[3/16] Check tar.exe ==" -ForegroundColor Yellow + +$tar = Get-Command tar.exe -ErrorAction SilentlyContinue +if (-not $tar) { throw "ERROR: tar.exe not found" } +Write-Host "[OK] tar.exe found" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [4/16] Extract Archive +# ============================================================================ +Write-Host "==[4/16] Extract Archive ==" -ForegroundColor Yellow +Write-Host "[INFO] Extracting..." -ForegroundColor Gray + +& tar.exe -xzf $Archive -C $Start +if ($LASTEXITCODE -ne 0) { throw "ERROR: Extraction failed" } +Write-Host "[OK] Extracted" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [5/16] Unblock Files +# ============================================================================ +Write-Host "==[5/16] Unblock Files ==" -ForegroundColor Yellow + +try { + Get-ChildItem -Path $Start -Recurse -Force -ErrorAction SilentlyContinue | + Unblock-File -ErrorAction SilentlyContinue + Write-Host "[OK] Files unblocked" -ForegroundColor Green +} catch { + Write-Host "[WARN] Unblock failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [6/16] Find Project Root +# ============================================================================ +Write-Host "==[6/16] Find Project Root ==" -ForegroundColor Yellow + +$gradlewList = Get-ChildItem -Path $Start -Recurse -Filter "gradlew.bat" -File -ErrorAction SilentlyContinue +if (-not $gradlewList) { throw "ERROR: gradlew.bat not found" } + +$gradlew = $gradlewList | Sort-Object { $_.FullName.Length } | Select-Object -First 1 +$ProjectDir = $gradlew.Directory.FullName + +Write-Host ("Project: " + $ProjectDir) -ForegroundColor Cyan +Set-Location -LiteralPath $ProjectDir +Write-Host "" + +# ============================================================================ +# [7/16] Fix Permissions +# ============================================================================ +Write-Host "==[7/16] Fix Permissions ==" -ForegroundColor Yellow + +try { + $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + cmd /c "icacls `"$ProjectDir`" /grant `"$currentUser`:(OI)(CI)F`" /t /q" 2>&1 | Out-Null + Write-Host "[OK] Permissions fixed" -ForegroundColor Green +} catch { + Write-Host "[WARN] icacls failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [8/16] Verify Wrapper +# ============================================================================ +Write-Host "==[8/16] Verify Wrapper ==" -ForegroundColor Yellow + +$WrapperDir = Join-Path $ProjectDir "gradle\wrapper" +$WrapperJar = Join-Path $WrapperDir "gradle-wrapper.jar" +$WrapperProp = Join-Path $WrapperDir "gradle-wrapper.properties" + +if (!(Test-Path -LiteralPath $WrapperProp)) { + throw "ERROR: gradle-wrapper.properties missing" +} + +if (!(Test-Path -LiteralPath $WrapperJar)) { + $SeedJar = Join-Path $ProjectDir "$WRAPPER_SEED_PATH\gradle-wrapper.jar" + if (Test-Path -LiteralPath $SeedJar) { + New-Item -ItemType Directory -Force -Path $WrapperDir | Out-Null + Copy-Item -Force -LiteralPath $SeedJar -Destination $WrapperJar + Write-Host "[OK] Injected from seed" -ForegroundColor Green + } else { + throw "ERROR: wrapper jar missing" + } +} else { + Write-Host "[OK] Wrapper verified" -ForegroundColor Green +} +Write-Host "" + +# ============================================================================ +# [9/16] Set GRADLE_USER_HOME +# ============================================================================ +Write-Host "==[9/16] Set GRADLE_USER_HOME ==" -ForegroundColor Yellow + +$OfflineHome = Join-Path $ProjectDir $OFFLINE_HOME_NAME +if (!(Test-Path -LiteralPath $OfflineHome)) { + throw "ERROR: _offline_gradle_home not found in archive" +} + +$env:GRADLE_USER_HOME = $OfflineHome +Write-Host ("GRADLE_USER_HOME = " + $env:GRADLE_USER_HOME) -ForegroundColor Cyan + +# Check cache +$CachesDir = Join-Path $OfflineHome "caches" +if (Test-Path -LiteralPath $CachesDir) { + $cacheSize = (Get-ChildItem -Path $CachesDir -Recurse -File -ErrorAction SilentlyContinue | + Measure-Object -Property Length -Sum).Sum + $cacheSizeMB = [math]::Round($cacheSize / 1MB, 2) + Write-Host ("[INFO] Cache size: " + $cacheSizeMB + " MB") -ForegroundColor Cyan +} else { + Write-Host "[WARN] No cache folder found" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [10/16] Verify settings.gradle +# ============================================================================ +Write-Host "==[10/16] Verify settings.gradle ==" -ForegroundColor Yellow + +$settingsFile = $null +if (Test-Path -LiteralPath ".\settings.gradle") { $settingsFile = "settings.gradle" } +elseif (Test-Path -LiteralPath ".\settings.gradle.kts") { $settingsFile = "settings.gradle.kts" } + +if ($settingsFile) { + $content = Get-Content -LiteralPath ".\$settingsFile" -Raw + if ($content -match "mavenLocal\(\)" -and $content -match "pluginManagement") { + Write-Host "[OK] settings.gradle configured for offline" -ForegroundColor Green + } else { + Write-Host "[WARN] settings.gradle may not be configured for offline" -ForegroundColor DarkYellow + Write-Host "[INFO] Build may fail if plugins not cached" -ForegroundColor Gray + } +} +Write-Host "" + +# ============================================================================ +# [11/16] Test Gradle +# ============================================================================ +Write-Host "==[11/16] Test Gradle ==" -ForegroundColor Yellow + +$gradleWorks = $false +try { + $output = cmd /c ".\gradlew.bat --offline --version 2>&1" + if ($LASTEXITCODE -eq 0) { + $gradleWorks = $true + Write-Host "[OK] Gradle working in offline mode" -ForegroundColor Green + } +} catch { } + +if (-not $gradleWorks) { + Write-Host "[WARN] Gradle --version failed" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [12/16] Stop Daemon +# ============================================================================ +Write-Host "==[12/16] Stop Daemon ==" -ForegroundColor Yellow + +try { cmd /c ".\gradlew.bat --stop 2>&1" | Out-Null } catch { } +Start-Sleep -Seconds 2 +Write-Host "[OK] Daemon stopped" -ForegroundColor Green +Write-Host "" + +# ============================================================================ +# [13/16] Run Offline Build +# ============================================================================ +Write-Host "==[13/16] Run Offline Build ==" -ForegroundColor Yellow +Write-Host "" +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host " Building with --offline flag" -ForegroundColor Cyan +Write-Host " All dependencies from local cache" -ForegroundColor Cyan +Write-Host "============================================================" -ForegroundColor Cyan +Write-Host "" + +$buildSuccess = $false +$buildTask = $null + +# Try bootJar +Write-Host "[TRY] --offline bootJar..." -ForegroundColor Gray +try { + cmd /c ".\gradlew.bat --offline clean bootJar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "bootJar" + } +} catch { } + +# Try jar +if (-not $buildSuccess) { + Write-Host "[TRY] --offline jar..." -ForegroundColor Gray + try { + cmd /c ".\gradlew.bat --offline clean jar --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "jar" + } + } catch { } +} + +# Try build +if (-not $buildSuccess) { + Write-Host "[TRY] --offline build..." -ForegroundColor Gray + try { + cmd /c ".\gradlew.bat --offline build --no-daemon" + if ($LASTEXITCODE -eq 0) { + $buildSuccess = $true + $buildTask = "build" + } + } catch { } +} + +Write-Host "" +if ($buildSuccess) { + Write-Host "============================================================" -ForegroundColor Green + Write-Host (" BUILD SUCCESS! (task: " + $buildTask + ")") -ForegroundColor Green + Write-Host "============================================================" -ForegroundColor Green +} else { + Write-Host "============================================================" -ForegroundColor Red + Write-Host " BUILD FAILED!" -ForegroundColor Red + Write-Host "============================================================" -ForegroundColor Red + Write-Host "" + Write-Host "Possible causes:" -ForegroundColor Yellow + Write-Host " - Dependencies not in cache" -ForegroundColor White + Write-Host " - Plugin resolution failed" -ForegroundColor White + Write-Host " - Need complete build in online env first" -ForegroundColor White + throw "Build failed" +} +Write-Host "" + +# ============================================================================ +# [14/16] Show Build Output +# ============================================================================ +Write-Host "==[14/16] Build Output ==" -ForegroundColor Yellow + +$libsDir = Join-Path $ProjectDir "build\libs" +if (Test-Path -LiteralPath $libsDir) { + Write-Host "build/libs contents:" -ForegroundColor Cyan + Get-ChildItem -LiteralPath $libsDir | + Format-Table Name, @{L="Size(KB)";E={[math]::Round($_.Length/1KB,1)}} -AutoSize | + Out-Host + + $mainJar = Get-ChildItem -LiteralPath $libsDir -Filter "*.jar" | + Where-Object { $_.Name -notmatch "plain|sources|javadoc" } | + Select-Object -First 1 +} else { + Write-Host "[WARN] build/libs not found" -ForegroundColor DarkYellow +} +Write-Host "" + +# ============================================================================ +# [15/16] Run Instructions +# ============================================================================ +Write-Host "==[15/16] Run Instructions ==" -ForegroundColor Yellow +Write-Host "" + +if ($mainJar) { + Write-Host "To run the application:" -ForegroundColor Cyan + Write-Host (" java -jar build\libs\" + $mainJar.Name) -ForegroundColor White + Write-Host "" +} + +Write-Host "To rebuild:" -ForegroundColor Cyan +Write-Host ' $env:GRADLE_USER_HOME = ".\\_offline_gradle_home"' -ForegroundColor White +Write-Host " .\gradlew.bat --offline bootJar --no-daemon" -ForegroundColor White +Write-Host "" + +# ============================================================================ +# [16/16] Complete +# ============================================================================ +Write-Host "============================================================" -ForegroundColor Green +Write-Host " Offline Build Complete!" -ForegroundColor Green +Write-Host "============================================================" -ForegroundColor Green +Write-Host "" +Write-Host ("Project: " + $ProjectDir) -ForegroundColor Cyan +Write-Host ""