mirror of
https://gitee.com/kekingcn/file-online-preview.git
synced 2026-04-18 06:13:41 +00:00
328 lines
10 KiB
Java
328 lines
10 KiB
Java
$ErrorActionPreference = 'Stop'
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
|
|
function Write-Step {
|
|
param([string]$Message)
|
|
Write-Host "==> $Message"
|
|
}
|
|
|
|
function Get-RequiredEnv {
|
|
param([string]$Name)
|
|
|
|
$Value = [Environment]::GetEnvironmentVariable($Name)
|
|
if ([string]::IsNullOrWhiteSpace($Value)) {
|
|
throw "Missing required environment variable: $Name"
|
|
}
|
|
|
|
return $Value
|
|
}
|
|
|
|
function Get-OptionalEnv {
|
|
param(
|
|
[string]$Name,
|
|
[string]$DefaultValue
|
|
)
|
|
|
|
$Value = [Environment]::GetEnvironmentVariable($Name)
|
|
if ([string]::IsNullOrWhiteSpace($Value)) {
|
|
return $DefaultValue
|
|
}
|
|
|
|
return $Value
|
|
}
|
|
|
|
$DeployRoot = Get-OptionalEnv 'KK_DEPLOY_ROOT' 'C:\kkFileView-5.0'
|
|
$HealthUrl = Get-OptionalEnv 'KK_DEPLOY_HEALTH_URL' 'http://127.0.0.1:8012/'
|
|
$RepoUrl = Get-OptionalEnv 'KK_DEPLOY_REPO_URL' 'https://github.com/kekingcn/kkFileView.git'
|
|
$Branch = Get-OptionalEnv 'KK_DEPLOY_BRANCH' 'master'
|
|
$SourceRoot = Get-OptionalEnv 'KK_DEPLOY_SOURCE_ROOT' 'C:\kkFileView-source'
|
|
$JavaHome = Get-OptionalEnv 'KK_DEPLOY_JAVA_HOME' 'C:\Program Files\jdk-21.0.2'
|
|
$GitExe = Get-OptionalEnv 'KK_DEPLOY_GIT_EXE' 'C:\kkFileView-tools\git\cmd\git.exe'
|
|
$MvnCmd = Get-OptionalEnv 'KK_DEPLOY_MVN_CMD' 'C:\kkFileView-tools\maven\bin\mvn.cmd'
|
|
$MavenSettings = Get-OptionalEnv 'KK_DEPLOY_MAVEN_SETTINGS' ''
|
|
$DryRun = Get-OptionalEnv 'KK_DEPLOY_DRY_RUN' 'false'
|
|
|
|
$BinDir = Join-Path $DeployRoot 'bin'
|
|
$StartupScript = Join-Path $BinDir 'startup.bat'
|
|
$ReleaseDir = Join-Path $DeployRoot 'releases'
|
|
$DeployTmp = Join-Path $DeployRoot 'deploy-tmp'
|
|
$BuildOutputDir = Join-Path (Join-Path $SourceRoot 'server') 'target'
|
|
|
|
if (-not (Test-Path $DeployRoot)) {
|
|
throw "Deploy root not found: $DeployRoot"
|
|
}
|
|
|
|
if (-not (Test-Path $BinDir)) {
|
|
throw "Bin directory not found: $BinDir"
|
|
}
|
|
|
|
if (-not (Test-Path $StartupScript)) {
|
|
throw "Startup script not found: $StartupScript"
|
|
}
|
|
|
|
$CurrentJar = Get-ChildItem $BinDir -Filter 'kkFileView-*.jar' | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
if (-not $CurrentJar) {
|
|
throw "No kkFileView jar found in $BinDir"
|
|
}
|
|
|
|
$JavaExe = Join-Path $JavaHome 'bin\java.exe'
|
|
if (-not (Test-Path $JavaExe)) {
|
|
throw "JDK 21 java executable not found: $JavaExe"
|
|
}
|
|
|
|
if (-not (Test-Path $GitExe)) {
|
|
throw "Git executable not found: $GitExe"
|
|
}
|
|
|
|
if (-not (Test-Path $MvnCmd)) {
|
|
throw "Maven executable not found: $MvnCmd"
|
|
}
|
|
|
|
if (-not [string]::IsNullOrWhiteSpace($MavenSettings) -and -not (Test-Path $MavenSettings)) {
|
|
throw "Maven settings file not found: $MavenSettings"
|
|
}
|
|
|
|
$JarName = $CurrentJar.Name
|
|
$JarPath = $CurrentJar.FullName
|
|
|
|
Write-Step "Deploy root: $DeployRoot"
|
|
Write-Step "Current jar: $JarPath"
|
|
Write-Step "Startup script: $StartupScript"
|
|
Write-Step "Health url: $HealthUrl"
|
|
Write-Step "Source root: $SourceRoot"
|
|
Write-Step "Branch: $Branch"
|
|
Write-Step "Git exe: $GitExe"
|
|
Write-Step "Maven cmd: $MvnCmd"
|
|
Write-Step "Java home: $JavaHome"
|
|
if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) {
|
|
Write-Step "Maven settings: $MavenSettings"
|
|
}
|
|
|
|
function Invoke-External {
|
|
param(
|
|
[string]$FilePath,
|
|
[string[]]$Arguments,
|
|
[string]$WorkingDirectory = $null
|
|
)
|
|
|
|
$previous = $null
|
|
if ($WorkingDirectory) {
|
|
$previous = Get-Location
|
|
Set-Location $WorkingDirectory
|
|
}
|
|
|
|
try {
|
|
& $FilePath @Arguments
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Command failed ($LASTEXITCODE): $FilePath $($Arguments -join ' ')"
|
|
}
|
|
} finally {
|
|
if ($previous) {
|
|
Set-Location $previous
|
|
}
|
|
}
|
|
}
|
|
|
|
function Assert-SafeSourceRoot {
|
|
param([string]$PathToCheck)
|
|
|
|
$FullPath = [System.IO.Path]::GetFullPath($PathToCheck)
|
|
$RootPath = [System.IO.Path]::GetPathRoot($FullPath)
|
|
if ($FullPath.TrimEnd('\') -eq $RootPath.TrimEnd('\')) {
|
|
throw "Refusing to use drive root as source root: $FullPath"
|
|
}
|
|
|
|
$DangerousLeafNames = @(
|
|
'Windows',
|
|
'Users',
|
|
'Program Files',
|
|
'Program Files (x86)',
|
|
'ProgramData'
|
|
)
|
|
$LeafName = Split-Path -Leaf $FullPath.TrimEnd('\')
|
|
if ($DangerousLeafNames -contains $LeafName) {
|
|
throw "Refusing to use a high-risk source root path: $FullPath"
|
|
}
|
|
}
|
|
|
|
$env:JAVA_HOME = $JavaHome
|
|
$env:Path = (Join-Path $JavaHome 'bin') + ';' + (Split-Path -Parent $GitExe) + ';' + (Split-Path -Parent $MvnCmd) + ';' + $env:Path
|
|
|
|
Write-Step 'Validating Git executable'
|
|
Invoke-External -FilePath $GitExe -Arguments @('--version')
|
|
|
|
Write-Step 'Validating Maven executable'
|
|
$MavenVersionArgs = @('-version')
|
|
if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) {
|
|
$MavenVersionArgs = @('-s', $MavenSettings, '-version')
|
|
}
|
|
Invoke-External -FilePath $MvnCmd -Arguments $MavenVersionArgs
|
|
|
|
if ($DryRun -eq 'true') {
|
|
Write-Step "Dry run enabled, remote validation finished"
|
|
return
|
|
}
|
|
|
|
New-Item -ItemType Directory -Force -Path $ReleaseDir | Out-Null
|
|
New-Item -ItemType Directory -Force -Path $DeployTmp | Out-Null
|
|
|
|
function Sync-Repository {
|
|
Assert-SafeSourceRoot -PathToCheck $SourceRoot
|
|
|
|
if (-not (Test-Path (Join-Path $SourceRoot '.git'))) {
|
|
if (Test-Path $SourceRoot) {
|
|
Remove-Item $SourceRoot -Recurse -Force
|
|
}
|
|
|
|
$parent = Split-Path -Parent $SourceRoot
|
|
if ($parent) {
|
|
New-Item -ItemType Directory -Force -Path $parent | Out-Null
|
|
}
|
|
|
|
Write-Step "Cloning repository from $RepoUrl"
|
|
Invoke-External -FilePath $GitExe -Arguments @('clone', '--depth', '1', '--branch', $Branch, '--single-branch', $RepoUrl, $SourceRoot)
|
|
return
|
|
}
|
|
|
|
Write-Step "Fetching latest branch state from origin/$Branch"
|
|
Invoke-External -FilePath $GitExe -Arguments @('remote', 'set-url', 'origin', $RepoUrl) -WorkingDirectory $SourceRoot
|
|
Invoke-External -FilePath $GitExe -Arguments @('fetch', '--prune', '--depth', '1', 'origin', $Branch) -WorkingDirectory $SourceRoot
|
|
Invoke-External -FilePath $GitExe -Arguments @('checkout', '-B', $Branch, "origin/$Branch") -WorkingDirectory $SourceRoot
|
|
Invoke-External -FilePath $GitExe -Arguments @('reset', '--hard', "origin/$Branch") -WorkingDirectory $SourceRoot
|
|
Invoke-External -FilePath $GitExe -Arguments @('clean', '-fd') -WorkingDirectory $SourceRoot
|
|
}
|
|
|
|
function Build-KkFileView {
|
|
Write-Step 'Building kkFileView from source'
|
|
$BuildArgs = @('-B', 'clean', 'package', '-Dmaven.test.skip=true', '--file', 'pom.xml')
|
|
if (-not [string]::IsNullOrWhiteSpace($MavenSettings)) {
|
|
$BuildArgs = @('-s', $MavenSettings) + $BuildArgs
|
|
}
|
|
Invoke-External -FilePath $MvnCmd -Arguments $BuildArgs -WorkingDirectory $SourceRoot
|
|
}
|
|
|
|
Sync-Repository
|
|
Build-KkFileView
|
|
|
|
$DownloadedJars = Get-ChildItem $BuildOutputDir -Filter 'kkFileView-*.jar' -File
|
|
if (-not $DownloadedJars) {
|
|
throw "No kkFileView jar found in build output: $BuildOutputDir"
|
|
}
|
|
|
|
if ($DownloadedJars.Count -ne 1) {
|
|
throw "Expected exactly one kkFileView jar in build output, found $($DownloadedJars.Count)"
|
|
}
|
|
|
|
$DownloadedJar = $DownloadedJars[0]
|
|
|
|
$Timestamp = Get-Date -Format 'yyyyMMddHHmmss'
|
|
$BackupJar = Join-Path $ReleaseDir ("{0}.{1}.bak" -f $JarName, $Timestamp)
|
|
|
|
function Stop-KkFileView {
|
|
foreach ($Process in @(Get-KkFileViewJavaProcesses) + @(Get-KkFileViewLauncherProcesses)) {
|
|
Write-Step "Stopping process $($Process.ProcessId)"
|
|
Stop-Process -Id $Process.ProcessId -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
function Get-KkFileViewJavaProcesses {
|
|
$JarPattern = [regex]::Escape($JarName)
|
|
return Get-CimInstance Win32_Process | Where-Object {
|
|
$_.Name -match '^java(\.exe)?$' -and $_.CommandLine -and $_.CommandLine -match $JarPattern
|
|
}
|
|
}
|
|
|
|
function Get-KkFileViewLauncherProcesses {
|
|
$StartupPattern = [regex]::Escape([System.IO.Path]::GetFileName($StartupScript))
|
|
return Get-CimInstance Win32_Process | Where-Object {
|
|
$_.Name -ieq 'cmd.exe' -and $_.CommandLine -and $_.CommandLine -match $StartupPattern
|
|
}
|
|
}
|
|
|
|
function Wait-KkFileViewStopped {
|
|
param([int]$TimeoutSeconds = 30)
|
|
|
|
for ($i = 0; $i -lt $TimeoutSeconds; $i++) {
|
|
$JavaProcesses = @(Get-KkFileViewJavaProcesses)
|
|
$CmdProcesses = @(Get-KkFileViewLauncherProcesses)
|
|
if ((@($JavaProcesses).Count + @($CmdProcesses).Count) -eq 0) {
|
|
return $true
|
|
}
|
|
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
function Start-KkFileView {
|
|
Write-Step "Starting kkFileView"
|
|
$CreateResult = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{
|
|
CommandLine = ('cmd.exe /c ""' + $StartupScript + '""')
|
|
CurrentDirectory = $BinDir
|
|
}
|
|
|
|
if ($CreateResult.ReturnValue -ne 0) {
|
|
throw "Failed to start kkFileView launcher, Win32_Process.Create returned $($CreateResult.ReturnValue)"
|
|
}
|
|
|
|
Write-Step "Launcher process created with pid $($CreateResult.ProcessId)"
|
|
}
|
|
|
|
function Wait-Health {
|
|
param([string]$Url)
|
|
|
|
$SuccessfulChecks = 0
|
|
for ($i = 0; $i -lt 24; $i++) {
|
|
Start-Sleep -Seconds 5
|
|
try {
|
|
$Response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 5
|
|
if ($Response.StatusCode -eq 200 -and @(Get-KkFileViewJavaProcesses).Count -gt 0) {
|
|
$SuccessfulChecks++
|
|
} else {
|
|
$SuccessfulChecks = 0
|
|
}
|
|
|
|
if ($SuccessfulChecks -ge 3) {
|
|
return $true
|
|
}
|
|
} catch {
|
|
$SuccessfulChecks = 0
|
|
Start-Sleep -Milliseconds 200
|
|
}
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
Write-Step "Backing up current jar to $BackupJar"
|
|
Copy-Item $JarPath $BackupJar -Force
|
|
|
|
Stop-KkFileView
|
|
if (-not (Wait-KkFileViewStopped)) {
|
|
throw "Timed out waiting for the previous kkFileView process to exit"
|
|
}
|
|
|
|
Write-Step "Replacing jar with artifact output"
|
|
Copy-Item $DownloadedJar.FullName $JarPath -Force
|
|
|
|
Start-KkFileView
|
|
|
|
if (-not (Wait-Health -Url $HealthUrl)) {
|
|
Write-Step "Health check failed, rolling back"
|
|
Stop-KkFileView
|
|
if (-not (Wait-KkFileViewStopped)) {
|
|
throw "Timed out waiting for the failed kkFileView process to exit during rollback"
|
|
}
|
|
Copy-Item $BackupJar $JarPath -Force
|
|
Start-KkFileView
|
|
|
|
if (-not (Wait-Health -Url $HealthUrl)) {
|
|
throw "Deployment failed and rollback health check also failed"
|
|
}
|
|
|
|
throw "Deployment failed, rollback completed successfully"
|
|
}
|
|
|
|
Write-Step "Deployment completed successfully"
|