From 9a7bd6c9e8dd75ec8179ddb7aa00a0676f06b02d Mon Sep 17 00:00:00 2001 From: Ednunp <29843396+Ednunp@users.noreply.github.com> Date: Sun, 12 Jul 2026 20:06:34 +0100 Subject: [PATCH] Release scripts: notes-freshness check + gate the test deploy Local checkpoint - NOT for public release. - build-release.ps1: abort if RELEASE_NOTES.md is missing or doesn't mention the tag (it leads with "# RemSound "), so a stale notes file from the previous release can't ship with the wrong content via `gh release create --notes-file`. - deploy-test.ps1: a binary deploy now runs the build-and-test gate (run-tests.ps1) first and refuses to deploy a build that didn't pass - so a test build Ed picks up has always passed the suite. Sound-only refreshes skip it (no code change). New -SkipGate switch overrides when the gate was just run. Verified end-to-end. Co-Authored-By: Claude Opus 4.8 --- build-release.ps1 | 16 ++++++++++++++++ deploy-test.ps1 | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/build-release.ps1 b/build-release.ps1 index 84c5ba3..0f84c34 100644 --- a/build-release.ps1 +++ b/build-release.ps1 @@ -49,6 +49,22 @@ if ($csprojVersion -ne $tagVersion) { } Write-Host "Version check: tag $Tag matches csproj $csprojVersion." -ForegroundColor DarkGray +# 0y. RELEASE_NOTES.md must exist AND be written for THIS tag - the final `gh release create` ships it +# verbatim, so a copy left over from the previous release would publish the wrong notes. The notes +# lead with "# RemSound ", so requiring the tag string to appear catches a forgotten update. +$notesFile = Join-Path $repo 'RELEASE_NOTES.md' +if (-not (Test-Path -LiteralPath $notesFile)) { + Write-Host "RELEASE ABORTED - RELEASE_NOTES.md not found. Write the notes for $Tag and re-run." -ForegroundColor Red + exit 1 +} +$notesText = Get-Content -LiteralPath $notesFile -Raw +if ($notesText -notmatch [regex]::Escape($Tag)) { + Write-Host "RELEASE ABORTED - RELEASE_NOTES.md does not mention $Tag - it looks stale from a previous release." -ForegroundColor Red + Write-Host "Update RELEASE_NOTES.md for $Tag (it should lead with '# RemSound $Tag') and re-run." -ForegroundColor Red + exit 1 +} +Write-Host "Release notes check: RELEASE_NOTES.md is written for $Tag." -ForegroundColor DarkGray + # 0a. SoundForge drops a .sfk peak file next to every .wav it opens. They're byproducts that must # never ship (the build only bundles *.wav, so they wouldn't anyway) - clear them from the # source 'default sounds\' folder so they don't accumulate and clutter the working tree. diff --git a/deploy-test.ps1 b/deploy-test.ps1 index 7922987..6581576 100644 --- a/deploy-test.ps1 +++ b/deploy-test.ps1 @@ -14,6 +14,10 @@ # if RemSound is open and has them locked. # # Run: powershell -ExecutionPolicy Bypass -File deploy-test.ps1 +# Add -SkipGate to skip the build-and-test gate (e.g. when you just ran it) - by default a binary +# deploy runs run-tests.ps1 first and refuses to deploy a build that didn't pass. + +param([switch]$SkipGate) $ErrorActionPreference = 'Stop' $repo = $PSScriptRoot @@ -34,6 +38,19 @@ if ($soundOnly) { Write-Host "RemSound is running - refreshing SOUNDS only (binaries are locked; close RemSound to update them)." -ForegroundColor Yellow } else { + # Never deploy a build to test that hasn't passed the tests. The gate publishes + tests its own + # throwaway copy, so it doesn't touch the publish\ folder below. -SkipGate overrides (e.g. when the + # gate was just run in this session). Sound-only refreshes above skip it - they change no code. + if (-not $SkipGate) { + $gate = Join-Path $repo 'run-tests.ps1' + if (Test-Path -LiteralPath $gate) { + Write-Host "Running the build-and-test gate before deploying..." -ForegroundColor Cyan + & $gate + if ($LASTEXITCODE -ne 0) { throw "build-and-test gate FAILED - not deploying. Fix the failures above, or re-run with -SkipGate to override." } + } + else { Write-Host "WARNING: run-tests.ps1 not found - deploying WITHOUT the test gate." -ForegroundColor Yellow } + } + Write-Host "Publishing (Release) -> $publish ..." -ForegroundColor Cyan & dotnet publish $proj -c Release -o $publish --nologo -v q if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed ($LASTEXITCODE)" }