341 lines
10 KiB
PowerShell
341 lines
10 KiB
PowerShell
# GSP Windows Agent Updater - PowerShell Script
|
|
# This script updates an existing Git-managed agent installation
|
|
|
|
#Requires -RunAsAdministrator
|
|
|
|
param(
|
|
[string]$InstallPath = "C:\GSP",
|
|
[string]$GitBranch = "master"
|
|
)
|
|
|
|
$Script:AgentDir = Join-Path $InstallPath "Agent"
|
|
$Script:GitDir = Join-Path $InstallPath "tools\PortableGit"
|
|
$Script:BackupDir = Join-Path $InstallPath "backups\agent"
|
|
$Script:LogsDir = Join-Path $InstallPath "logs"
|
|
$Script:UpdateLogFile = Join-Path $Script:LogsDir "update.log"
|
|
|
|
function Log-Message {
|
|
param([string]$Message, [switch]$IsError = $false)
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$logLine = "[$timestamp] $Message"
|
|
|
|
if ($IsError) {
|
|
Write-Host $logLine -ForegroundColor Red
|
|
} else {
|
|
Write-Host $logLine
|
|
}
|
|
|
|
Add-Content -Path $Script:UpdateLogFile -Value $logLine -Force
|
|
}
|
|
|
|
function Test-Administrator {
|
|
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
|
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
}
|
|
|
|
function Stop-Agent {
|
|
Log-Message "Stopping agent..."
|
|
|
|
try {
|
|
# Try to stop the scheduled task
|
|
Stop-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
|
Log-Message "Scheduled task stopped"
|
|
|
|
# Give it a moment to shut down gracefully
|
|
Start-Sleep -Seconds 2
|
|
|
|
# Kill any remaining bash/perl processes from the agent
|
|
Get-Process bash,perl -ErrorAction SilentlyContinue | ForEach-Object {
|
|
try {
|
|
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
|
|
Log-Message "Killed remaining process: $($_.Name) (PID: $($_.Id))"
|
|
} catch {
|
|
# Process may already be gone
|
|
}
|
|
}
|
|
|
|
return $true
|
|
} catch {
|
|
Log-Message "WARNING stopping agent: $_" -IsError $true
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Backup-Agent {
|
|
Log-Message "Backing up current agent..."
|
|
|
|
try {
|
|
$backupName = "agent-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
$backupPath = Join-Path $Script:BackupDir $backupName
|
|
|
|
Log-Message "Backup destination: $backupPath"
|
|
|
|
Copy-Item -Path $Script:AgentDir -Destination $backupPath -Recurse -Force
|
|
|
|
Log-Message "Backup completed successfully"
|
|
return $backupPath
|
|
} catch {
|
|
Log-Message "ERROR creating backup: $_" -IsError $true
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Preserve-LocalFolders {
|
|
Log-Message "Preserving local configuration and runtime folders..."
|
|
|
|
$preserved = @{}
|
|
$preserveFolders = @("Cfg", "steamcmd", "screenlogs", "startups", "tmp", "shared")
|
|
|
|
try {
|
|
foreach ($folder in $preserveFolders) {
|
|
$folderPath = Join-Path $Script:AgentDir $folder
|
|
if (Test-Path $folderPath) {
|
|
$tempPath = Join-Path $env:TEMP "gsp_preserve_$folder"
|
|
if (Test-Path $tempPath) {
|
|
Remove-Item $tempPath -Recurse -Force
|
|
}
|
|
Copy-Item -Path $folderPath -Destination $tempPath -Recurse -Force
|
|
$preserved[$folder] = $tempPath
|
|
Log-Message " Preserved: $folder"
|
|
}
|
|
}
|
|
|
|
return $preserved
|
|
} catch {
|
|
Log-Message "ERROR preserving folders: $_" -IsError $true
|
|
return @{}
|
|
}
|
|
}
|
|
|
|
function Update-Repository {
|
|
Log-Message "Updating repository from Git..."
|
|
|
|
try {
|
|
$gitExe = Join-Path $Script:GitDir "cmd\git.exe"
|
|
|
|
if (-not (Test-Path $gitExe)) {
|
|
Log-Message "ERROR: git.exe not found at: $gitExe" -IsError $true
|
|
return $false
|
|
}
|
|
|
|
if (-not (Test-Path (Join-Path $Script:AgentDir ".git"))) {
|
|
Log-Message "ERROR: Agent directory is not a Git repository (.git folder not found)" -IsError $true
|
|
Log-Message "The agent must be installed with the Git-based installer to use this update script"
|
|
return $false
|
|
}
|
|
|
|
Log-Message "Running git fetch..."
|
|
$fetchProcess = Start-Process -FilePath $gitExe `
|
|
-ArgumentList "fetch", "origin" `
|
|
-Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir
|
|
|
|
if ($fetchProcess.ExitCode -ne 0) {
|
|
Log-Message "ERROR: git fetch failed with code: $($fetchProcess.ExitCode)" -IsError $true
|
|
return $false
|
|
}
|
|
|
|
Log-Message "Running git reset to $GitBranch..."
|
|
$resetProcess = Start-Process -FilePath $gitExe `
|
|
-ArgumentList "reset", "--hard", "origin/$GitBranch" `
|
|
-Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir
|
|
|
|
if ($resetProcess.ExitCode -ne 0) {
|
|
Log-Message "ERROR: git reset failed with code: $($resetProcess.ExitCode)" -IsError $true
|
|
return $false
|
|
}
|
|
|
|
Log-Message "Repository updated successfully"
|
|
return $true
|
|
} catch {
|
|
Log-Message "ERROR updating repository: $_" -IsError $true
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Restore-LocalFolders {
|
|
param([hashtable]$PreservedFolders)
|
|
|
|
Log-Message "Restoring preserved local folders..."
|
|
|
|
try {
|
|
foreach ($folder in $PreservedFolders.Keys) {
|
|
$tempPath = $PreservedFolders[$folder]
|
|
$targetPath = Join-Path $Script:AgentDir $folder
|
|
|
|
if (Test-Path $targetPath) {
|
|
Remove-Item -Path $targetPath -Recurse -Force
|
|
}
|
|
|
|
Copy-Item -Path $tempPath -Destination $targetPath -Recurse -Force
|
|
Remove-Item -Path $tempPath -Recurse -Force
|
|
|
|
Log-Message " Restored: $folder"
|
|
}
|
|
|
|
return $true
|
|
} catch {
|
|
Log-Message "ERROR restoring folders: $_" -IsError $true
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Validate-Agent {
|
|
Log-Message "Validating agent syntax..."
|
|
|
|
try {
|
|
$agentScript = Join-Path $Script:AgentDir "OGP64\OGP\ogp_agent.pl"
|
|
|
|
if (-not (Test-Path $agentScript)) {
|
|
Log-Message "WARNING: ogp_agent.pl not found, skipping syntax check"
|
|
return $true
|
|
}
|
|
|
|
# Try to run perl syntax check
|
|
$perlCheck = Start-Process -FilePath "perl.exe" `
|
|
-ArgumentList "-c", $agentScript `
|
|
-Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue
|
|
|
|
if ($perlCheck.ExitCode -ne 0) {
|
|
Log-Message "WARNING: Perl syntax check failed, but update may still be valid" -IsError $true
|
|
} else {
|
|
Log-Message "Perl syntax validation passed"
|
|
}
|
|
|
|
return $true
|
|
} catch {
|
|
Log-Message "WARNING: Could not validate agent syntax: $_" -IsError $true
|
|
return $true
|
|
}
|
|
}
|
|
|
|
function Start-Agent {
|
|
Log-Message "Starting agent..."
|
|
|
|
try {
|
|
Start-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
|
Log-Message "Scheduled task started"
|
|
return $true
|
|
} catch {
|
|
Log-Message "WARNING: Could not start scheduled task immediately" -IsError $true
|
|
Log-Message "Agent will start at next system boot"
|
|
return $true
|
|
}
|
|
}
|
|
|
|
function Rollback-Update {
|
|
param([string]$BackupPath)
|
|
|
|
Log-Message "ROLLING BACK UPDATE..."
|
|
|
|
if (-not (Test-Path $BackupPath)) {
|
|
Log-Message "ERROR: Backup not found, cannot rollback" -IsError $true
|
|
return $false
|
|
}
|
|
|
|
try {
|
|
Log-Message "Restoring from backup: $BackupPath"
|
|
|
|
# Stop agent first
|
|
Stop-Agent | Out-Null
|
|
|
|
# Remove updated directory
|
|
if (Test-Path $Script:AgentDir) {
|
|
Remove-Item -Path $Script:AgentDir -Recurse -Force
|
|
}
|
|
|
|
# Restore backup
|
|
Copy-Item -Path $BackupPath -Destination $Script:AgentDir -Recurse -Force
|
|
|
|
# Restart agent
|
|
Start-Agent | Out-Null
|
|
|
|
Log-Message "Rollback completed successfully"
|
|
return $true
|
|
} catch {
|
|
Log-Message "ERROR during rollback: $_" -IsError $true
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Main {
|
|
Log-Message "========================================="
|
|
Log-Message "GSP Windows Agent Update"
|
|
Log-Message "========================================="
|
|
Log-Message "Install Path: $InstallPath"
|
|
Log-Message "Git Branch: $GitBranch"
|
|
Log-Message ""
|
|
|
|
# Check admin
|
|
if (-not (Test-Administrator)) {
|
|
Log-Message "ERROR: This script must be run as Administrator" -IsError $true
|
|
exit 1
|
|
}
|
|
|
|
# Verify directories exist
|
|
if (-not (Test-Path $Script:AgentDir)) {
|
|
Log-Message "ERROR: Agent not found at: $Script:AgentDir" -IsError $true
|
|
exit 1
|
|
}
|
|
|
|
if (-not (Test-Path $Script:GitDir)) {
|
|
Log-Message "ERROR: Portable Git not found at: $Script:GitDir" -IsError $true
|
|
exit 1
|
|
}
|
|
|
|
# Create logs directory if needed
|
|
if (-not (Test-Path $Script:LogsDir)) {
|
|
New-Item -ItemType Directory -Path $Script:LogsDir -Force | Out-Null
|
|
}
|
|
|
|
# Stop agent
|
|
Stop-Agent
|
|
|
|
# Create backup
|
|
$backupPath = Backup-Agent
|
|
if (-not $backupPath) {
|
|
Log-Message "FATAL: Could not create backup" -IsError $true
|
|
exit 1
|
|
}
|
|
|
|
# Preserve local folders
|
|
$preserved = Preserve-LocalFolders
|
|
|
|
# Update from Git
|
|
if (-not (Update-Repository)) {
|
|
Log-Message "FATAL: Update failed, rolling back..." -IsError $true
|
|
Rollback-Update $backupPath | Out-Null
|
|
exit 1
|
|
}
|
|
|
|
# Restore preserved folders
|
|
if ($preserved.Count -gt 0) {
|
|
if (-not (Restore-LocalFolders $preserved)) {
|
|
Log-Message "WARNING: Failed to restore all folders" -IsError $true
|
|
Rollback-Update $backupPath | Out-Null
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# Validate agent
|
|
Validate-Agent
|
|
|
|
# Start agent
|
|
Start-Agent
|
|
|
|
Log-Message ""
|
|
Log-Message "========================================="
|
|
Log-Message "Update Complete!"
|
|
Log-Message "========================================="
|
|
Log-Message "Agent has been updated successfully"
|
|
Log-Message "Backup location: $backupPath"
|
|
Log-Message "Log file: $Script:UpdateLogFile"
|
|
Log-Message ""
|
|
Log-Message "The agent will restart at the next opportunity"
|
|
Log-Message ""
|
|
|
|
Read-Host "Press Enter to close this window"
|
|
}
|
|
|
|
Main
|