fix: make updater checksum verification self-contained
ForgeFlow quality gate / quality (push) Canceled after 0s
ForgeFlow quality gate / quality (push) Canceled after 0s
This commit is contained in:
@@ -8,7 +8,8 @@ param(
|
||||
[Parameter(Mandatory = $true)][string]$LogPath,
|
||||
[Parameter(Mandatory = $true)][string]$StatusPath,
|
||||
[Parameter(Mandatory = $true)][string]$UpdateId,
|
||||
[switch]$HandshakeOnly
|
||||
[switch]$HandshakeOnly,
|
||||
[switch]$VerifyOnly
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -51,6 +52,16 @@ function Write-UpdateState {
|
||||
function Write-Log([string]$Message) {
|
||||
"{0} {1}" -f [DateTime]::UtcNow.ToString("o"), $Message | Add-Content -LiteralPath $LogPath -Encoding UTF8
|
||||
}
|
||||
function Get-Sha256([string]$Path) {
|
||||
$stream = [IO.File]::OpenRead($Path)
|
||||
$algorithm = [Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return ([BitConverter]::ToString($algorithm.ComputeHash($stream))).Replace("-", "").ToLowerInvariant()
|
||||
} finally {
|
||||
$algorithm.Dispose()
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Write-UpdateState -State "started" -Message "Binary updater owns the update request."
|
||||
@@ -59,9 +70,13 @@ try {
|
||||
Write-Log "Handshake-only verification completed successfully."
|
||||
exit 0
|
||||
}
|
||||
$actualSha256 = (Get-FileHash -LiteralPath $BinaryPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$actualSha256 = Get-Sha256 -Path $BinaryPath
|
||||
if ($actualSha256 -ne $ExpectedSha256.ToLowerInvariant()) { throw "Binary update SHA-256 verification failed." }
|
||||
if (-not (Test-Path -LiteralPath $CurrentExecutable -PathType Leaf)) { throw "Current ForgeFlow executable was not found." }
|
||||
if ($VerifyOnly) {
|
||||
Write-Log "Verification-only SHA-256 check completed successfully."
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-UpdateState -State "waiting-for-exit" -Message "Waiting for ForgeFlow to close."
|
||||
try { Wait-Process -Id $ParentPid -Timeout 60 -ErrorAction Stop } catch {
|
||||
|
||||
@@ -71,6 +71,17 @@ function Write-UpdateState {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-Sha256([string]$Path) {
|
||||
$stream = [IO.File]::OpenRead($Path)
|
||||
$algorithm = [Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return ([BitConverter]::ToString($algorithm.ComputeHash($stream))).Replace("-", "").ToLowerInvariant()
|
||||
} finally {
|
||||
$algorithm.Dispose()
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-Robocopy {
|
||||
param([string]$From, [string]$To)
|
||||
New-Item -ItemType Directory -Force -Path $To | Out-Null
|
||||
@@ -120,7 +131,7 @@ try {
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
$actualHash = (Get-FileHash -LiteralPath $ArchivePath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$actualHash = Get-Sha256 -Path $ArchivePath
|
||||
if ($actualHash -ne $ExpectedSha256.ToLowerInvariant()) { throw "Update archive checksum mismatch." }
|
||||
|
||||
$working = Join-Path ([IO.Path]::GetTempPath()) ("forgeflow-update-" + [guid]::NewGuid().ToString("N"))
|
||||
|
||||
+7
-2
@@ -87,6 +87,7 @@ const required = [
|
||||
"docs/RELEASE_NOTES_0.10.5.md",
|
||||
"docs/RELEASE_NOTES_0.10.6.md",
|
||||
"docs/RELEASE_NOTES_0.10.7.md",
|
||||
"docs/RELEASE_NOTES_0.10.8.md",
|
||||
"docs/UPDATING.md",
|
||||
"docs/DIAGNOSTICS.md",
|
||||
"docs/DEPLOYMENT_SETUP.md",
|
||||
@@ -125,9 +126,9 @@ for (const file of required) await access(path.join(root, file));
|
||||
const packageJson = JSON.parse(
|
||||
await readFile(path.join(root, "package.json"), "utf8"),
|
||||
);
|
||||
if (packageJson.version !== "0.10.7")
|
||||
if (packageJson.version !== "0.10.8")
|
||||
throw new Error(
|
||||
`Expected package version 0.10.7, got ${packageJson.version}.`,
|
||||
`Expected package version 0.10.8, got ${packageJson.version}.`,
|
||||
);
|
||||
const sourceManifest = await readFile(
|
||||
path.join(root, "SOURCE_MANIFEST.txt"),
|
||||
@@ -469,6 +470,10 @@ const release0107 = await readFile(path.join(root, "docs/RELEASE_NOTES_0.10.7.md
|
||||
for (const phrase of ["exact provenance", "automatic", "repository sidebar", "DevRunbook", "no container changes"]) {
|
||||
if (!release0107.includes(phrase)) throw new Error(`0.10.7 release notes are missing: ${phrase}`);
|
||||
}
|
||||
const release0108 = await readFile(path.join(root, "docs/RELEASE_NOTES_0.10.8.md"), "utf8");
|
||||
for (const phrase of ["Get-FileHash", ".NET SHA-256", "PSModulePath", "binary", "source update helpers"]) {
|
||||
if (!release0108.includes(phrase)) throw new Error(`0.10.8 release notes are missing: ${phrase}`);
|
||||
}
|
||||
const configSource = await readFile(path.join(root, "src/main/config-store.cjs"), "utf8");
|
||||
for (const mode of ["server-git", "push-bundle", "monitor-only"]) {
|
||||
if (!configSource.includes(mode)) throw new Error(`Deployment configuration is missing mode: ${mode}`);
|
||||
|
||||
Reference in New Issue
Block a user