param( [Parameter(Mandatory = $true)][string]$Project, [string]$Cli = (Join-Path $PSScriptRoot '..\target\debug\package-builder.exe'), [switch]$Export, [switch]$SignDevelopment ) $ErrorActionPreference = 'Stop' $projectPath = (Resolve-Path -LiteralPath $Project).Path $cliPath = (Resolve-Path -LiteralPath $Cli).Path $sampleRoot = Split-Path -Parent $projectPath $reports = Join-Path $sampleRoot 'reports' if (-not (Test-Path -LiteralPath $reports)) { New-Item -ItemType Directory -Path $reports | Out-Null } $utf8 = New-Object System.Text.UTF8Encoding($false) function Invoke-BuilderJson([string[]]$BuilderArguments, [string]$ReportPath) { $result = & $cliPath @BuilderArguments $code = $LASTEXITCODE $json = $result -join "`n" [System.IO.File]::WriteAllText($ReportPath, $json, $utf8) if ($code -ne 0) { throw "package-builder failed ($code); report: $ReportPath" } return ($json | ConvertFrom-Json) } # Use the existing Rust engine for planning, packaging, unpack verification and export. # Packaging stays in the Rust engine. Optional signing is a separate post-build step. $plan = Invoke-BuilderJson -BuilderArguments @('plan','release','--project',$projectPath,'--target','msix-direct') -ReportPath (Join-Path $reports 'plan.json') Write-Output "Plan: $($plan.id); files: $($plan.files.Count)" $mappingPath = Join-Path $reports 'file-mapping.json' if (Test-Path -LiteralPath $mappingPath) { $expected = Get-Content -LiteralPath $mappingPath -Raw -Encoding UTF8 | ConvertFrom-Json $actualTargets = @{} foreach ($file in $plan.files) { $actualTargets[$file.target] = $file } foreach ($file in $expected) { if (-not $actualTargets.ContainsKey($file.target)) { throw "ISM target missing from actual plan: $($file.target)" } $actual = $actualTargets[$file.target] # Compare normalized source paths too; filename matching alone is insufficient. $actualSource = $actual.source -replace '^\\\\\?\\', '' if ($actualSource -ine $file.preparedSource -or [uint64]$actual.bytes -ne [uint64]$file.bytes -or $actual.sha256 -ne $file.sha256) { throw "ISM source/size mismatch: $($file.ismFileId)" } } if ($plan.files.Count -ne ($expected.Count + 2)) { throw 'Unexpected payload count; expected ISM files plus two logo assets.' } } $result = Invoke-BuilderJson -BuilderArguments @('build','--project',$projectPath,'--plan-id',$plan.id) -ReportPath (Join-Path $reports 'build-result.json') Write-Output "Build: $($result.status); signing: $($result.signing)" Write-Output "Artifact: $($result.artifact)" if ($SignDevelopment) { & (Join-Path $PSScriptRoot 'Sign-DevelopmentMsix.ps1') ` -Release (Join-Path $sampleRoot ("releases\" + $result.buildId + '\release.json')) ` -Output (Join-Path $sampleRoot ('signed-development-' + $result.buildId)) } if ($Export) { $exportRoot = Join-Path $sampleRoot ('export-' + $plan.id) $exportedPath = Invoke-BuilderJson -BuilderArguments @('export','--project',$projectPath,'--release',$plan.id,'--output',$exportRoot) -ReportPath (Join-Path $reports 'export-result.json') Write-Output "Export: $exportedPath" }