Files
GTI_GERENCIADOR_FISCAL/scripts/build_windows_installer.ps1
T

95 lines
4.9 KiB
PowerShell

# Build the three Windows installer artifacts with PyInstaller:
#
# dist/installer/GTIFiscalAgent-Setup-<version>.exe (onefile, --uac-admin) <- main download artifact
# dist/installer/GTIFiscalAgentService/<host> (onedir) <- embedded in Setup, extracted to Program Files
# dist/installer/Uninstall.exe (onefile, --uac-admin) <- embedded in Setup, ARP uninstaller
# dist/installer/GTIFiscalAgent-Setup-<version>.exe.sha256
#
# Reproducibility = automated, repeatable, deterministic inputs + immutable
# PUBLISHED release (byte-identical hashes are NOT required).
#
# Requires (fails fast if missing): python with PyInstaller, pywin32, fdb,
# httpx; icacls for the ACL on credentials.bin.
[CmdletBinding()]
param(
[string]$Python = "python",
[switch]$SkipSetup = $false,
[switch]$SkipService = $false,
[switch]$SkipUninstall = $false
)
$ErrorActionPreference = "Stop"
$Root = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$Version = (Get-Content (Join-Path $Root "release\VERSION") -Raw).Trim()
$Out = Join-Path $Root "dist\installer"
$Work = Join-Path $Root "build\installer"
$SpecDir = Join-Path $Root "build\installer"
function Invoke-Step([string]$Title, [scriptblock]$Body) {
Write-Host "== $Title ==" -ForegroundColor Cyan
& $Body
if ($LASTEXITCODE -ne 0) { throw "$Title failed with exit code $LASTEXITCODE" }
}
Write-Host "Building GTI Fiscal Agent installer v$Version" -ForegroundColor Green
$py = (Get-Command $Python).Source
& $py -c "import PyInstaller, fdb, httpx, win32serviceutil; print('deps ok, pyinstaller', PyInstaller.__version__)"
if ($LASTEXITCODE -ne 0) { throw "build environment is missing PyInstaller/fdb/httpx/pywin32" }
if (-not (Get-Command "icacls" -ErrorAction SilentlyContinue)) { throw "missing required tool: icacls" }
$Paths = @("--paths", (Join-Path $Root "agent\src"), "--paths", (Join-Path $Root "agent\scripts"),
"--paths", (Join-Path $Root "agent\service"), "--paths", (Join-Path $Root "central"))
$Common = @("--noconfirm", "--clean", "--distpath", $Out, "--workpath", $Work, "--specpath", $SpecDir,
"--log-level", "WARN")
# win32crypt is imported lazily inside credential_store (function body), so the
# AST scan misses it; the agent service modules also need the pywin32 service libs.
$Hidden = @("--hidden-import=win32timezone", "--hidden-import=win32crypt",
"--hidden-import=win32serviceutil", "--hidden-import=win32service",
"--hidden-import=win32event", "--hidden-import=servicemanager")
# None of the reachable runtime modules import these (verified by tracing
# __import__ while loading run_agent_service's full chain); they only add
# ~100MB+ of dead weight via hook-gathered submodules. Exclude them.
$Excludes = @("--exclude-module=numpy", "--exclude-module=PIL", "--exclude-module=yaml",
"--exclude-module=scipy", "--exclude-module=pandas", "--exclude-module=matplotlib",
"--exclude-module=openpyxl", "--exclude-module=jinja2")
if (-not $SkipService) {
Invoke-Step "Build service host (onedir)" -Body {
& $py -m PyInstaller @Common @Paths @Hidden @Excludes "--onedir" `
"--name" "GTIFiscalAgentService" (Join-Path $Root "installer\service_main.py")
}
}
if (-not $SkipUninstall) {
Invoke-Step "Build Uninstall.exe (onefile, uac-admin)" -Body {
& $py -m PyInstaller @Common @Paths @Hidden @Excludes "--onefile" "--uac-admin" "--name" "Uninstall" `
(Join-Path $Root "installer\uninstall_main.py")
}
}
if (-not $SkipSetup) {
$ServiceData = (Join-Path $Out "GTIFiscalAgentService") + ";" + "GTIFiscalAgentService"
$UninstallData = (Join-Path $Out "Uninstall.exe") + ";" + "."
$ExecutorData = (Join-Path $Root "scripts\firebird_write_executor.py") + ";" + "scripts"
Invoke-Step "Build Setup.exe (onefile, uac-admin)" -Body {
& $py -m PyInstaller @Common @Paths @Hidden @Excludes "--onefile" "--uac-admin" "--name" "GTIFiscalAgent-Setup" `
"--add-data" $ServiceData "--add-data" $UninstallData "--add-data" $ExecutorData `
(Join-Path $Root "installer\setup_main.py")
}
}
$BuiltSetup = Join-Path $Out "GTIFiscalAgent-Setup.exe"
$FinalSetup = Join-Path $Out "GTIFiscalAgent-Setup-$Version.exe"
if (Test-Path $BuiltSetup) {
Move-Item -Force $BuiltSetup $FinalSetup
$Digest = (Get-FileHash -Algorithm SHA256 -Path $FinalSetup).Hash.ToLowerInvariant()
Set-Content -Path "$FinalSetup.sha256" -Value "$Digest $([IO.Path]::GetFileName($FinalSetup))`n" -NoNewline -Encoding Ascii
Write-Host "Installer: $FinalSetup" -ForegroundColor Green
Write-Host "sha256: $Digest" -ForegroundColor Green
} else {
Write-Host "Setup artifact not built (skipped); service host + Uninstall.exe still available under $Out" -ForegroundColor Yellow
}
Get-ChildItem $Out -Recurse | Select-Object FullName, Length | Format-Table -AutoSize
Write-Host "Build complete." -ForegroundColor Green