From 61f6d1c1a3c1c7731fe41ed3d9c60b3ecce67601 Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:32:52 -0600 Subject: [PATCH 1/6] ci: build on the shared ci-workflows Windows workflow Locked restore, warnings-as-errors build, dotnet format, core and CLI tests with the 100% coverage gate, the template pack/instantiate smoke test and the PowerShell analyzer/Pester checks run on the KOF Windows host runner; the review-gate scripts lint and test on node.yaml. Pins SDK 10.0.403 (the runner's SDK) and refreshes the lock files for its ILLink 10.0.14 reference. Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 63 ++++++++++++++++++++++++++++ global.json | 2 +- src/Kof22App.Cli/packages.lock.json | 6 +-- src/Kof22App.Core/packages.lock.json | 6 +-- 4 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 .gitea/workflows/build.yaml diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..1bf7b48 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,63 @@ +name: build +on: + push: + branches: ['**'] + tags: ['v*'] +jobs: + windows: + uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@native-workflows + secrets: inherit + with: + commands: | + dotnet restore Kof22App.slnx -p:Platform=x64 --locked-mode + dotnet build Kof22App.slnx -p:Platform=x64 -warnaserror --no-restore + # The WinUI app project is built directly so the format workspace can load its generated XAML code. + dotnet build src/Kof22App/Kof22App.csproj -p:Platform=x64 -warnaserror --no-restore + $env:Platform = 'x64' + dotnet format Kof22App.slnx --verify-no-changes --severity warn --no-restore + Remove-Item Env:Platform + dotnet test tests/Kof22App.Core.Tests --no-build --settings coverage.runsettings --collect:"XPlat Code Coverage" --logger trx --results-directory TestResults + dotnet test tests/Kof22App.Cli.Tests --no-build --settings coverage.runsettings --collect:"XPlat Code Coverage" --logger trx --results-directory TestResults + ./build/Assert-Coverage.ps1 -ResultsDirectory TestResults -Packages Kof22App.Core,kof22-app + # Template: pack, install into a private hive, instantiate with and without the CLI, then build, format, test and gate coverage. + $temp = $env:RUNNER_TEMP ?? [IO.Path]::GetTempPath() + $hive = Join-Path $temp "template-hive-$env:GITHUB_RUN_ID" + dotnet pack templates/KofTwentyTwo.Templates.WindowsApp.csproj -c Release -p:Version=0.1.0 -p:RestoreLockedMode=true -o artifacts/template + dotnet new install artifacts/template/KofTwentyTwo.Templates.WindowsApp.0.1.0.nupkg --debug:custom-hive $hive + foreach ($cli in 'true', 'false') { + $directory = "artifacts/template-probe-$cli" + $name = if ($cli -eq 'true') { 'TemplateProbe.WithCli' } else { 'TemplateProbe.NoCli' } + dotnet new k22-winapp -n $name --appId "probe-$cli" --displayName "Probe $cli" --cli $cli -o $directory --debug:custom-hive $hive + dotnet restore "$directory/$name.slnx" -p:Platform=x64 --locked-mode + dotnet build "$directory/$name.slnx" -p:Platform=x64 -warnaserror --no-restore + dotnet format "$directory/$name.slnx" --verify-no-changes --severity warn --no-restore + dotnet test "$directory/tests/$name.Core.Tests" --no-build --settings "$directory/coverage.runsettings" --collect:'XPlat Code Coverage' --results-directory "$directory/TestResults" + if ($cli -eq 'true') { + dotnet test "$directory/tests/$name.Cli.Tests" --no-build --settings "$directory/coverage.runsettings" --collect:'XPlat Code Coverage' --results-directory "$directory/TestResults" + } + & "$directory/build/Assert-Coverage.ps1" -ResultsDirectory "$directory/TestResults" + } + # PowerShell build scripts: analyzer and Pester boundary tests with pinned modules saved to the job's temp directory. + $modules = Join-Path $temp "psmodules-$env:GITHUB_RUN_ID" + Save-PSResource -Name PSScriptAnalyzer -Version 1.25.0 -Repository PSGallery -TrustRepository -Path $modules + Save-PSResource -Name Pester -Version 5.7.1 -Repository PSGallery -TrustRepository -Path $modules + Import-Module (Join-Path $modules PSScriptAnalyzer/1.25.0/PSScriptAnalyzer.psd1) + Import-Module (Join-Path $modules Pester/5.7.1/Pester.psd1) + foreach ($file in Get-ChildItem -LiteralPath build -Recurse -File | Where-Object Extension -In '.ps1', '.psm1', '.psd1') { + # One file at a time: recursive analysis can crash inside 1.25.0. + $findings = @(Invoke-ScriptAnalyzer -Path $file.FullName -Settings ./PSScriptAnalyzerSettings.psd1) + if ($findings.Count -gt 0) { $findings | Format-Table; throw "Script analysis failed: $($file.Name)" } + } + $pester = New-PesterConfiguration + $pester.Run.Path = @('build/Assert-Coverage.Tests.ps1', 'build/GitHubRepository.Tests.ps1', 'build/Distribution.Tests.ps1', 'build/InstalledUpdates.Tests.ps1', 'build/PackageBytes.Tests.ps1', 'build/ReleaseSigning.Tests.ps1') + $pester.Run.PassThru = $true + if ((Invoke-Pester -Configuration $pester).Result -ne 'Passed') { throw 'Pester tests failed' } + scripts: + uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/node.yaml@v1 + with: + node-version: '24' + install: npm ci --ignore-scripts + commands: | + npm run lint + npm test + npm audit signatures diff --git a/global.json b/global.json index 163a6e1..d9997a0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.401", + "version": "10.0.403", "rollForward": "latestFeature" } } diff --git a/src/Kof22App.Cli/packages.lock.json b/src/Kof22App.Cli/packages.lock.json index 0cbd674..bfed54d 100644 --- a/src/Kof22App.Cli/packages.lock.json +++ b/src/Kof22App.Cli/packages.lock.json @@ -10,9 +10,9 @@ }, "Microsoft.NET.ILLink.Tasks": { "type": "Direct", - "requested": "[10.0.12, )", - "resolved": "10.0.12", - "contentHash": "xi+BDjFpW+Sb+MHFHaH6Y/gV9I8BluFwRXc1QyCdoZbIK26eNiBeFuMTe/FMwc33G1wdHCyDg7CVTmb8OdQrMQ==" + "requested": "[10.0.14, )", + "resolved": "10.0.14", + "contentHash": "YlTamXppEQls6DYWt7RdUuwWDb0lyw/vXCaGeQpLCpsLmfwGuCkOz/vIGgMTV7ECsJcavkCOkxZXv9s8rdAHkQ==" }, "kof22app.core": { "type": "Project", diff --git a/src/Kof22App.Core/packages.lock.json b/src/Kof22App.Core/packages.lock.json index 94f96e2..c706ce4 100644 --- a/src/Kof22App.Core/packages.lock.json +++ b/src/Kof22App.Core/packages.lock.json @@ -22,9 +22,9 @@ }, "Microsoft.NET.ILLink.Tasks": { "type": "Direct", - "requested": "[10.0.12, )", - "resolved": "10.0.12", - "contentHash": "xi+BDjFpW+Sb+MHFHaH6Y/gV9I8BluFwRXc1QyCdoZbIK26eNiBeFuMTe/FMwc33G1wdHCyDg7CVTmb8OdQrMQ==" + "requested": "[10.0.14, )", + "resolved": "10.0.14", + "contentHash": "YlTamXppEQls6DYWt7RdUuwWDb0lyw/vXCaGeQpLCpsLmfwGuCkOz/vIGgMTV7ECsJcavkCOkxZXv9s8rdAHkQ==" } }, "net10.0/win-arm64": {}, -- 2.54.0 From 49147f6c2830f4c2075dbd63a3a6c81c075bfbd1 Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:35:32 -0600 Subject: [PATCH 2/6] ci: run the coverage gate as a separate pwsh process Assert-Coverage.ps1 reports a shortfall with exit 1, which only stops the build when the script runs as a native process. Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 1bf7b48..0a71835 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -18,7 +18,7 @@ jobs: Remove-Item Env:Platform dotnet test tests/Kof22App.Core.Tests --no-build --settings coverage.runsettings --collect:"XPlat Code Coverage" --logger trx --results-directory TestResults dotnet test tests/Kof22App.Cli.Tests --no-build --settings coverage.runsettings --collect:"XPlat Code Coverage" --logger trx --results-directory TestResults - ./build/Assert-Coverage.ps1 -ResultsDirectory TestResults -Packages Kof22App.Core,kof22-app + pwsh -NoProfile -File ./build/Assert-Coverage.ps1 -ResultsDirectory TestResults -Packages Kof22App.Core,kof22-app # Template: pack, install into a private hive, instantiate with and without the CLI, then build, format, test and gate coverage. $temp = $env:RUNNER_TEMP ?? [IO.Path]::GetTempPath() $hive = Join-Path $temp "template-hive-$env:GITHUB_RUN_ID" @@ -35,7 +35,7 @@ jobs: if ($cli -eq 'true') { dotnet test "$directory/tests/$name.Cli.Tests" --no-build --settings "$directory/coverage.runsettings" --collect:'XPlat Code Coverage' --results-directory "$directory/TestResults" } - & "$directory/build/Assert-Coverage.ps1" -ResultsDirectory "$directory/TestResults" + pwsh -NoProfile -File "$directory/build/Assert-Coverage.ps1" -ResultsDirectory "$directory/TestResults" } # PowerShell build scripts: analyzer and Pester boundary tests with pinned modules saved to the job's temp directory. $modules = Join-Path $temp "psmodules-$env:GITHUB_RUN_ID" -- 2.54.0 From f9cad0128d68b3115b10b27da16ebcf5264ff38b Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:38:25 -0600 Subject: [PATCH 3/6] ci: create the module directory before saving the pinned modules Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 0a71835..62fd3a6 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -39,6 +39,7 @@ jobs: } # PowerShell build scripts: analyzer and Pester boundary tests with pinned modules saved to the job's temp directory. $modules = Join-Path $temp "psmodules-$env:GITHUB_RUN_ID" + New-Item -ItemType Directory -Force -Path $modules | Out-Null Save-PSResource -Name PSScriptAnalyzer -Version 1.25.0 -Repository PSGallery -TrustRepository -Path $modules Save-PSResource -Name Pester -Version 5.7.1 -Repository PSGallery -TrustRepository -Path $modules Import-Module (Join-Path $modules PSScriptAnalyzer/1.25.0/PSScriptAnalyzer.psd1) -- 2.54.0 From fe1883d4a410eb9cc82f373a3f149047f6dd5ecf Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:42:17 -0600 Subject: [PATCH 4/6] ci: let the Pester suites see child exit codes They assert on failing child processes themselves; the shared workflow's native-exit-code preference turned those expected failures into errors. Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 62fd3a6..9168f38 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -49,6 +49,8 @@ jobs: $findings = @(Invoke-ScriptAnalyzer -Path $file.FullName -Settings ./PSScriptAnalyzerSettings.psd1) if ($findings.Count -gt 0) { $findings | Format-Table; throw "Script analysis failed: $($file.Name)" } } + # The Pester suites assert on child processes' exit codes themselves. + $PSNativeCommandUseErrorActionPreference = $false $pester = New-PesterConfiguration $pester.Run.Path = @('build/Assert-Coverage.Tests.ps1', 'build/GitHubRepository.Tests.ps1', 'build/Distribution.Tests.ps1', 'build/InstalledUpdates.Tests.ps1', 'build/PackageBytes.Tests.ps1', 'build/ReleaseSigning.Tests.ps1') $pester.Run.PassThru = $true -- 2.54.0 From b4a2734d9e93f8302943d596774fc1f20ca0cfb2 Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:47:22 -0600 Subject: [PATCH 5/6] ci: call the shared workflow from ci-workflows main Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 9168f38..d2a3e31 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -5,7 +5,7 @@ on: tags: ['v*'] jobs: windows: - uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@native-workflows + uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@main secrets: inherit with: commands: | -- 2.54.0 From 579dac6df8f1a4bdc496d94ea2e4769e9f6cdfaf Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 8 Nov 2026 07:51:25 -0600 Subject: [PATCH 6/6] ci: pin the shared workflow to v1 Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index d2a3e31..aaab9d8 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -5,7 +5,7 @@ on: tags: ['v*'] jobs: windows: - uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@main + uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@v1 secrets: inherit with: commands: | -- 2.54.0