91 lines
6.3 KiB
PowerShell
91 lines
6.3 KiB
PowerShell
param([switch]$SkipTests)
|
|
$ErrorActionPreference = 'Stop'
|
|
$root = Split-Path -Parent $PSScriptRoot
|
|
& (Join-Path $PSScriptRoot 'build-launcher.ps1')
|
|
& (Join-Path $PSScriptRoot 'sync.ps1')
|
|
if (-not $SkipTests) { & (Join-Path $PSScriptRoot 'test.ps1') }
|
|
$report = Join-Path $root 'artifacts\validation.json'
|
|
if (-not (Test-Path -LiteralPath $report)) { throw 'Нет отчёта проверки. Сначала выполните scripts/test.ps1.' }
|
|
$validated = Get-Content -LiteralPath $report -Raw | ConvertFrom-Json
|
|
if ($validated.status -ne 'passed') { throw 'Отчёт проверки CAD содержит ошибки.' }
|
|
if ($null -eq $validated.native_exit_code -or $validated.native_exit_code -ne 0) {
|
|
throw 'Не подтверждено корректное завершение CAD-процесса. Запустите scripts/test.ps1.'
|
|
}
|
|
if (-not $validated.source_sha256 -or $validated.source_sha256.Count -eq 0) {
|
|
throw 'В отчёте проверки нет снимка исходного кода. Выполните scripts/test.ps1.'
|
|
}
|
|
# Compare the complete current set too: checking only saved entries would let
|
|
# newly added, untested commands enter a -SkipTests package unnoticed.
|
|
$currentSources = foreach ($directory in @('src', 'tests', 'scripts')) {
|
|
Get-ChildItem -LiteralPath (Join-Path $root $directory) -File -Recurse |
|
|
Where-Object {
|
|
$_.Name -notmatch '\.(pyc|FCBak)$' -and
|
|
$_.FullName.Substring($root.Length + 1) -notmatch '(^|[\\/])(bin|obj|__pycache__)([\\/]|$)'
|
|
} | ForEach-Object { $_.FullName.Substring($root.Length + 1) }
|
|
}
|
|
$validatedPaths = @($validated.source_sha256 | ForEach-Object { $_.path } | Sort-Object)
|
|
$currentPaths = @($currentSources | Sort-Object)
|
|
if (($validatedPaths -join "`n") -cne ($currentPaths -join "`n")) {
|
|
throw 'Состав исходных файлов изменился после проверки. Выполните scripts/test.ps1.'
|
|
}
|
|
foreach ($file in $validated.source_sha256) {
|
|
$current = (Get-FileHash -LiteralPath (Join-Path $root $file.path) -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
if ($current -ne $file.sha256) { throw "Исходный файл изменился после проверки: $($file.path). Выполните scripts/test.ps1." }
|
|
}
|
|
$enginePath = Join-Path $root ((Get-Content -LiteralPath (Join-Path $root 'data\runtime-path.txt') -Raw).Trim())
|
|
$engineRoot = Split-Path -Parent (Split-Path -Parent $enginePath)
|
|
$workbench = Join-Path $engineRoot 'Mod\QInventor'
|
|
if (-not (Test-Path -LiteralPath $workbench)) { $workbench = Join-Path (Split-Path -Parent $enginePath) 'Mod\QInventor' }
|
|
$sourceRoot = Join-Path $root 'src\QInventor'
|
|
$sourceFiles = @(Get-ChildItem -LiteralPath $sourceRoot -File -Recurse |
|
|
Where-Object { $_.Extension -ne '.pyc' -and $_.FullName -notmatch '[\\/]__pycache__[\\/]' })
|
|
$moduleFiles = @(Get-ChildItem -LiteralPath $workbench -File -Recurse |
|
|
Where-Object { $_.Extension -ne '.pyc' -and $_.FullName -notmatch '[\\/]__pycache__[\\/]' })
|
|
$sourceNames = @($sourceFiles | ForEach-Object { $_.FullName.Substring($sourceRoot.Length + 1) } | Sort-Object)
|
|
$moduleNames = @($moduleFiles | ForEach-Object { $_.FullName.Substring($workbench.Length + 1) } | Sort-Object)
|
|
if (($sourceNames -join "`n") -cne ($moduleNames -join "`n")) {
|
|
throw 'Рабочая среда CAD содержит файлы, которых нет в проверенном снимке исходного кода.'
|
|
}
|
|
foreach ($file in $sourceFiles) {
|
|
$nativeCopy = Join-Path $workbench $file.FullName.Substring($sourceRoot.Length + 1)
|
|
if ((Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $nativeCopy -Algorithm SHA256).Hash) {
|
|
throw "Рабочая среда CAD отличается от проверенного исходного кода: $($file.Name)"
|
|
}
|
|
}
|
|
$release = Join-Path $root 'release'
|
|
New-Item -ItemType Directory -Path $release -Force | Out-Null
|
|
$sourceHashes = Get-ChildItem -LiteralPath (Join-Path $root 'src') -File -Recurse |
|
|
Where-Object { $_.Extension -ne '.pyc' } | ForEach-Object {
|
|
@{ path = $_.FullName.Substring($root.Length+1); sha256 = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant() }
|
|
}
|
|
$manifest = @{
|
|
application = 'QInventor'; version = '1.0.0'; platform = 'Windows x64';
|
|
engine = 'FreeCAD 1.1.4 / Open CASCADE';
|
|
officialRuntimeArchiveSha256 = '4828741fc91ee37fafcdb97a1abacb18b04ba451ac4372d9ff7a7349b36f4d6d';
|
|
builtAtUtc = [DateTime]::UtcNow.ToString('o');
|
|
launcherSha256 = (Get-FileHash -LiteralPath (Join-Path $root 'QInventor.exe') -Algorithm SHA256).Hash.ToLowerInvariant();
|
|
validation = $validated; sources = @($sourceHashes)
|
|
}
|
|
$manifest | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath (Join-Path $root 'manifest.json') -Encoding utf8
|
|
Copy-Item -LiteralPath $report -Destination (Join-Path $release 'validation.json') -Force
|
|
$archive = Join-Path $release 'QInventor-1.0.0-win-x64-portable.zip'
|
|
if (Test-Path -LiteralPath $archive) {
|
|
Move-Item -LiteralPath $archive -Destination (Join-Path $release "QInventor-previous-$([DateTime]::Now.ToString('yyyyMMdd-HHmmss')).zip")
|
|
}
|
|
$files = @('QInventor.exe','QInventor.cmd','README.md','LICENSE','THIRD_PARTY_NOTICES.md','manifest.json',
|
|
'runtime','src','scripts','tests','docs','examples','data\runtime-path.txt')
|
|
Push-Location $root
|
|
try {
|
|
& 'C:\Program Files\7-Zip\7z.exe' a -tzip $archive @files '-xr!__pycache__' '-xr!*.pyc' '-xr!*.pdb' '-xr!*.FCStd1' '-xr!*.FCBak' '-xr!obj' '-xr!artifacts' '-x!scripts\launcher\bin\*' -mx1 -bsp0 -bso0
|
|
if ($LASTEXITCODE -ne 0) { throw 'Не удалось создать переносимый архив.' }
|
|
} finally { Pop-Location }
|
|
# Do not globally exclude bin: the runtime's bin directory contains the CAD
|
|
# executables. The launcher development bin is filtered by exact archive paths.
|
|
& 'C:\Program Files\7-Zip\7z.exe' t $archive -bsp0 -bso0
|
|
if ($LASTEXITCODE -ne 0) { throw 'Проверка целостности переносимого архива завершилась с ошибкой.' }
|
|
Get-FileHash -LiteralPath $archive -Algorithm SHA256 |
|
|
Select-Object @{Name='Алгоритм';Expression={$_.Algorithm}},
|
|
@{Name='Контрольная сумма';Expression={$_.Hash}},
|
|
@{Name='Файл';Expression={$_.Path}} | Format-List
|
|
Write-Host "Переносимый выпуск: $archive"
|