Files
panopainter/scripts/automation/package-smoke.ps1

414 lines
19 KiB
PowerShell

[CmdletBinding()]
param(
[string]$Preset = "windows-msvc-default",
[string]$Configuration = "Debug",
[string]$Target = "PanoPainter",
[string]$CMakeCommand = "cmake",
[switch]$ReadinessOnly,
[switch]$AndroidNativeChecks,
[string[]]$PackageKinds = @(
"windows-appx",
"android-standard-apk",
"android-quest-apk",
"android-focus-apk",
"apple-bundle",
"linux-app",
"webgl"
)
)
$ErrorActionPreference = "Stop"
$started = Get-Date
$root = (Get-Location).Path
function Test-CommandAvailable {
param([string]$Name)
return [bool](Get-Command $Name -ErrorAction SilentlyContinue)
}
function Expand-ArgumentList {
param([string[]]$Values)
$expanded = @()
foreach ($value in $Values) {
foreach ($part in ($value -split ",")) {
$trimmed = $part.Trim()
if ($trimmed.Length -gt 0) {
$expanded += $trimmed
}
}
}
return $expanded
}
function New-ArtifactCheck {
param(
[string]$Name,
[string]$Path,
[string]$PathType = "Any"
)
$exists = if ($PathType -eq "Container") {
Test-Path -LiteralPath $Path -PathType Container
} elseif ($PathType -eq "Leaf") {
Test-Path -LiteralPath $Path -PathType Leaf
} else {
Test-Path -LiteralPath $Path
}
[ordered]@{
name = $Name
path = $Path
pathType = $PathType
exists = $exists
}
}
function New-Prerequisite {
param(
[string]$Name,
[bool]$Available,
[string]$Detail
)
[ordered]@{
name = $Name
available = $Available
detail = $Detail
}
}
function New-PackageReadiness {
param(
[string]$Kind,
[string]$Status,
[string]$Reason,
[object[]]$Prerequisites,
[object[]]$Artifacts,
[string]$ValidationCommand
)
[ordered]@{
kind = $Kind
status = $Status
reason = $Reason
debt = "DEBT-0011"
validationCommand = $ValidationCommand
prerequisites = $Prerequisites
artifacts = $Artifacts
}
}
function Get-AndroidNativeCheckPlan {
param([string[]]$Kinds)
$packages = @()
if ($Kinds -contains "android-standard-apk") {
$packages += [ordered]@{
packages = @("standard")
configureOnly = $false
}
}
$configureOnlyPackages = @()
if ($Kinds -contains "android-quest-apk") {
$configureOnlyPackages += "quest"
}
if ($Kinds -contains "android-focus-apk") {
$configureOnlyPackages += "focus"
}
if ($configureOnlyPackages.Count -gt 0) {
$packages += [ordered]@{
packages = $configureOnlyPackages
configureOnly = $true
}
}
return $packages
}
function Invoke-AndroidNativePackageChecks {
param([string[]]$Kinds)
$plans = @(Get-AndroidNativeCheckPlan -Kinds $Kinds)
$results = @()
$overallExitCode = 0
foreach ($plan in $plans) {
$arguments = @(
"-ExecutionPolicy", "Bypass",
"-File", (Join-Path $root "scripts/automation/android-legacy-package-build.ps1"),
"-Packages", ($plan.packages -join ",")
)
if ($plan.configureOnly) {
$arguments += "-ConfigureOnly"
}
$output = @(& powershell @arguments 2>&1)
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $exitCode
}
$jsonLine = @($output | ForEach-Object { $_.ToString() } | Where-Object { $_.TrimStart().StartsWith("{") } | Select-Object -Last 1)
$summary = $null
if ($jsonLine.Count -gt 0) {
try {
$summary = $jsonLine[-1] | ConvertFrom-Json
} catch {
$summary = $null
}
}
$results += [ordered]@{
packages = $plan.packages
configureOnly = [bool]$plan.configureOnly
exitCode = $exitCode
command = "powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages $($plan.packages -join ',')$(if ($plan.configureOnly) { ' -ConfigureOnly' } else { '' })"
summary = $summary
}
}
[ordered]@{
requested = $plans.Count -gt 0
exitCode = $overallExitCode
results = $results
}
}
$PackageKinds = @(Expand-ArgumentList -Values $PackageKinds)
function Get-PackageReadiness {
param([string[]]$Kinds)
$readiness = @()
foreach ($kind in $Kinds) {
switch ($kind) {
"windows-appx" {
$wapproj = Join-Path $root "PanoPainterPackage/PanoPainterPackage.wapproj"
$manifest = Join-Path $root "PanoPainterPackage/Package.appxmanifest"
$appPackages = Join-Path $root "PanoPainterPackage/AppPackages"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "legacy-wapproj-present-but-root-cmake-package-target-missing" `
-ValidationCommand "msbuild PanoPainterPackage/PanoPainterPackage.wapproj /p:Configuration=$Configuration /p:Platform=x64" `
-Prerequisites @(
(New-Prerequisite -Name "legacy-wapproj" -Available (Test-Path -LiteralPath $wapproj -PathType Leaf) -Detail $wapproj),
(New-Prerequisite -Name "appx-manifest" -Available (Test-Path -LiteralPath $manifest -PathType Leaf) -Detail $manifest),
(New-Prerequisite -Name "makeappx" -Available (Test-CommandAvailable "makeappx") -Detail "Windows SDK packaging tool"),
(New-Prerequisite -Name "signtool" -Available (Test-CommandAvailable "signtool") -Detail "Windows SDK signing tool"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "app-packages" -Path $appPackages -PathType "Container")
)
}
"android-standard-apk" {
$gradle = Join-Path $root "android/android/build.gradle"
$manifest = Join-Path $root "android/android/src/main/AndroidManifest.xml"
$apkDir = Join-Path $root "android/android/build/outputs/apk"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "legacy-gradle-package-not-consuming-root-cmake-targets" `
-ValidationCommand "gradle -p android/android assembleDebug" `
-Prerequisites @(
(New-Prerequisite -Name "gradle-build" -Available (Test-Path -LiteralPath $gradle -PathType Leaf) -Detail $gradle),
(New-Prerequisite -Name "android-manifest" -Available (Test-Path -LiteralPath $manifest -PathType Leaf) -Detail $manifest),
(New-Prerequisite -Name "gradle" -Available (Test-CommandAvailable "gradle") -Detail "Android package builder"),
(New-Prerequisite -Name "retained-native-cmake-check" -Available $true -Detail "powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "android-arm64/android-x64"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "apk-output" -Path $apkDir -PathType "Container")
)
}
"android-quest-apk" {
$gradle = Join-Path $root "android/quest/build.gradle"
$manifest = Join-Path $root "android/quest/src/main/AndroidManifest.xml"
$apkDir = Join-Path $root "android/quest/build/outputs/apk"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "legacy-gradle-package-not-consuming-root-cmake-targets" `
-ValidationCommand "gradle -p android/quest assembleDebug" `
-Prerequisites @(
(New-Prerequisite -Name "gradle-build" -Available (Test-Path -LiteralPath $gradle -PathType Leaf) -Detail $gradle),
(New-Prerequisite -Name "android-manifest" -Available (Test-Path -LiteralPath $manifest -PathType Leaf) -Detail $manifest),
(New-Prerequisite -Name "gradle" -Available (Test-CommandAvailable "gradle") -Detail "Android package builder"),
(New-Prerequisite -Name "retained-native-cmake-check" -Available $true -Detail "powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages quest -ConfigureOnly"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "android-quest-arm64"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "apk-output" -Path $apkDir -PathType "Container")
)
}
"android-focus-apk" {
$gradle = Join-Path $root "android/focus/build.gradle"
$manifest = Join-Path $root "android/focus/src/main/AndroidManifest.xml"
$apkDir = Join-Path $root "android/focus/build/outputs/apk"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "legacy-gradle-package-not-consuming-root-cmake-targets" `
-ValidationCommand "gradle -p android/focus assembleDebug" `
-Prerequisites @(
(New-Prerequisite -Name "gradle-build" -Available (Test-Path -LiteralPath $gradle -PathType Leaf) -Detail $gradle),
(New-Prerequisite -Name "android-manifest" -Available (Test-Path -LiteralPath $manifest -PathType Leaf) -Detail $manifest),
(New-Prerequisite -Name "gradle" -Available (Test-CommandAvailable "gradle") -Detail "Android package builder"),
(New-Prerequisite -Name "retained-native-cmake-check" -Available $true -Detail "powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages focus -ConfigureOnly"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "android-focus-arm64"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "apk-output" -Path $apkDir -PathType "Container")
)
}
"apple-bundle" {
$xcodeProject = Join-Path $root "PanoPainter.xcodeproj/project.pbxproj"
$bundleDir = Join-Path $root "out/package/apple"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "legacy-xcode-project-and-host-toolchain-not-aligned-with-root-cmake-package-target" `
-ValidationCommand "xcodebuild -project PanoPainter.xcodeproj -configuration $Configuration" `
-Prerequisites @(
(New-Prerequisite -Name "legacy-xcode-project" -Available (Test-Path -LiteralPath $xcodeProject -PathType Leaf) -Detail $xcodeProject),
(New-Prerequisite -Name "xcodebuild" -Available (Test-CommandAvailable "xcodebuild") -Detail "Apple package builder"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "macos/ios-device/ios-simulator"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "apple-package-output" -Path $bundleDir -PathType "Container")
)
}
"linux-app" {
$linuxCmake = Join-Path $root "linux/CMakeLists.txt"
$linuxBinary = Join-Path $root "out/package/linux/panopainter"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "retained-linux-cmake-not-consuming-root-cmake-targets" `
-ValidationCommand "cmake -S linux -B out/package/linux-retained && cmake --build out/package/linux-retained --target panopainter" `
-Prerequisites @(
(New-Prerequisite -Name "retained-linux-cmake" -Available (Test-Path -LiteralPath $linuxCmake -PathType Leaf) -Detail $linuxCmake),
(New-Prerequisite -Name "cmake" -Available (Test-CommandAvailable "cmake") -Detail "Linux retained app CMake configure/build tool"),
(New-Prerequisite -Name "retained-platform-cmake-baseline" -Available $true -Detail "python scripts/dev/check_retained_platform_cmake.py"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "linux-clang"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "linux-app-output" -Path $linuxBinary -PathType "Leaf")
)
}
"webgl" {
$webglCmake = Join-Path $root "webgl/CMakeLists.txt"
$webDir = Join-Path $root "out/package/webgl"
$readiness += New-PackageReadiness `
-Kind $kind `
-Status "blocked" `
-Reason "retained-webgl-cmake-not-consuming-root-cmake-targets" `
-ValidationCommand "emcmake cmake -S webgl -B out/package/webgl-retained && cmake --build out/package/webgl-retained --target panopainter" `
-Prerequisites @(
(New-Prerequisite -Name "retained-webgl-cmake" -Available (Test-Path -LiteralPath $webglCmake -PathType Leaf) -Detail $webglCmake),
(New-Prerequisite -Name "emcc" -Available (Test-CommandAvailable "emcc") -Detail "Emscripten compiler"),
(New-Prerequisite -Name "emcmake" -Available (Test-CommandAvailable "emcmake") -Detail "Emscripten CMake wrapper"),
(New-Prerequisite -Name "retained-platform-cmake-baseline" -Available $true -Detail "python scripts/dev/check_retained_platform_cmake.py"),
(New-Prerequisite -Name "root-cmake-preset" -Available $true -Detail "emscripten"),
(New-Prerequisite -Name "root-cmake-package-target" -Available $false -Detail "Not migrated yet")
) `
-Artifacts @(
(New-ArtifactCheck -Name "webgl-output" -Path $webDir -PathType "Container")
)
}
}
}
return $readiness
}
$androidNativeValidation = if ($AndroidNativeChecks) {
Invoke-AndroidNativePackageChecks -Kinds $PackageKinds
} else {
[ordered]@{
requested = $false
exitCode = 0
results = @()
}
}
if ($ReadinessOnly) {
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "package-smoke"
preset = $Preset
configuration = $Configuration
target = $Target
stage = "readiness"
exitCode = 0
elapsedMs = $elapsed
androidNativeValidation = $androidNativeValidation
packageReadiness = @(Get-PackageReadiness -Kinds $PackageKinds)
} | ConvertTo-Json -Compress -Depth 8
exit $androidNativeValidation.exitCode
}
& $CMakeCommand --build --preset $Preset --config $Configuration --target $Target
$buildExitCode = $LASTEXITCODE
if ($buildExitCode -ne 0) {
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "package-smoke"
preset = $Preset
configuration = $Configuration
target = $Target
stage = "build"
cmakeCommand = $CMakeCommand
exitCode = $buildExitCode
elapsedMs = $elapsed
androidNativeValidation = $androidNativeValidation
packageReadiness = @(Get-PackageReadiness -Kinds $PackageKinds)
} | ConvertTo-Json -Compress -Depth 8
exit $buildExitCode
}
$binaryDir = Join-Path (Join-Path (Join-Path (Get-Location) "out/build/$Preset") $Configuration) "$Target.exe"
$targetDir = Split-Path -Parent $binaryDir
$dataDir = Join-Path $targetDir "data"
$curlDll = if ($Configuration -eq "Debug") { "libcurl_debug.dll" } else { "libcurl.dll" }
$checks = @(
[ordered]@{ name = "executable"; path = $binaryDir; exists = Test-Path -LiteralPath $binaryDir -PathType Leaf },
[ordered]@{ name = "data"; path = $dataDir; exists = Test-Path -LiteralPath $dataDir -PathType Container },
[ordered]@{ name = "BugTrapU-x64.dll"; path = (Join-Path $targetDir "BugTrapU-x64.dll"); exists = Test-Path -LiteralPath (Join-Path $targetDir "BugTrapU-x64.dll") -PathType Leaf },
[ordered]@{ name = $curlDll; path = (Join-Path $targetDir $curlDll); exists = Test-Path -LiteralPath (Join-Path $targetDir $curlDll) -PathType Leaf },
[ordered]@{ name = "libyuv.dll"; path = (Join-Path $targetDir "libyuv.dll"); exists = Test-Path -LiteralPath (Join-Path $targetDir "libyuv.dll") -PathType Leaf },
[ordered]@{ name = "libmp4v2.dll"; path = (Join-Path $targetDir "libmp4v2.dll"); exists = Test-Path -LiteralPath (Join-Path $targetDir "libmp4v2.dll") -PathType Leaf },
[ordered]@{ name = "openh264-2.0.0-win64.dll"; path = (Join-Path $targetDir "openh264-2.0.0-win64.dll"); exists = Test-Path -LiteralPath (Join-Path $targetDir "openh264-2.0.0-win64.dll") -PathType Leaf },
[ordered]@{ name = "openvr_api.dll"; path = (Join-Path $targetDir "openvr_api.dll"); exists = Test-Path -LiteralPath (Join-Path $targetDir "openvr_api.dll") -PathType Leaf }
)
$failed = @($checks | Where-Object { -not $_.exists })
$exitCode = if ($failed.Count -eq 0) { 0 } else { 2 }
if ($androidNativeValidation.exitCode -ne 0 -and $exitCode -eq 0) {
$exitCode = $androidNativeValidation.exitCode
}
$elapsedMs = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "package-smoke"
preset = $Preset
configuration = $Configuration
target = $Target
cmakeCommand = $CMakeCommand
exitCode = $exitCode
elapsedMs = $elapsedMs
checks = $checks
androidNativeValidation = $androidNativeValidation
packageReadiness = @(Get-PackageReadiness -Kinds $PackageKinds)
} | ConvertTo-Json -Compress -Depth 8
exit $exitCode