Repository navigation
Adopt Rapid membership and native Orleans serialization #211
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Tests | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| mode: | |
| description: 'Select full qualification or sequential functional database gates' | |
| type: choice | |
| default: all | |
| options: [all, functional-gates] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: keyload-build-tests-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| repository-checks: | |
| name: Check repository rules | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Download source code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Check repository rules | |
| run: node scripts/Features/RepositoryGovernance/verify.mjs | |
| analyzer-rules: | |
| name: Test code analyzers | |
| if: ${{ github.event_name != 'workflow_dispatch' || inputs.mode == 'all' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Download source code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Restore .NET packages | |
| run: dotnet restore KeyLoad.slnx | |
| - name: Build analyzer tests | |
| run: | | |
| dotnet build build/KeyLoad.AppHost --no-restore -warnaserror | |
| dotnet build tests/KeyLoad.Analyzers.Tests --no-restore -warnaserror | |
| - name: Prepare source-bound analyzer coverage | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'artifacts/code-quality/analyzer-coverage' | |
| New-Item -ItemType Directory -Path $evidence -Force | Out-Null | |
| Copy-Item scripts/Features/CodeQuality/site-analyzer-coverage.settings.xml (Join-Path $evidence 'coverage.config.xml') | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/site-analyzer-coverage.ps1 ` | |
| -Mode Prepare -Repository $root ` | |
| -Contract (Join-Path $root 'scripts/Features/CodeQuality/site-analyzer-coverage.contract.json') ` | |
| -EvidenceRoot $evidence | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Run analyzer tests | |
| id: analyzers | |
| run: | | |
| node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=analyzers --KeyLoadTests:ResultsDirectory=TestResults/analyzers --KeyLoadTests:ReportTrx=true "--KeyLoadTests:CoverageSettings=$GITHUB_WORKSPACE/artifacts/code-quality/analyzer-coverage/coverage.config.xml" "--KeyLoadTests:CoverageOutput=$GITHUB_WORKSPACE/artifacts/code-quality/analyzer-coverage/coverage.cobertura.xml" | |
| - name: Verify every analyzer test passed | |
| if: ${{ !cancelled() && steps.analyzers.outcome != 'skipped' }} | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $files = @(Get-ChildItem -LiteralPath (Join-Path $root 'TestResults/analyzers') -Filter '*.trx' -File) | |
| if ($files.Count -ne 1) { throw 'Expected exactly one analyzer TRX receipt' } | |
| [xml]$document = Get-Content -LiteralPath $files[0].FullName -Raw | |
| $counts = $document.TestRun.ResultSummary.Counters | |
| if ([int]$counts.total -le 0 -or [int]$counts.executed -ne [int]$counts.total -or | |
| [int]$counts.passed -ne [int]$counts.total) { | |
| throw 'Incomplete or failing analyzer qualification; skipped tests cannot pass' | |
| } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA | |
| total = [int]$counts.total | |
| executed = [int]$counts.executed | |
| passed = [int]$counts.passed | |
| sha256 = (Get-FileHash -LiteralPath $files[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $root 'artifacts/code-quality/analyzer-coverage/test-receipt.json') -Encoding utf8NoBOM | |
| - name: Verify source-bound analyzer coverage | |
| if: ${{ !cancelled() && steps.analyzers.outcome != 'skipped' }} | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'artifacts/code-quality/analyzer-coverage' | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/site-analyzer-coverage.ps1 ` | |
| -Mode Verify -Repository $root ` | |
| -Contract (Join-Path $root 'scripts/Features/CodeQuality/site-analyzer-coverage.contract.json') ` | |
| -EvidenceRoot $evidence -CoverageReport (Join-Path $evidence 'coverage.cobertura.xml') | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Save analyzer test results | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: analyzer-rule-evidence | |
| path: | | |
| TestResults/** | |
| tests/KeyLoad.Analyzers.Tests/**/TestResults/** | |
| artifacts/code-quality/** | |
| if-no-files-found: error | |
| verify: | |
| name: Build and test KeyLoad | |
| if: ${{ github.event_name != 'workflow_dispatch' || inputs.mode == 'all' }} | |
| needs: repository-checks | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-24.04] | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Download source code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Restore .NET packages | |
| run: dotnet restore KeyLoad.slnx | |
| - name: Build KeyLoad | |
| id: build | |
| run: dotnet build KeyLoad.slnx --no-restore -warnaserror | |
| - name: Prepare execution source and execution test assembly identity receipts | |
| id: execution-source-identity | |
| if: ${{ !cancelled() && steps.build.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'TestResults/execution-source-identity' | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.production-source-manifest.ps1 ` | |
| -Mode prepare -Root $root -EvidenceRoot $evidence | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Verify the pinned execution full-text package | |
| run: | | |
| node --input-type=module <<'JS' | |
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import crypto from 'node:crypto'; | |
| import { execFileSync, spawnSync } from 'node:child_process'; | |
| const cache = execFileSync('dotnet', ['nuget', 'locals', 'global-packages', '--list'], { encoding: 'utf8' }).trim(); | |
| const prefix = 'global-packages: '; | |
| if (!cache.startsWith(prefix) || cache.includes('\n')) throw new Error('Ambiguous NuGet package cache.'); | |
| const packagePath = path.join(cache.slice(prefix.length), 'zonetree.fulltextsearch', '1.0.9', 'zonetree.fulltextsearch.1.0.9.nupkg'); | |
| const digest = crypto.createHash('sha256').update(fs.readFileSync(packagePath)).digest('hex'); | |
| if (digest !== '7ea1fbb7aba0ad00391d78d2f414166b500335f5b1affe43c305d861b55719ff') throw new Error('Execution FTS package differs from ADR-078.'); | |
| const verification = spawnSync('dotnet', ['nuget', 'verify', packagePath, '--all'], { encoding: 'utf8', maxBuffer: 1048576 }); | |
| fs.mkdirSync('artifacts/qualification', { recursive: true }); | |
| fs.writeFileSync('artifacts/qualification/execution-full-text-package-signature.log', `Package SHA256: ${digest}\n${verification.stdout ?? ''}${verification.stderr ?? ''}`); | |
| process.stdout.write(verification.stdout ?? ''); | |
| process.stderr.write(verification.stderr ?? ''); | |
| if (verification.error || verification.status !== 0) throw verification.error ?? new Error('Execution FTS package signature verification failed.'); | |
| JS | |
| - name: Build current Debug analyzer for execution formatting | |
| run: dotnet build analyzers/KeyLoad.Analyzers/KeyLoad.Analyzers.csproj --no-restore --configuration Debug -warnaserror | |
| - name: Check code formatting | |
| run: dotnet format KeyLoad.slnx --verify-no-changes --no-restore | |
| - name: Check repository rules | |
| run: node scripts/Features/RepositoryGovernance/verify.mjs | |
| - name: Test execution coverage source ownership | |
| id: source-ownership | |
| run: node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/(PathMapCompilerTests)|(ProductionSourceManifestSettlementTests)|(SourceManifestChildSettlementTests)|(ProductionSourceManifestOperationTests)/*' --KeyLoadTests:ResultsDirectory=TestResults/execution-source-ownership --KeyLoadTests:ReportTrx=true | |
| - name: Verify original source ownership test receipt | |
| if: ${{ !cancelled() && steps.source-ownership.outcome != 'skipped' }} | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $reports = @(Get-ChildItem TestResults/execution-source-ownership -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1) { throw 'Exactly one original source ownership TRX is required.' } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $counters = $trx.TestRun.ResultSummary.Counters | |
| if ([int] $counters.total -ne 10 -or [int] $counters.executed -ne 10 -or | |
| [int] $counters.passed -ne 10 -or [int] $counters.failed -ne 0) { | |
| throw 'Every execution source ownership case must execute and pass.' | |
| } | |
| $receipt = [ordered]@{ | |
| source = $env:GITHUB_SHA; total = 10; executed = 10; passed = 10 | |
| originalTrxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| } | |
| $receipt | ConvertTo-Json | Set-Content TestResults/execution-source-ownership/test-receipt.json | |
| - name: Run unit tests | |
| if: ${{ !cancelled() && steps.build.outcome == 'success' }} | |
| run: node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=unit --KeyLoadTests:ReportTrx=true | |
| - name: Test recovery after process crashes | |
| if: ${{ !cancelled() && steps.build.outcome == 'success' }} | |
| run: node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=recovery --KeyLoadTests:ReportTrx=true | |
| - name: Verify execution source and execution test assembly identity receipts | |
| if: ${{ !cancelled() && steps.build.outcome == 'success' && steps.execution-source-identity.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'TestResults/execution-source-identity' | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.production-source-manifest.ps1 ` | |
| -Mode verify -Root $root -EvidenceRoot $evidence | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Save test results | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: test-results-${{ matrix.os }} | |
| path: | | |
| **/TestResults/** | |
| artifacts/qualification/** | |
| if-no-files-found: ignore | |
| - name: Save build diagnostics | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: code-quality-${{ matrix.os }} | |
| path: artifacts/code-quality/** | |
| if-no-files-found: error | |
| aspire-cluster: | |
| name: ${{ inputs.mode == 'functional-gates' && 'Test functional database gates (one then three nodes)' || 'Test three-node database' }} | |
| if: ${{ github.event_name != 'workflow_dispatch' || inputs.mode == 'all' || inputs.mode == 'functional-gates' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 180 | |
| steps: | |
| - name: Download source code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up .NET | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| global-json-file: global.json | |
| - name: Find Chrome for admin tests | |
| shell: bash | |
| run: | | |
| admin_chrome=$(command -v google-chrome || command -v google-chrome-stable || command -v chromium || command -v chromium-browser) | |
| test -n "$admin_chrome" && test -x "$admin_chrome" | |
| "$admin_chrome" --version | |
| printf 'KEYLOAD_ADMIN_CHROME_PATH=%s\n' "$admin_chrome" >> "$GITHUB_ENV" | |
| - name: Restore .NET packages | |
| run: dotnet restore KeyLoad.slnx | |
| - name: Build the complete execution coverage cohort | |
| run: dotnet build KeyLoad.slnx --no-restore -warnaserror | |
| - name: Prepare original source and execution test assembly receipts | |
| id: coverage-source | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'TestResults/functional-coverage/cluster' | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.production-source-manifest.ps1 ` | |
| -Mode prepare -Root $root -EvidenceRoot $evidence | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| "KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST=$evidence/functional-coverage.production-source-manifest.json" | Add-Content $env:GITHUB_ENV | |
| - name: Test functional database gate with 1 node(s) | |
| id: functional-single | |
| if: ${{ github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' }} | |
| shell: bash | |
| env: | |
| TMPDIR: ${{ runner.temp }}/functional-gates | |
| run: | | |
| evidence="TestResults/functional-gates/single" | |
| mkdir -p "$TMPDIR" "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster '--KeyLoadTests:Filter=/*/*/FunctionalDatabaseGateTests/SingleInstanceRunsEveryModelThroughSdkMcpAndSqlWithPersistedUsers' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/single --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original single functional gate receipt | |
| id: functional-single-receipt | |
| if: ${{ !cancelled() && inputs.mode == 'functional-gates' && (steps.functional-single.outcome == 'success' || steps.functional-single.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-single.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/single' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original functional gate TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 1 -and $definitions.Count -eq 1 | |
| $valid = $valid -and [int]$counts.total -eq 1 -and [int]$counts.executed -eq 1 -and [int]$counts.passed -eq 1 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $method = 'SingleInstanceRunsEveryModelThroughSdkMcpAndSqlWithPersistedUsers' | |
| $valid = $valid -and $results[0].outcome -ceq 'Passed' -and $results[0].testName -ceq $method -and | |
| $results[0].testId -ceq $definitions[0].id -and $definitions[0].TestMethod.name -ceq $method -and | |
| $definitions[0].TestMethod.className -ceq 'KeyLoad.IntegrationTests.Features.DatabaseComposition.FunctionalDatabaseGateTests' | |
| $processEvidence = & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE -ResultsDirectory $directory ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | ConvertFrom-Json | |
| if ($LASTEXITCODE -ne 0) { throw 'Original execution process lifecycle verification failed.' } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| method = $method; nodes = 1; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| processEvidence = $processEvidence | |
| } | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'The exact original functional case must execute once and pass without skips.' } | |
| - name: Test functional database gate with 3 node(s) | |
| id: functional-three | |
| if: ${{ success() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-single-receipt.outcome == 'success' }} | |
| shell: bash | |
| env: | |
| TMPDIR: ${{ runner.temp }}/functional-gates | |
| run: | | |
| evidence="TestResults/functional-gates/three" | |
| mkdir -p "$TMPDIR" "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster '--KeyLoadTests:Filter=/*/*/FunctionalDatabaseGateTests/ThreeNodeClusterRunsSameEveryModelScenarioThroughSdkMcpAndSql' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/three --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original three functional gate receipt | |
| id: functional-three-receipt | |
| if: ${{ !cancelled() && inputs.mode == 'functional-gates' && (steps.functional-three.outcome == 'success' || steps.functional-three.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-three.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/three' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original functional gate TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 1 -and $definitions.Count -eq 1 | |
| $valid = $valid -and [int]$counts.total -eq 1 -and [int]$counts.executed -eq 1 -and [int]$counts.passed -eq 1 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $method = 'ThreeNodeClusterRunsSameEveryModelScenarioThroughSdkMcpAndSql' | |
| $valid = $valid -and $results[0].outcome -ceq 'Passed' -and $results[0].testName -ceq $method -and | |
| $results[0].testId -ceq $definitions[0].id -and $definitions[0].TestMethod.name -ceq $method -and | |
| $definitions[0].TestMethod.className -ceq 'KeyLoad.IntegrationTests.Features.DatabaseComposition.FunctionalDatabaseGateTests' | |
| $processEvidence = & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE -ResultsDirectory $directory ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | ConvertFrom-Json | |
| if ($LASTEXITCODE -ne 0) { throw 'Original execution process lifecycle verification failed.' } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| method = $method; nodes = 3; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| processEvidence = $processEvidence | |
| } | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'The exact original functional case must execute once and pass without skips.' } | |
| - name: Test execution cold profile and selector preconditions | |
| id: functional-cold-preconditions | |
| if: ${{ success() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-three-receipt.outcome == 'success' }} | |
| shell: bash | |
| run: | | |
| evidence="TestResults/functional-gates/cold-preconditions" | |
| mkdir -p "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/(FunctionalColdReopenProfileTests|TUnitSelectionTests)/*' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/cold-preconditions --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original execution cold precondition receipt | |
| id: functional-cold-preconditions-receipt | |
| if: ${{ !cancelled() && inputs.mode == 'functional-gates' && (steps.functional-cold-preconditions.outcome == 'success' || steps.functional-cold-preconditions.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-cold-preconditions.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/cold-preconditions' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original cold precondition TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 10 -and $definitions.Count -eq 10 | |
| $valid = $valid -and [int]$counts.total -eq 10 -and [int]$counts.executed -eq 10 -and [int]$counts.passed -eq 10 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $expected = [ordered]@{ | |
| 'FunctionalColdReopenProfileTests.ActualModelKeepsFaultCommandsExclusiveToSelectedProfiles' = 5 | |
| 'FunctionalColdReopenProfileTests.InvalidColdAndConflictingSelectionsRefuseBeforeResourcesThenHealthyModelWorks' = 1 | |
| 'TUnitSelectionTests.EntryPreservesOriginalTUnitArgumentsAndRejectsInvalidSelections' = 4 | |
| } | |
| $observed = [Collections.Generic.Dictionary[string,int]]::new([StringComparer]::Ordinal) | |
| $resultIds = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) | |
| $definitionIds = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) | |
| $displays = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) | |
| foreach ($definition in $definitions) { | |
| if (-not $definitionIds.Add([string]$definition.id)) { $valid = $false } | |
| $class = [string]$definition.TestMethod.className | |
| $method = [string]$definition.TestMethod.name | |
| $prefix = 'KeyLoad.UnitTests.Features.TestInfrastructure.' | |
| if (-not $class.StartsWith($prefix, [StringComparison]::Ordinal)) { $valid = $false; continue } | |
| $key = $class.Substring($prefix.Length) + '.' + $method | |
| if ($key -cnotin @($expected.Keys)) { $valid = $false; continue } | |
| if (-not $observed.ContainsKey($key)) { $observed[$key] = 0 } | |
| $observed[$key]++ | |
| $matching = @($results | Where-Object { $_.testId -ceq $definition.id }) | |
| if ($matching.Count -ne 1) { $valid = $false; continue } | |
| $result = $matching[0] | |
| if ($result.outcome -cne 'Passed' -or $result.testName -cne $definition.name -or | |
| -not $resultIds.Add([string]$result.testId) -or -not $displays.Add($key + ':' + $result.testName)) { $valid = $false } | |
| } | |
| foreach ($key in $expected.Keys) { | |
| if (-not $observed.ContainsKey($key) -or $observed[$key] -ne $expected[$key]) { $valid = $false } | |
| } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| methods = $expected; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'Every original cold profile and selector precondition must execute exactly once and pass without skips.' } | |
| - name: Test cold functional database gate with 1 node(s) | |
| id: functional-cold-single | |
| if: ${{ success() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-cold-preconditions-receipt.outcome == 'success' }} | |
| shell: bash | |
| env: | |
| TMPDIR: ${{ runner.temp }}/functional-gates | |
| run: | | |
| evidence="TestResults/functional-gates/cold-single" | |
| mkdir -p "$TMPDIR" "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster '--KeyLoadTests:Filter=/*/*/FunctionalDatabaseColdReopenTests/SingleInstanceColdReopensAllModelsAndReplaysOriginalPublicCommands' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/cold-single --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original single cold functional gate receipt | |
| id: functional-cold-single-receipt | |
| if: ${{ !cancelled() && inputs.mode == 'functional-gates' && (steps.functional-cold-single.outcome == 'success' || steps.functional-cold-single.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-cold-single.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/cold-single' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original functional gate TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 1 -and $definitions.Count -eq 1 | |
| $valid = $valid -and [int]$counts.total -eq 1 -and [int]$counts.executed -eq 1 -and [int]$counts.passed -eq 1 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $method = 'SingleInstanceColdReopensAllModelsAndReplaysOriginalPublicCommands' | |
| $valid = $valid -and $results[0].outcome -ceq 'Passed' -and $results[0].testName -ceq $method -and | |
| $results[0].testId -ceq $definitions[0].id -and $definitions[0].TestMethod.name -ceq $method -and | |
| $definitions[0].TestMethod.className -ceq 'KeyLoad.IntegrationTests.Features.DatabaseComposition.FunctionalDatabaseColdReopenTests' | |
| $processEvidence = & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE -ResultsDirectory $directory ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | ConvertFrom-Json | |
| if ($LASTEXITCODE -ne 0) { throw 'Original execution process lifecycle verification failed.' } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| method = $method; nodes = 1; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| processEvidence = $processEvidence | |
| } | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'The exact original functional case must execute once and pass without skips.' } | |
| - name: Test cold functional database gate with 3 node(s) | |
| id: functional-cold-three | |
| if: ${{ success() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-cold-single-receipt.outcome == 'success' }} | |
| shell: bash | |
| env: | |
| TMPDIR: ${{ runner.temp }}/functional-gates | |
| run: | | |
| evidence="TestResults/functional-gates/cold-three" | |
| mkdir -p "$TMPDIR" "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster '--KeyLoadTests:Filter=/*/*/FunctionalDatabaseColdReopenTests/ThreeNodeColdReopensAllModelsAndReplaysOriginalPublicCommands' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/cold-three --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original three cold functional gate receipt | |
| id: functional-cold-three-receipt | |
| if: ${{ !cancelled() && inputs.mode == 'functional-gates' && (steps.functional-cold-three.outcome == 'success' || steps.functional-cold-three.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-cold-three.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/cold-three' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original functional gate TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 1 -and $definitions.Count -eq 1 | |
| $valid = $valid -and [int]$counts.total -eq 1 -and [int]$counts.executed -eq 1 -and [int]$counts.passed -eq 1 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $method = 'ThreeNodeColdReopensAllModelsAndReplaysOriginalPublicCommands' | |
| $valid = $valid -and $results[0].outcome -ceq 'Passed' -and $results[0].testName -ceq $method -and | |
| $results[0].testId -ceq $definitions[0].id -and $definitions[0].TestMethod.name -ceq $method -and | |
| $definitions[0].TestMethod.className -ceq 'KeyLoad.IntegrationTests.Features.DatabaseComposition.FunctionalDatabaseColdReopenTests' | |
| $processEvidence = & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE -ResultsDirectory $directory ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | ConvertFrom-Json | |
| if ($LASTEXITCODE -ne 0) { throw 'Original execution process lifecycle verification failed.' } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| method = $method; nodes = 3; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| processEvidence = $processEvidence | |
| } | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'The exact original functional case must execute once and pass without skips.' } | |
| - name: Test distinct execution files and exclusive-owner refusal with 3 nodes | |
| id: functional-file-ownership-three | |
| if: ${{ success() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-cold-three-receipt.outcome == 'success' }} | |
| shell: bash | |
| env: | |
| TMPDIR: ${{ runner.temp }}/functional-gates | |
| run: | | |
| evidence="TestResults/functional-gates/file-ownership-three" | |
| mkdir -p "$TMPDIR" "$evidence" | |
| if node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster '--KeyLoadTests:Filter=/*/*/FunctionalFileOwnershipClusterTests/DistinctFilesRetainAllModelsAcrossCompetingOwnersAndTwoColdReopens' --KeyLoadTests:Execution:MaximumParallelTests=50 --KeyLoadTests:ResultsDirectory=TestResults/functional-gates/file-ownership-three --KeyLoadTests:ReportTrx=true > "$evidence/execution.stdout.original.txt" 2> "$evidence/execution.stderr.original.txt"; then | |
| _exit=0 | |
| else | |
| _exit=$? | |
| fi | |
| printf '%s\n' "$_exit" > "$evidence/execution-exit-code.txt" | |
| tail -c 65536 "$evidence/execution.stdout.original.txt" | |
| tail -c 65536 "$evidence/execution.stderr.original.txt" >&2 | |
| exit "$_exit" | |
| - name: Verify original distinct-files and exclusive-owner refusal receipt | |
| id: functional-file-ownership-three-receipt | |
| if: ${{ !cancelled() && github.event_name == 'workflow_dispatch' && inputs.mode == 'functional-gates' && steps.functional-cold-three-receipt.outcome == 'success' && (steps.functional-file-ownership-three.outcome == 'success' || steps.functional-file-ownership-three.outcome == 'failure') }} | |
| shell: pwsh | |
| env: | |
| _OUTCOME: ${{ steps.functional-file-ownership-three.outcome }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates/file-ownership-three' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -Recurse -File) | |
| if ($reports.Count -ne 1 -or $reports[0].Length -le 0 -or $reports[0].Length -gt 16777216) { | |
| throw 'Exactly one bounded original functional gate TRX is required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $ns = [Xml.XmlNamespaceManager]::new($trx.NameTable) | |
| $ns.AddNamespace('t', 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010') | |
| $counts = $trx.SelectSingleNode('/t:TestRun/t:ResultSummary/t:Counters', $ns) | |
| $results = @($trx.SelectNodes('/t:TestRun/t:Results/t:UnitTestResult', $ns)) | |
| $definitions = @($trx.SelectNodes('/t:TestRun/t:TestDefinitions/t:UnitTest', $ns)) | |
| $runtimeExit = (Get-Content -LiteralPath (Join-Path $directory 'execution-exit-code.txt') -Raw).Trim() | |
| $valid = $env:_OUTCOME -ceq 'success' -and $runtimeExit -ceq '0' -and $null -ne $counts -and | |
| $results.Count -eq 1 -and $definitions.Count -eq 1 | |
| $valid = $valid -and [int]$counts.total -eq 1 -and [int]$counts.executed -eq 1 -and [int]$counts.passed -eq 1 | |
| foreach ($counter in $counts.Attributes) { | |
| if ($counter.Name -notin @('total','executed','passed') -and [long]$counter.Value -ne 0) { $valid = $false } | |
| } | |
| $method = 'DistinctFilesRetainAllModelsAcrossCompetingOwnersAndTwoColdReopens' | |
| $valid = $valid -and $results[0].outcome -ceq 'Passed' -and $results[0].testName -ceq $method -and | |
| $results[0].testId -ceq $definitions[0].id -and $definitions[0].TestMethod.name -ceq $method -and | |
| $definitions[0].TestMethod.className -ceq 'KeyLoad.IntegrationTests.Features.DatabaseComposition.FunctionalFileOwnershipClusterTests' | |
| $processEvidence = & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE -ResultsDirectory $directory ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | ConvertFrom-Json | |
| if ($LASTEXITCODE -ne 0) { throw 'Original execution process lifecycle verification failed.' } | |
| [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| method = $method; nodes = 3; maximumParallelTests = 50; runtimeOutcome = $env:_OUTCOME; runtimeExitCode = $runtimeExit; accepted = $valid | |
| stdoutSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stdout.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| stderrSha256 = (Get-FileHash -LiteralPath (Join-Path $directory 'execution.stderr.original.txt') -Algorithm SHA256).Hash.ToLowerInvariant() | |
| trxSha256 = (Get-FileHash -LiteralPath $reports[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant() | |
| sourceManifestSha256 = (Get-FileHash -LiteralPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST -Algorithm SHA256).Hash.ToLowerInvariant() | |
| processEvidence = $processEvidence | |
| } | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $directory 'functional-gate-receipt.json') -Encoding utf8NoBOM | |
| if (-not $valid) { throw 'The exact original functional case must execute once and pass without skips.' } | |
| - name: Test three-node database with .NET and MCP clients | |
| id: cluster-required | |
| if: ${{ inputs.mode != 'functional-gates' }} | |
| run: node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=cluster --KeyLoadTests:ResultsDirectory=TestResults/cluster-required --KeyLoadTests:ReportTrx=true | |
| - name: Check original three-node reports for diagnostic upload | |
| id: cluster-original-reports | |
| if: ${{ inputs.mode != 'functional-gates' && !cancelled() && (steps.cluster-required.outcome == 'success' || steps.cluster-required.outcome == 'failure') }} | |
| shell: bash | |
| run: | | |
| test -d TestResults/cluster-required | |
| original_trx=$(find TestResults/cluster-required -type f -name '*.trx' -size +0c -print -quit) | |
| test -n "$original_trx" | |
| printf '%s\n' "$original_trx" | |
| - name: Save original three-node diagnostics before covered suites | |
| if: ${{ inputs.mode != 'functional-gates' && !cancelled() && steps.cluster-original-reports.outcome == 'success' }} | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: aspire-cluster-original-diagnostics | |
| path: | | |
| TestResults/cluster-required/** | |
| TestResults/functional-coverage/cluster/** | |
| if-no-files-found: error | |
| - name: Reconcile original execution full and five-group discovery in both modes | |
| id: execution-census | |
| if: ${{ inputs.mode != 'functional-gates' && !cancelled() && steps.coverage-source.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.workflow-discovery.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE ` | |
| -EvidenceRoot (Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster') | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Execute full censuses and twelve original covered suite inputs | |
| id: functional-coverage | |
| if: ${{ inputs.mode != 'functional-gates' && !cancelled() && steps.execution-census.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.workflow-collect.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE ` | |
| -EvidenceRoot (Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster') ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Verify original coverage source and execution test assembly receipts after all children settle | |
| id: coverage-source-after | |
| if: ${{ !cancelled() && steps.coverage-source.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.production-source-manifest.ps1 ` | |
| -Mode verify -Root $env:GITHUB_WORKSPACE ` | |
| -EvidenceRoot (Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster') | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Assemble product descriptor from original reports | |
| id: product-descriptor | |
| if: ${{ inputs.mode != 'functional-gates' && success() }} | |
| shell: pwsh | |
| env: | |
| RECOVERY_EXIT_CODE: ${{ steps.functional-coverage.outputs.recovery_exit_code }} | |
| CLUSTER_EXIT_CODE: ${{ steps.functional-coverage.outputs.cluster_exit_code }} | |
| run: | | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.execution-product-descriptor.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST ` | |
| -ResultsRoot (Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster') ` | |
| -UnitRunStatusPath (Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster/functional-coverage.unit-run-status.v1.json') ` | |
| -RecoveryExitCode ([int]$env:RECOVERY_EXIT_CODE) -ClusterExitCode ([int]$env:CLUSTER_EXIT_CODE) | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Exercise original product admission and copied TRX denial with healthy re-admission | |
| id: product-admission | |
| if: ${{ inputs.mode != 'functional-gates' && success() }} | |
| env: | |
| KEYLOAD__PRODUCT_ADMISSION_REQUIRED: 'true' | |
| KEYLOAD__PRODUCT_DESCRIPTOR_PATH: ${{ github.workspace }}/TestResults/functional-coverage/cluster/functional-coverage.execution-product-descriptor.v1.json | |
| run: node scripts/Features/TestInfrastructure/run-tests.mjs --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/CoverageMergeTests/*' --KeyLoadTests:ResultsDirectory=TestResults/execution-product-admission --KeyLoadTests:ReportTrx=true | |
| - name: Verify original product-admission test and closed phase receipt | |
| if: ${{ inputs.mode != 'functional-gates' && !cancelled() && steps.product-admission.outcome != 'skipped' }} | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| Set-StrictMode -Version Latest | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/execution-product-admission' | |
| $reports = @(Get-ChildItem -LiteralPath $directory -Filter '*.trx' -File -Recurse) | |
| $receipts = @(Get-ChildItem -LiteralPath $directory -Filter 'execution-product-admission-phase.v1.json' -File -Recurse) | |
| if ($reports.Count -ne 1 -or $receipts.Count -ne 1 -or $receipts[0].Length -le 0 -or $receipts[0].Length -gt 65536) { | |
| throw 'Exactly one original TRX and bounded product-admission receipt are required.' | |
| } | |
| [xml] $trx = Get-Content -LiteralPath $reports[0].FullName -Raw | |
| $counts = $trx.TestRun.ResultSummary.Counters | |
| if ([int] $counts.total -ne 1 -or [int] $counts.executed -ne 1 -or [int] $counts.passed -ne 1 -or [int] $counts.failed -ne 0) { | |
| throw 'The real product-admission whole operation must execute and pass.' | |
| } | |
| . ./scripts/Features/CodeQuality/functional-coverage.execution-merge.inputs.ps1 | |
| $bytes = [IO.File]::ReadAllBytes($receipts[0].FullName) | |
| $document = [Text.Json.JsonDocument]::Parse([ReadOnlyMemory[byte]]::new($bytes)) | |
| try { Assert-FcJsonUnique $document.RootElement } | |
| finally { $document.Dispose() } | |
| $phase = ConvertFrom-Json ([Text.Encoding]::UTF8.GetString($bytes)) -AsHashtable | |
| Assert-FcExactKeys $phase @('schemaVersion','phase','descriptorSha256','healthyAdmissions','rejectedAdmissions','rejectedOutcome') | |
| $descriptor = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-coverage/cluster/functional-coverage.execution-product-descriptor.v1.json' | |
| foreach ($name in @('schemaVersion','healthyAdmissions','rejectedAdmissions')) { | |
| if ($phase[$name] -isnot [int] -and $phase[$name] -isnot [long]) { throw 'Invalid product phase integer.' } | |
| } | |
| if ($phase.schemaVersion -ne 1 -or $phase.phase -cne 'product-admission' -or | |
| $phase.descriptorSha256 -cne (Get-FileHash $descriptor -Algorithm SHA256).Hash.ToLowerInvariant() -or | |
| $phase.healthyAdmissions -ne 2 -or $phase.rejectedAdmissions -ne 1 -or | |
| $phase.rejectedOutcome -cne 'An original execution test outcome report does not match the exact contributor inventory.') { | |
| throw 'The product-admission phase does not bind the original descriptor and complete flow.' | |
| } | |
| - name: Validate and merge execution product coverage | |
| if: ${{ inputs.mode != 'functional-gates' && success() }} | |
| shell: pwsh | |
| run: | | |
| $root = $env:GITHUB_WORKSPACE | |
| $evidence = Join-Path $root 'TestResults/functional-coverage/cluster' | |
| $descriptorPath = Join-Path $evidence 'functional-coverage.execution-product-descriptor.v1.json' | |
| $boundsPath = Join-Path $evidence 'functional-coverage.execution-options.v1.json' | |
| $descriptor = Get-Content -LiteralPath $descriptorPath -Raw | ConvertFrom-Json | |
| $runtimeOptionsCore = Get-Content -LiteralPath $boundsPath -Raw | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.execution-merge.ps1 ` | |
| -Mode Product -Repository $root -EvidenceRoot $evidence -DescriptorPath $descriptorPath ` | |
| -ToolPackageRoot $descriptor.tool.packageRoot -ToolVersion $descriptor.tool.version ` | |
| -OptionsJson $runtimeOptionsCore | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Verify original execution process teardown evidence | |
| id: execution-cleanup | |
| if: ${{ always() && steps.coverage-source.outcome == 'success' }} | |
| shell: pwsh | |
| run: | | |
| & pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/functional-coverage.process-lifecycle.ps1 ` | |
| -Repository $env:GITHUB_WORKSPACE ` | |
| -ResultsDirectory (Join-Path $env:GITHUB_WORKSPACE 'TestResults') ` | |
| -SourceManifestPath $env:KEYLOAD_PRODUCT_COVERAGE_SOURCE_MANIFEST | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - name: Retain focused functional gate outcomes after cleanup | |
| if: ${{ always() && inputs.mode == 'functional-gates' }} | |
| shell: pwsh | |
| env: | |
| SINGLE_OUTCOME: ${{ steps.functional-single.outcome }} | |
| SINGLE_RECEIPT: ${{ steps.functional-single-receipt.outcome }} | |
| THREE_OUTCOME: ${{ steps.functional-three.outcome }} | |
| THREE_RECEIPT: ${{ steps.functional-three-receipt.outcome }} | |
| FILE_OWNERSHIP_OUTCOME: ${{ steps.functional-file-ownership-three.outcome }} | |
| FILE_OWNERSHIP_RECEIPT: ${{ steps.functional-file-ownership-three-receipt.outcome }} | |
| COLD_PRECONDITIONS_OUTCOME: ${{ steps.functional-cold-preconditions.outcome }} | |
| COLD_PRECONDITIONS_RECEIPT: ${{ steps.functional-cold-preconditions-receipt.outcome }} | |
| COLD_SINGLE_OUTCOME: ${{ steps.functional-cold-single.outcome }} | |
| COLD_SINGLE_RECEIPT: ${{ steps.functional-cold-single-receipt.outcome }} | |
| COLD_THREE_OUTCOME: ${{ steps.functional-cold-three.outcome }} | |
| COLD_THREE_RECEIPT: ${{ steps.functional-cold-three-receipt.outcome }} | |
| SOURCE_VERIFY: ${{ steps.coverage-source-after.outcome }} | |
| _CLEANUP: ${{ steps.execution-cleanup.outcome }} | |
| run: | | |
| $directory = Join-Path $env:GITHUB_WORKSPACE 'TestResults/functional-gates' | |
| New-Item -ItemType Directory -Path $directory -Force | Out-Null | |
| $outcomes = [ordered]@{ | |
| sourceRevision = $env:GITHUB_SHA; runId = $env:GITHUB_RUN_ID; runAttempt = $env:GITHUB_RUN_ATTEMPT | |
| single = $env:SINGLE_OUTCOME; singleReceipt = $env:SINGLE_RECEIPT | |
| three = $env:THREE_OUTCOME; threeReceipt = $env:THREE_RECEIPT | |
| fileOwnershipThree = $env:FILE_OWNERSHIP_OUTCOME; fileOwnershipThreeReceipt = $env:FILE_OWNERSHIP_RECEIPT | |
| coldPreconditions = $env:COLD_PRECONDITIONS_OUTCOME; coldPreconditionsReceipt = $env:COLD_PRECONDITIONS_RECEIPT | |
| coldSingle = $env:COLD_SINGLE_OUTCOME; coldSingleReceipt = $env:COLD_SINGLE_RECEIPT | |
| coldThree = $env:COLD_THREE_OUTCOME; coldThreeReceipt = $env:COLD_THREE_RECEIPT | |
| sourceVerify = $env:SOURCE_VERIFY; runtimeCleanup = $env:_CLEANUP | |
| } | |
| $outcomes | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $directory 'functional-gates-outcomes.json') -Encoding utf8NoBOM | |
| foreach ($name in @('single','singleReceipt','three','threeReceipt','fileOwnershipThree','fileOwnershipThreeReceipt','coldPreconditions','coldPreconditionsReceipt','coldSingle','coldSingleReceipt','coldThree','coldThreeReceipt','sourceVerify','runtimeCleanup')) { | |
| if ($outcomes[$name] -cne 'success') { throw 'Both original normal gates, execution file-ownership gate and receipt, cold preconditions, both cold gates and joined identity/cleanup checks must pass.' } | |
| } | |
| - name: Save three-node database test results | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: ${{ inputs.mode == 'functional-gates' && 'functional-gates-qualification' || 'aspire-cluster-qualification' }} | |
| path: | | |
| TestResults/** | |
| ${{ runner.temp }}/functional-gates/**/execution-resource-logs/** | |
| tests/KeyLoad.IntegrationTests/**/TestResults/** | |
| artifacts/qualification/** | |
| if-no-files-found: error | |
| - name: Save three-node build diagnostics | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: code-quality-aspire-cluster | |
| path: artifacts/code-quality/** | |
| if-no-files-found: error |