Update
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$SourcePath,
|
||||
[Parameter(Mandatory=$true)][string]$ArchivePath,
|
||||
[Parameter(Mandatory=$true)][string]$ExpectedVersion,
|
||||
[Parameter(Mandatory=$true)][string]$ExpectedSha256,
|
||||
[Parameter(Mandatory=$true)][int]$ParentPid,
|
||||
[Parameter(Mandatory=$true)][string]$LogPath
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
function Write-UpdateLog {
|
||||
param([string]$Message)
|
||||
$line = "$(Get-Date -Format o) $Message"
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $LogPath) | Out-Null
|
||||
Add-Content -Path $LogPath -Value $line -Encoding UTF8
|
||||
}
|
||||
|
||||
function Invoke-Robocopy {
|
||||
param([string]$From, [string]$To)
|
||||
New-Item -ItemType Directory -Force -Path $To | Out-Null
|
||||
& robocopy.exe $From $To /MIR /R:2 /W:1 /NFL /NDL /NJH /NJS /NP /XD node_modules .git dist | Out-Null
|
||||
if ($LASTEXITCODE -gt 7) { throw "robocopy failed with exit code $LASTEXITCODE" }
|
||||
}
|
||||
|
||||
try {
|
||||
Write-UpdateLog "ForgeFlow source update started for version $ExpectedVersion."
|
||||
$deadline = (Get-Date).AddMinutes(2)
|
||||
while (Get-Process -Id $ParentPid -ErrorAction SilentlyContinue) {
|
||||
if ((Get-Date) -gt $deadline) { throw "ForgeFlow did not exit before the update timeout." }
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
$actualHash = (Get-FileHash -Path $ArchivePath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
if ($actualHash -ne $ExpectedSha256.ToLowerInvariant()) { throw "Update archive checksum mismatch." }
|
||||
|
||||
$working = Join-Path ([IO.Path]::GetTempPath()) ("forgeflow-update-" + [guid]::NewGuid().ToString("N"))
|
||||
$extract = Join-Path $working "extract"
|
||||
$backup = Join-Path $working "backup"
|
||||
New-Item -ItemType Directory -Force -Path $extract | Out-Null
|
||||
Write-UpdateLog "Creating source backup."
|
||||
Invoke-Robocopy -From $SourcePath -To $backup
|
||||
|
||||
Write-UpdateLog "Extracting update archive."
|
||||
Expand-Archive -LiteralPath $ArchivePath -DestinationPath $extract -Force
|
||||
$manifest = Get-ChildItem -Path $extract -Filter package.json -File -Recurse |
|
||||
Where-Object {
|
||||
try {
|
||||
$json = Get-Content $_.FullName -Raw | ConvertFrom-Json
|
||||
return $json.name -eq "forgeflow" -and $json.version -eq $ExpectedVersion
|
||||
} catch { return $false }
|
||||
} |
|
||||
Select-Object -First 1
|
||||
|
||||
if (-not $manifest) { throw "The update does not contain ForgeFlow version $ExpectedVersion." }
|
||||
$incoming = Split-Path -Parent $manifest.FullName
|
||||
Write-UpdateLog "Applying verified source files."
|
||||
Invoke-Robocopy -From $incoming -To $SourcePath
|
||||
|
||||
Push-Location $SourcePath
|
||||
try {
|
||||
Write-UpdateLog "Installing exact dependencies."
|
||||
& cmd.exe /d /s /c "npm install --no-audit --no-fund" *>> $LogPath
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm install failed with exit code $LASTEXITCODE." }
|
||||
Write-UpdateLog "Running ForgeFlow quality gate."
|
||||
& cmd.exe /d /s /c "npm run check" *>> $LogPath
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm run check failed with exit code $LASTEXITCODE." }
|
||||
} finally { Pop-Location }
|
||||
|
||||
Write-UpdateLog "Update validated successfully. Restarting ForgeFlow."
|
||||
Start-Process -FilePath "cmd.exe" -WorkingDirectory $SourcePath -ArgumentList "/d", "/s", "/c", "npm start"
|
||||
Remove-Item -LiteralPath $working -Recurse -Force -ErrorAction SilentlyContinue
|
||||
exit 0
|
||||
}
|
||||
catch {
|
||||
Write-UpdateLog ("Update failed: " + $_.Exception.Message)
|
||||
try {
|
||||
if ($backup -and (Test-Path $backup)) {
|
||||
Write-UpdateLog "Restoring previous source version."
|
||||
Invoke-Robocopy -From $backup -To $SourcePath
|
||||
Push-Location $SourcePath
|
||||
try {
|
||||
& cmd.exe /d /s /c "npm install --no-audit --no-fund" *>> $LogPath
|
||||
} finally { Pop-Location }
|
||||
Start-Process -FilePath "cmd.exe" -WorkingDirectory $SourcePath -ArgumentList "/d", "/s", "/c", "npm start"
|
||||
}
|
||||
} catch {
|
||||
Write-UpdateLog ("Rollback failed: " + $_.Exception.Message)
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
Reference in New Issue
Block a user