diff --git a/PRODUCTION_READINESS.md b/PRODUCTION_READINESS.md index 9c6fe470..b26e4bd6 100644 --- a/PRODUCTION_READINESS.md +++ b/PRODUCTION_READINESS.md @@ -56,6 +56,7 @@ Date: 2026-06-08. - Windows local autostart was repaired on 2026-06-10 with `scripts/repair-windows-autostart.ps1 -Launch`: the HKCU Run key `QSfera` points to the Craft runtime `bin\qsfera.exe`, required Qt6 runtime DLLs are present there, and `qsfera.exe` started from that path. - Windows tray "Show" now brings the settings window to the foreground after restoring it to an available screen. The same `Application::showSettings()` path is used by tray menu actions and `qsfera.exe --show`, and Win32 window enumeration on 2026-06-10 reported `Visible=True`, `Foreground=True`, title `КуСфера`. - Windows Desktop now has repeatable local packaging and feed-publication scripts. `scripts/package-windows-desktop.ps1` produced a smoke-tested `4.0.0` x64 package with Qt/MSVC runtime files; `scripts/publish-windows-desktop.ps1` generated a valid local `stable.xml` feed for that MSI and refuses remote publication unless the MSI is Authenticode-signed. +- Windows Desktop packaging now fails before ZIP/MSI creation if the staged app is missing critical Qt6/MSVC/OpenSSL DLLs, the Qt platform plugin, QSfera VFS plugins, QML import manifests, or `qt.conf` runtime path entries; it also smoke-starts the staged `qsfera.exe --version` from the staged working directory. - Added `scripts/verify-production-state.ps1` as a repeatable live production endpoint gate for the public server status, Android Argus manifest/download, and Desktop update feed. - `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-10: server `edition=stable`/`productversion=7.0.0`, Android `1.3.12`/`40`, downloaded APK size `12237552`, APK SHA-256 `279d00c6a43072caa0b26269f547fb0dc3268088aae5cd9f4ccfbbb485c35ded`, and valid Desktop no-update feed. - `scripts/verify-production-state.ps1 -VerifyAndroidDownload` passed on 2026-06-12: server `edition=stable`/`productversion=7.0.0`, Android `1.3.13`/`41`, downloaded APK size `12261408`, APK SHA-256 `f065e6584e6a09999e72ba0eeeaae903e93fb8980a0426e4b39b5e2366bf6611`, and valid Desktop no-update feed. diff --git a/scripts/package-windows-desktop.ps1 b/scripts/package-windows-desktop.ps1 index 57fd5d72..aea5a381 100644 --- a/scripts/package-windows-desktop.ps1 +++ b/scripts/package-windows-desktop.ps1 @@ -63,6 +63,64 @@ function Copy-DirectoryIfPresent([string]$Source, [string]$Destination) { Copy-Item -Path (Join-Path $Source "*") -Destination $Destination -Recurse -Force } +function Assert-StageFile([string]$StageDirectory, [string]$RelativePath) { + $path = Join-Path $StageDirectory $RelativePath + if (-not (Test-Path -LiteralPath $path)) { + Fail "Packaged runtime file is missing: $path" + } + + if ((Get-Item -LiteralPath $path).Length -le 0) { + Fail "Packaged runtime file is empty: $path" + } +} + +function Assert-WindowsRuntimeStage([string]$StageDirectory) { + $criticalFiles = @( + "qsfera.exe", + "qt.conf", + "Qt6Core.dll", + "Qt6Gui.dll", + "Qt6Widgets.dll", + "Qt6Network.dll", + "Qt6Qml.dll", + "Qt6Quick.dll", + "Qt6QuickControls2.dll", + "qt6keychain.dll", + "kdsingleapplication-qt6.dll", + "libcrypto-3-x64.dll", + "libssl-3-x64.dll", + "plugins\platforms\qwindows.dll", + "plugins\tls\qschannelbackend.dll", + "plugins\QSfera_vfs_cfapi.dll", + "plugins\QSfera_vfs_off.dll", + "qml\eu\QSfera\gui\qmldir", + "qml\QtQuick\Controls\qmldir" + ) + + foreach ($file in $criticalFiles) { + Assert-StageFile -StageDirectory $StageDirectory -RelativePath $file + } + + $qtConf = Get-Content -LiteralPath (Join-Path $StageDirectory "qt.conf") -Raw -Encoding ASCII + foreach ($entry in @("Plugins=plugins", "Qml2Imports=qml", "Translations=translations")) { + if (-not $qtConf.Contains($entry)) { + Fail "qt.conf does not contain required entry '$entry'." + } + } + + Push-Location $StageDirectory + try { + $versionOutput = & (Join-Path $StageDirectory "qsfera.exe") --version 2>&1 + if ($LASTEXITCODE -ne 0) { + Fail "Packaged qsfera.exe failed to start from the staging directory. Output: $($versionOutput | Out-String)" + } + } finally { + Pop-Location + } + + Write-Output "OK: packaged Windows runtime contains required Qt/MSVC/OpenSSL files and qsfera.exe --version starts from the staging directory." +} + function ConvertTo-WixIdentifier([string]$Prefix, [string]$Value) { $normalized = ($Value -replace '[^A-Za-z0-9_]', '_') if ($normalized.Length -gt 60) { @@ -312,6 +370,8 @@ Qml2Imports=qml Translations=translations "@ | Set-Content -LiteralPath (Join-Path $StageDirectory "qt.conf") -Encoding ASCII +Assert-WindowsRuntimeStage -StageDirectory $StageDirectory + Remove-PathWithRetry $zipPath Compress-ArchiveWithRetry -SourcePath (Join-Path $StageDirectory "*") -DestinationPath $zipPath