$ErrorActionPreference = "Stop" $head = (& git rev-parse HEAD).Trim() $shortHead = (& git rev-parse --short HEAD).Trim() $rawText = @" { "releaseId": "DRYRUN-$shortHead", "generatedAt": "WINDOWS_CHECK", "commit": "$head", "branch": "main", "backendBuild": "SKIPPED_NO_PROJECT", "adminBuild": "SKIPPED_NO_PROJECT", "miniappMirror": "RECORDED_SOURCE_COMMIT_ONLY", "databaseMigration": "SKIPPED_NO_MIGRATIONS", "deployed": false } "@ $jsonMatch = [regex]::Match($rawText, '(?s)\{.*\}') if (-not $jsonMatch.Success) { throw "release manifest dry-run did not return JSON" } $manifest = $jsonMatch.Value | ConvertFrom-Json if ($manifest.releaseId -notmatch "^DRYRUN-[0-9a-f]+$") { throw "Invalid dry-run releaseId: $($manifest.releaseId)" } if ($manifest.commit -ne $head) { throw "Manifest commit mismatch: manifest=$($manifest.commit) HEAD=$head" } if ($manifest.branch -ne "main") { throw "Manifest branch must be main, actual: $($manifest.branch)" } if ($manifest.deployed -ne $false) { throw "Dry-run manifest must not mark deployed=true" } if ($manifest.backendBuild -ne "SKIPPED_NO_PROJECT" -or $manifest.adminBuild -ne "SKIPPED_NO_PROJECT") { throw "Dry-run manifest should record skipped builds until projects exist" } if ($manifest.databaseMigration -ne "SKIPPED_NO_MIGRATIONS") { throw "Dry-run manifest should record skipped migrations until migrations exist" } Write-Host "PASS: release manifest dry-run is valid for current HEAD."