@@ -10,26 +10,53 @@ permissions:
1010 contents : write
1111
1212jobs :
13- build-and-release :
13+ build :
1414 runs-on : windows-latest
15+ outputs :
16+ version : ${{ steps.version.outputs.version }}
17+ tag : ${{ steps.version.outputs.tag }}
1518
1619 steps :
1720 - name : Checkout
1821 uses : actions/checkout@v4
22+ with :
23+ fetch-depth : 0
1924
2025 - name : Setup .NET
2126 uses : actions/setup-dotnet@v4
2227 with :
2328 dotnet-version : " 8.0.x"
2429
30+ - name : Resolve version
31+ id : version
32+ shell : pwsh
33+ run : |
34+ $refName = "${{ github.ref_name }}"
35+ if ($refName -match '^v\d+\.\d+\.\d+$') {
36+ $version = $refName.TrimStart('v')
37+ $tag = $refName
38+ }
39+ else {
40+ [xml]$project = Get-Content "ThreadPilot.csproj"
41+ $version = $project.Project.PropertyGroup.Version
42+ if ([string]::IsNullOrWhiteSpace($version)) {
43+ throw "Unable to resolve version from tag or ThreadPilot.csproj"
44+ }
45+
46+ $tag = "v$version"
47+ }
48+
49+ "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
50+ "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
51+
2552 - name : Restore
2653 run : dotnet restore "ThreadPilot_1.sln"
2754
2855 - name : Build
2956 run : dotnet build "ThreadPilot_1.sln" --configuration Release --no-restore
3057
3158 - name : Test
32- run : dotnet test "ThreadPilot_1.sln" --configuration Release --no-build
59+ run : dotnet test "ThreadPilot_1.sln" --configuration Release --no-build --collect:"XPlat Code Coverage" --results-directory TestResults
3360
3461 - name : Publish self-contained single-file
3562 run : dotnet publish "ThreadPilot.csproj" --configuration Release -p:PublishProfile=WinX64-SingleFile
5279 shell : pwsh
5380 run : |
5481 $ErrorActionPreference = "Stop"
55- $version = "${{ github.ref_name }}".TrimStart('v')
82+ $version = "${{ steps.version.outputs.version }}"
5683 $sourceDir = (Resolve-Path "artifacts/release/singlefile").Path
5784
5885 & iscc.exe "/DMyAppVersion=$version" "/DMyAppSourceDir=$sourceDir" "Installer/setup.iss"
@@ -118,7 +145,7 @@ jobs:
118145 shell : pwsh
119146 run : |
120147 $ErrorActionPreference = "Stop"
121- $version = "${{ github.ref_name }}"
148+ $version = "${{ steps.version.outputs.tag }}"
122149 New-Item -ItemType Directory -Force -Path "artifacts/release/packages" | Out-Null
123150 New-Item -ItemType Directory -Force -Path "artifacts/release/package-staging" | Out-Null
124151
@@ -206,15 +233,185 @@ jobs:
206233 "$($hash.Hash) $($_.Name)" | Out-File -FilePath $hashFile -Append -Encoding utf8
207234 }
208235
236+ - name : Update winget installer manifest
237+ shell : pwsh
238+ run : |
239+ $ErrorActionPreference = "Stop"
240+ $version = "${{ steps.version.outputs.version }}"
241+ $tag = "${{ steps.version.outputs.tag }}"
242+ $installer = Get-ChildItem "artifacts/release/installer/*.exe" -File | Select-Object -First 1
243+ if (-not $installer)
244+ {
245+ throw "Installer executable not found."
246+ }
247+
248+ $sha = (Get-FileHash $installer.FullName -Algorithm SHA256).Hash.ToUpperInvariant()
249+ $url = "https://github.com/${{ github.repository }}/releases/download/$tag/$($installer.Name)"
250+ $manifestPath = "winget/manifests/p/PrimeBuild/ThreadPilot/$version/PrimeBuild.ThreadPilot.installer.yaml"
251+
252+ if (-not (Test-Path $manifestPath))
253+ {
254+ throw "Winget installer manifest not found at $manifestPath"
255+ }
256+
257+ $content = Get-Content $manifestPath -Raw
258+ $content = $content.Replace("{{INSTALLER_URL}}", $url).Replace("{{INSTALLER_SHA256}}", $sha)
259+ Set-Content -Path $manifestPath -Value $content -Encoding utf8
260+
261+ - name : Generate SBOM
262+ shell : pwsh
263+ run : |
264+ $ErrorActionPreference = "Stop"
265+ dotnet tool install --global Microsoft.Sbom.DotNetTool
266+ $env:PATH += ";$env:USERPROFILE\.dotnet\tools"
267+ sbom-tool generate -b ./artifacts -bc . -pn ThreadPilot -pv "${{ steps.version.outputs.version }}" -ps PrimeBuild -nsb https://github.com/PrimeBuild-pc/ThreadPilot
268+
269+ - name : Upload portable artifact
270+ uses : actions/upload-artifact@v4
271+ with :
272+ name : release-portable
273+ path : artifacts/release/singlefile
274+
275+ - name : Upload installer artifact
276+ uses : actions/upload-artifact@v4
277+ with :
278+ name : release-installer
279+ path : artifacts/release/installer
280+
281+ - name : Upload packages artifact
282+ uses : actions/upload-artifact@v4
283+ with :
284+ name : release-packages
285+ path : artifacts/release/packages
286+
287+ - name : Upload msix artifact
288+ uses : actions/upload-artifact@v4
289+ with :
290+ name : release-msix
291+ path : artifacts/release/msix
292+
293+ - name : Upload checksums artifact
294+ uses : actions/upload-artifact@v4
295+ with :
296+ name : release-checksums
297+ path : artifacts/release/SHA256SUMS.txt
298+
299+ - name : Upload winget manifests
300+ uses : actions/upload-artifact@v4
301+ with :
302+ name : winget-manifests
303+ path : winget/manifests/p/PrimeBuild/ThreadPilot/${{ steps.version.outputs.version }}
304+
305+ - name : Upload SBOM
306+ uses : actions/upload-artifact@v4
307+ with :
308+ name : sbom
309+ path : _manifest/spdx_2.2/manifest.spdx.json
310+
311+ smoke-test :
312+ runs-on : windows-latest
313+ needs : build
314+
315+ steps :
316+ - uses : actions/download-artifact@v4
317+ with :
318+ name : release-portable
319+ path : smoke
320+
321+ - name : Smoke test
322+ shell : pwsh
323+ run : |
324+ $ErrorActionPreference = "Stop"
325+ $exe = Get-ChildItem "smoke" -Recurse -Filter "ThreadPilot.exe" -File | Select-Object -First 1
326+ if (-not $exe)
327+ {
328+ throw "ThreadPilot.exe not found in smoke-test artifact."
329+ }
330+
331+ $process = Start-Process -FilePath $exe.FullName -ArgumentList "--smoke-test" -Wait -PassThru
332+ if ($process.ExitCode -ne 0)
333+ {
334+ throw "Smoke test failed with exit code $($process.ExitCode)."
335+ }
336+
337+ release :
338+ runs-on : windows-latest
339+ needs :
340+ - build
341+ - smoke-test
342+
343+ steps :
344+ - name : Checkout
345+ uses : actions/checkout@v4
346+ with :
347+ fetch-depth : 0
348+
349+ - name : Download installer artifact
350+ uses : actions/download-artifact@v4
351+ with :
352+ name : release-installer
353+ path : release-assets/installer
354+
355+ - name : Download packages artifact
356+ uses : actions/download-artifact@v4
357+ with :
358+ name : release-packages
359+ path : release-assets/packages
360+
361+ - name : Download msix artifact
362+ uses : actions/download-artifact@v4
363+ with :
364+ name : release-msix
365+ path : release-assets/msix
366+
367+ - name : Download checksums artifact
368+ uses : actions/download-artifact@v4
369+ with :
370+ name : release-checksums
371+ path : release-assets
372+
373+ - name : Download winget manifests
374+ uses : actions/download-artifact@v4
375+ with :
376+ name : winget-manifests
377+ path : winget-manifests
378+
379+ - name : Download SBOM artifact
380+ uses : actions/download-artifact@v4
381+ with :
382+ name : sbom
383+ path : sbom
384+
385+ - name : Generate changelog
386+ id : git-cliff
387+ uses : orhun/git-cliff-action@v3
388+ with :
389+ config : cliff.toml
390+ args : --latest
391+
392+ - name : Contributors file check (manual maintenance mode)
393+ shell : pwsh
394+ run : |
395+ if (-not (Test-Path "CONTRIBUTORS.md")) {
396+ throw "CONTRIBUTORS.md not found."
397+ }
398+
399+ Write-Host "CONTRIBUTORS.md is maintained manually in this workflow."
400+
209401 - name : Publish GitHub release
210402 uses : softprops/action-gh-release@v2
211403 with :
404+ tag_name : ${{ needs.build.outputs.tag }}
405+ name : ThreadPilot ${{ needs.build.outputs.tag }}
406+ body : ${{ steps.git-cliff.outputs.content }}
212407 files : |
213- artifacts/release/installer/*.exe
214- artifacts/release/packages/*.zip
215- artifacts/release/msix/**/*.msix
216- artifacts/release/msix/**/*.appx
217- artifacts/release/msix/**/*.msixbundle
218- artifacts/release/msix/**/*.appxbundle
219- artifacts/release/SHA256SUMS.txt
408+ release-assets/installer/*.exe
409+ release-assets/packages/*.zip
410+ release-assets/msix/**/*.msix
411+ release-assets/msix/**/*.appx
412+ release-assets/msix/**/*.msixbundle
413+ release-assets/msix/**/*.appxbundle
414+ release-assets/SHA256SUMS.txt
415+ winget-manifests/**/*.yaml
416+ sbom/manifest.spdx.json
220417 generate_release_notes : true
0 commit comments