79 lines
5.2 KiB
PowerShell
79 lines
5.2 KiB
PowerShell
param(
|
|
[Parameter(Mandatory)][ValidateSet('EditMode','PlayMode','AndroidBuild','AndroidSmoke')][string]$Phase,
|
|
[ValidateSet('FirstSlice','Composition','Persistence','Content','Final')][string]$Milestone = 'Final'
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
$projectRoot = Split-Path $PSScriptRoot -Parent
|
|
Set-Location -LiteralPath $projectRoot
|
|
$evidenceDir = Join-Path $projectRoot "artifacts/verification/$Milestone"
|
|
New-Item -ItemType Directory -Path $evidenceDir -Force | Out-Null
|
|
$phaseName = $Phase.ToLowerInvariant()
|
|
$logPath = Join-Path $evidenceDir "$phaseName.log"
|
|
$record = [ordered]@{
|
|
phase = $Phase; milestone = $Milestone; startedUtc = [DateTime]::UtcNow.ToString('o')
|
|
sourceCommit = (& git rev-parse HEAD); sourceDirty = [bool](& git status --porcelain)
|
|
command = $null; exitCode = $null; status = 'not-run'; log = $logPath
|
|
}
|
|
try {
|
|
$record.editor = (Get-Content 'ProjectSettings/ProjectVersion.txt' | Select-String '^m_EditorVersion:').ToString().Split(':',2)[1].Trim()
|
|
$record.packages = (Get-Content 'Packages/manifest.json' -Raw | ConvertFrom-Json).dependencies
|
|
$apkPath = Join-Path $projectRoot "artifacts/android/$Milestone/MagnetismHeroes.apk"
|
|
if ($Phase -in @('EditMode','PlayMode')) {
|
|
$xmlPath = Join-Path $evidenceDir "$phaseName.xml"
|
|
if (Test-Path -LiteralPath $xmlPath) { Remove-Item -LiteralPath $xmlPath }
|
|
$cliArgs = @('test', $projectRoot, '--mode', $Phase, '--output', $xmlPath, '--timeout', '900', '--', '-logFile', $logPath)
|
|
$record.command = 'unity ' + (($cliArgs | ForEach-Object { '"' + $_ + '"' }) -join ' ')
|
|
& unity @cliArgs
|
|
$record.exitCode = $LASTEXITCODE
|
|
if (!(Test-Path -LiteralPath $xmlPath)) { throw "Unity $Phase exited $($record.exitCode) without a test report. See $logPath" }
|
|
[xml]$report = Get-Content -LiteralPath $xmlPath -Raw
|
|
$cases = @($report.SelectNodes('//test-case'))
|
|
$record.total = $cases.Count
|
|
$record.passed = @($cases | Where-Object { $_.result -eq 'Passed' }).Count
|
|
$record.failed = @($cases | Where-Object { $_.result -eq 'Failed' }).Count
|
|
$record.notPassed = $record.total - $record.passed
|
|
if ($record.exitCode -ne 0) { throw "Unity $Phase exited $($record.exitCode). See $logPath" }
|
|
if ($record.total -eq 0 -or $record.notPassed -ne 0) { throw "Test report contains $($record.total) tests and $($record.notPassed) non-passing cases." }
|
|
} elseif ($Phase -eq 'AndroidBuild') {
|
|
New-Item -ItemType Directory -Path (Split-Path $apkPath -Parent) -Force | Out-Null
|
|
if (Test-Path -LiteralPath $apkPath) { Remove-Item -LiteralPath $apkPath }
|
|
$env:MAGNETISM_APK_PATH = $apkPath
|
|
$cliArgs = @('run', $projectRoot, '--timeout', '1800', '--log-file', $logPath, '--no-tail', '--', '-buildTarget', 'Android', '-executeMethod', 'MagnetismHeroes.Editor.ProjectBootstrap.BuildAndroid')
|
|
$record.command = 'unity ' + (($cliArgs | ForEach-Object { '"' + $_ + '"' }) -join ' ')
|
|
& unity @cliArgs
|
|
$record.exitCode = $LASTEXITCODE
|
|
if ($LASTEXITCODE -ne 0 -or !(Test-Path -LiteralPath $apkPath)) { throw 'Android build failed or produced no APK.' }
|
|
$record.apk = $apkPath
|
|
$record.apkSha256 = (Get-FileHash -LiteralPath $apkPath -Algorithm SHA256).Hash
|
|
& (Join-Path $PSScriptRoot 'android/inspect-apk.ps1') -ApkPath $apkPath -EvidenceDir $evidenceDir -SourceCommit $record.sourceCommit -SourceDirty $record.sourceDirty -MetadataName 'apk-metadata.json'
|
|
$record.apkMetadata = Join-Path $evidenceDir 'apk-metadata.json'
|
|
$record.sourceCommitEnd = (& git rev-parse HEAD)
|
|
& git update-index --refresh | Out-Null
|
|
$record.sourceDirtyEnd = [bool](& git status --porcelain)
|
|
$record.trackedDiffEnd = @(& git diff --name-only HEAD)
|
|
if ($record.sourceDirty -or $record.sourceDirtyEnd -or $record.sourceCommitEnd -ne $record.sourceCommit) { throw 'Source changed during the Android build or is dirty.' }
|
|
if ($Milestone -eq 'Final') {
|
|
Copy-Item -LiteralPath $apkPath -Destination (Join-Path $projectRoot 'artifacts/android/MagnetismHeroes.apk')
|
|
}
|
|
} else {
|
|
$smokeScript = Join-Path $PSScriptRoot 'android/smoke.ps1'
|
|
if (!(Test-Path -LiteralPath $smokeScript)) { throw 'Android smoke verification has not been implemented yet.' }
|
|
$record.command = "pwsh -NoProfile -File tools/android/smoke.ps1 -ApkPath $apkPath -Milestone $Milestone -EvidenceDir $evidenceDir"
|
|
& pwsh -NoProfile -File $smokeScript -ApkPath $apkPath -Milestone $Milestone -EvidenceDir $evidenceDir *> $logPath
|
|
$record.exitCode = $LASTEXITCODE
|
|
Get-Content -LiteralPath $logPath | Select-Object -Last 5 | Write-Host
|
|
if ($LASTEXITCODE -ne 0) { throw "Android smoke verification exited $LASTEXITCODE." }
|
|
}
|
|
$record.status = 'passed'
|
|
} catch {
|
|
$record.status = 'failed'
|
|
$record.error = $_.Exception.Message
|
|
Write-Host $record.error -ForegroundColor Red
|
|
} finally {
|
|
$record.finishedUtc = [DateTime]::UtcNow.ToString('o')
|
|
$record | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $evidenceDir "$phaseName-evidence.json") -Encoding utf8
|
|
}
|
|
if ($record.status -ne 'passed') { exit 1 }
|
|
Write-Host "$Phase / $Milestone passed. Evidence: $evidenceDir"
|
|
exit 0
|