param( [string]$Configuration = "Release" ) $ErrorActionPreference = "Stop" $repoRoot = Split-Path -Parent $PSScriptRoot $projectPath = Join-Path $repoRoot "src\AttackTracerNinjaCli\AttackTracerNinjaCli.csproj" $installerRoot = Join-Path $repoRoot "installer" $artifactsRoot = Join-Path $repoRoot "artifacts" $publishRoot = Join-Path $artifactsRoot "publish\win-x64" $packageRoot = Join-Path $artifactsRoot "installer-payload" $bootstrapperProject = Join-Path $repoRoot "installer\AttackTracerNinjaBootstrapper\AttackTracerNinjaBootstrapper.csproj" $bootstrapperPayload = Join-Path $repoRoot "installer\AttackTracerNinjaBootstrapper\payload.zip" $bootstrapperPublish = Join-Path $artifactsRoot "bootstrapper\win-x64" $outputExe = Join-Path $artifactsRoot "AttackTracerNinjaSetup.exe" function Get-ShortPath([string]$path) { $resolved = [System.IO.Path]::GetFullPath($path) $cmdPath = $resolved.Replace('"', '""') $shortPath = cmd /c "for %I in (""$cmdPath"") do @echo %~sI" return ($shortPath | Select-Object -Last 1).Trim() } [xml]$projectXml = Get-Content $projectPath $version = $projectXml.Project.PropertyGroup.Version | Select-Object -First 1 if ([string]::IsNullOrWhiteSpace($version)) { $version = "1.2.2" } Write-Host "Publishing AttackTracerNinja version $version" if (Test-Path $publishRoot) { Remove-Item -LiteralPath $publishRoot -Recurse -Force } if (Test-Path $packageRoot) { Remove-Item -LiteralPath $packageRoot -Recurse -Force } if (Test-Path $bootstrapperPublish) { Remove-Item -LiteralPath $bootstrapperPublish -Recurse -Force } if (Test-Path $bootstrapperPayload) { Remove-Item -LiteralPath $bootstrapperPayload -Force } if (Test-Path $outputExe) { Remove-Item -LiteralPath $outputExe -Force } New-Item -ItemType Directory -Force -Path $publishRoot, $packageRoot, $bootstrapperPublish | Out-Null & dotnet restore $projectPath -r win-x64 if ($LASTEXITCODE -ne 0) { throw "dotnet restore failed" } & dotnet publish $projectPath ` -c $Configuration ` -r win-x64 ` --self-contained true ` -p:PublishSingleFile=true ` -p:IncludeNativeLibrariesForSelfExtract=true ` -o $publishRoot if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed" } Copy-Item -Path (Join-Path $publishRoot "AttackTracerNinjaCli.exe") -Destination (Join-Path $packageRoot "AttackTracerNinjaCli.exe") -Force if (Test-Path (Join-Path $publishRoot "AttackTracerNinjaCli.pdb")) { Copy-Item -Path (Join-Path $publishRoot "AttackTracerNinjaCli.pdb") -Destination (Join-Path $packageRoot "AttackTracerNinjaCli.pdb") -Force } Copy-Item -Path (Join-Path $repoRoot "config\attacktracer-settings.example.json") -Destination (Join-Path $packageRoot "attacktracer-settings.example.json") -Force Copy-Item -Path (Join-Path $repoRoot "config\attacktracer-client.example.json") -Destination (Join-Path $packageRoot "attacktracer-client.example.json") -Force Copy-Item -Path (Join-Path $repoRoot "config\update-channel.example.json") -Destination (Join-Path $packageRoot "update-channel.example.json") -Force Copy-Item -Path (Join-Path $repoRoot "samples\ninja-vulnerability-export.example.csv") -Destination (Join-Path $packageRoot "ninja-vulnerability-export.example.csv") -Force Copy-Item -Path (Join-Path $installerRoot "install-attacktracer-ninja.ps1") -Destination (Join-Path $packageRoot "install-attacktracer-ninja.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "launch-install.cmd") -Destination (Join-Path $packageRoot "launch-install.cmd") -Force Copy-Item -Path (Join-Path $installerRoot "uninstall-attacktracer-ninja.ps1") -Destination (Join-Path $packageRoot "uninstall-attacktracer-ninja.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "runtime-run-attacktracer-ninja.ps1") -Destination (Join-Path $packageRoot "run-attacktracer-ninja.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "runtime-run-attacktracer-ninja-monitor.ps1") -Destination (Join-Path $packageRoot "run-attacktracer-ninja-monitor.ps1") -Force Copy-Item -Path (Join-Path $repoRoot "scripts\protect-attacktracer-secret.ps1") -Destination (Join-Path $packageRoot "protect-attacktracer-secret.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "update-attacktracer-ninja.ps1") -Destination (Join-Path $packageRoot "update-attacktracer-ninja.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "runtime-build-attacktracer-org-report.ps1") -Destination (Join-Path $packageRoot "build-attacktracer-org-report.ps1") -Force Copy-Item -Path (Join-Path $installerRoot "README.txt") -Destination (Join-Path $packageRoot "README.txt") -Force Set-Content -Path (Join-Path $packageRoot "VERSION.txt") -Value $version -NoNewline Write-Host "Creating embedded payload zip" Compress-Archive -Path (Join-Path $packageRoot "*") -DestinationPath $bootstrapperPayload -CompressionLevel Optimal -Force Write-Host "Publishing bootstrapper installer" & dotnet restore $bootstrapperProject -r win-x64 if ($LASTEXITCODE -ne 0) { throw "Bootstrapper restore failed" } & dotnet publish $bootstrapperProject ` -c $Configuration ` -r win-x64 ` --self-contained true ` -p:PublishSingleFile=true ` -p:IncludeNativeLibrariesForSelfExtract=true ` -o $bootstrapperPublish if ($LASTEXITCODE -ne 0) { throw "Bootstrapper publish failed" } Copy-Item -Path (Join-Path $bootstrapperPublish "AttackTracerNinjaBootstrapper.exe") -Destination $outputExe -Force Write-Host "Installer created at $outputExe"