Release ForgeFlow 0.6.1

This commit is contained in:
NuklearRabbit
2026-07-25 06:18:11 +02:00
parent 9d3933c878
commit 971896a1d5
10 changed files with 229 additions and 49 deletions
+47 -11
View File
@@ -6,7 +6,8 @@ param(
[Parameter(Mandatory=$true)][int]$ParentPid,
[Parameter(Mandatory=$true)][string]$LogPath,
[Parameter(Mandatory=$true)][string]$StatusPath,
[Parameter(Mandatory=$true)][string]$UpdateId
[Parameter(Mandatory=$true)][string]$UpdateId,
[switch]$HandshakeOnly
)
$ErrorActionPreference = "Stop"
@@ -17,8 +18,9 @@ $backup = $null
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
$directory = Split-Path -Parent $LogPath
if ($directory) { New-Item -ItemType Directory -Force -Path $directory | Out-Null }
Add-Content -LiteralPath $LogPath -Value $line -Encoding UTF8
}
function Write-UpdateState {
@@ -27,6 +29,7 @@ function Write-UpdateState {
[string]$Message = "",
[hashtable]$Extra = @{}
)
$payload = [ordered]@{
schemaVersion = 1
updateId = $UpdateId
@@ -39,13 +42,28 @@ function Write-UpdateState {
updatedAt = (Get-Date).ToUniversalTime().ToString("o")
}
foreach ($key in $Extra.Keys) { $payload[$key] = $Extra[$key] }
$directory = Split-Path -Parent $StatusPath
New-Item -ItemType Directory -Force -Path $directory | Out-Null
if ($directory) { New-Item -ItemType Directory -Force -Path $directory | Out-Null }
$temporary = "$StatusPath.$PID.tmp"
$json = $payload | ConvertTo-Json -Depth 8
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($temporary, $json, $utf8NoBom)
Move-Item -LiteralPath $temporary -Destination $StatusPath -Force
try {
if ([System.IO.File]::Exists($StatusPath)) {
# Windows PowerShell 5.1 does not reliably let Move-Item -Force replace
# an existing file. File.Replace is atomic on the local NTFS volume.
[System.IO.File]::Replace($temporary, $StatusPath, $null)
} else {
[System.IO.File]::Move($temporary, $StatusPath)
}
} catch {
# Some filesystems do not implement File.Replace. Copy with overwrite is
# the deterministic fallback; the temporary file is removed afterwards.
[System.IO.File]::Copy($temporary, $StatusPath, $true)
[System.IO.File]::Delete($temporary)
}
}
function Invoke-Robocopy {
@@ -85,6 +103,11 @@ try {
Write-UpdateLog "ForgeFlow source update helper started for version $ExpectedVersion."
Write-UpdateState -State "started" -Message "The external update helper started successfully." -Extra @{ helperPid = $PID; startedAt = (Get-Date).ToUniversalTime().ToString("o") }
if ($HandshakeOnly) {
Write-UpdateLog "Handshake-only verification completed successfully."
exit 0
}
Write-UpdateState -State "waiting-for-exit" -Message "Waiting for the running ForgeFlow process to exit."
$deadline = (Get-Date).AddMinutes(2)
while (Get-Process -Id $ParentPid -ErrorAction SilentlyContinue) {
@@ -92,7 +115,7 @@ try {
Start-Sleep -Milliseconds 500
}
$actualHash = (Get-FileHash -Path $ArchivePath -Algorithm SHA256).Hash.ToLowerInvariant()
$actualHash = (Get-FileHash -LiteralPath $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"))
@@ -143,6 +166,13 @@ try {
try {
$restart = Start-ForgeFlow -WorkingDirectory $SourcePath
Write-UpdateLog "Update validated successfully. ForgeFlow was restarted directly with Electron PID $($restart.Id)."
Write-UpdateState -State "success" -Message "ForgeFlow $ExpectedVersion was installed and restarted successfully." -Extra @{
installedVersion = $ExpectedVersion
completedAt = $completedAt
restartLaunched = $true
restartPid = $restart.Id
restartError = $null
}
} catch {
$restartError = $_.Exception.Message
Write-UpdateLog "Update validated successfully, but automatic restart failed: $restartError"
@@ -159,10 +189,10 @@ try {
}
catch {
$failureMessage = $_.Exception.Message
Write-UpdateLog ("Update failed: " + $failureMessage)
Write-UpdateState -State "failed" -Message $failureMessage -Extra @{ failedAt = (Get-Date).ToUniversalTime().ToString("o") }
try { Write-UpdateLog ("Update failed: " + $failureMessage) } catch {}
try { Write-UpdateState -State "failed" -Message $failureMessage -Extra @{ failedAt = (Get-Date).ToUniversalTime().ToString("o") } } catch {}
try {
if ($backup -and (Test-Path $backup)) {
if ($backup -and (Test-Path -LiteralPath $backup)) {
Write-UpdateLog "Restoring previous source version."
Invoke-Robocopy -From $backup -To $SourcePath
Install-ForgeFlowDependencies -WorkingDirectory $SourcePath
@@ -176,6 +206,12 @@ catch {
try {
$rollbackRestart = Start-ForgeFlow -WorkingDirectory $SourcePath
Write-UpdateLog "Rollback restored and ForgeFlow restarted directly with Electron PID $($rollbackRestart.Id)."
Write-UpdateState -State "rolled-back" -Message $failureMessage -Extra @{
completedAt = $rollbackCompletedAt
restartLaunched = $true
restartPid = $rollbackRestart.Id
restartError = $null
}
} catch {
$rollbackRestartError = $_.Exception.Message
Write-UpdateLog ("Rollback restart failed: " + $rollbackRestartError)
@@ -188,8 +224,8 @@ catch {
}
}
} catch {
Write-UpdateLog ("Rollback failed: " + $_.Exception.Message)
Write-UpdateState -State "failed" -Message ("$failureMessage Rollback also failed: " + $_.Exception.Message) -Extra @{ completedAt = (Get-Date).ToUniversalTime().ToString("o") }
try { Write-UpdateLog ("Rollback failed: " + $_.Exception.Message) } catch {}
try { Write-UpdateState -State "failed" -Message ("$failureMessage Rollback also failed: " + $_.Exception.Message) -Extra @{ completedAt = (Get-Date).ToUniversalTime().ToString("o") } } catch {}
}
exit 1
}