$ErrorActionPreference = 'Stop' $projectRoot = [IO.Path]::GetFullPath('C:\wechat_rpa') $artifactRoot = [IO.Path]::GetFullPath('C:\kefu\deploy\review-contacts-20260917') $buildPython = Join-Path $projectRoot '.build-venv\Scripts\python.exe' $appDir = Join-Path $projectRoot 'dist\ZhenAI-WeCom-Assistant-v1.4.23' if (Test-Path -LiteralPath $appDir) { throw 'Expected a new v1.4.23 output directory' } $versionLine = Get-Content -LiteralPath (Join-Path $projectRoot 'app_version.py') | Select-String '^APP_VERSION = "1.4.23"$' if (-not $versionLine) { throw 'Expected APP_VERSION 1.4.23 before build' } $sourceNames = @('wechat_rpa.spec','packaging_exporter.py','review_assistant.py','review_assistant_contacts.py','test_review_assistant_contacts.py','test_review_assistant_ui.py','send_lock.py','desktop_instance.py','wechat_gui.py','gui_runtime.py','wechat_bot.py','wecom_native_sender.py','wechat_gui_qt.py','protocol_engine.py','wxwork_protocol_probe.py','app_version.py','review_policy.py','review_state.py','reply_session_policy.py','wxwork_db.py','assets/ui/console-review.css','assets/ui/console-app.js','assets/ui/zhenyang-ai-console.html') $manifest = [ordered]@{} foreach ($name in $sourceNames) { $manifest[$name] = (Get-FileHash -LiteralPath (Join-Path $projectRoot $name) -Algorithm SHA256).Hash.ToLowerInvariant() } [IO.File]::WriteAllText((Join-Path $artifactRoot 'build-source-manifest.json'), ($manifest | ConvertTo-Json), [Text.UTF8Encoding]::new($false)) $env:LOCALAPPDATA = Join-Path $artifactRoot 'build-self-check-profile\Local' $env:APPDATA = Join-Path $artifactRoot 'build-self-check-profile\Roaming' New-Item -ItemType Directory -Path $env:LOCALAPPDATA,$env:APPDATA -Force | Out-Null $oldRelease = Join-Path $projectRoot 'releases\甄AI客服-安装包-v1.4.22.exe' $oldHash = (Get-FileHash -LiteralPath $oldRelease -Algorithm SHA256).Hash if ($oldHash -ne '86242d5c12ea140443e7f8b19440b24844fd2982ba233383cba0777e613f02d4') { throw 'Previous v1.4.22 release hash changed' } Push-Location $projectRoot try { & (Join-Path $projectRoot 'build_windows_exe.ps1') -PythonPath $buildPython *> (Join-Path $artifactRoot 'app-build.log') if ($LASTEXITCODE -ne 0) { throw 'Application build returned failure' } foreach ($name in $sourceNames) { $actual = (Get-FileHash -LiteralPath (Join-Path $projectRoot $name) -Algorithm SHA256).Hash.ToLowerInvariant() if ($actual -ne $manifest[$name]) { throw ('Source changed during build: ' + $name) } } & (Join-Path $projectRoot 'build_installer.ps1') -SkipAppBuild *> (Join-Path $artifactRoot 'installer-build.log') if ($LASTEXITCODE -ne 0) { throw 'Installer build returned failure' } if ((Get-FileHash -LiteralPath $oldRelease -Algorithm SHA256).Hash -ne $oldHash) { throw 'Previous release changed during build' } Write-Output 'Application and installer build completed with production self-check.' } finally { Pop-Location }