From 2a8c608653e646448e2f5bde7cf6c77ed99b1025 Mon Sep 17 00:00:00 2001 From: Ednunp <29843396+Ednunp@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:56:34 +0100 Subject: [PATCH] Release scripts: bulletproof test-deploy data preservation + tag/version gate Local checkpoint - NOT for public release. Two gaps found reviewing the publish/release scripts: - deploy-test.ps1: the binary sync (publish -> D:\Dropbox\remsound) used /E with no /MIR, so it never DELETES user data - but it could OVERWRITE it if publish\ ever accumulated a "user settings and logs" folder. Added /XD/'user settings and logs','recordings','logs', 'profiles','config' + /XF 'global config.json','remsound.config.json' so the binary sync is physically incapable of touching Ed's profiles/logs/config in either direction. Test deploys keep ALL of his data current, by construction. - build-release.ps1: never checked the -Tag against the csproj . A mismatch ships RemSound-.zip containing a different version's binary, which the in-app updater (it downloads by tag name) reads as a perpetual "update available". Now aborts up front if tag != csproj - also catches a forgotten version bump. The intended split was already correct: test deploy keeps everything; build-release publishes to a fresh folder, strips pdb, and scans staged files AND the zip for any profiles/logs/config/recordings, aborting if found. Co-Authored-By: Claude Opus 4.8 --- build-release.ps1 | 14 ++++++++++++++ deploy-test.ps1 | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/build-release.ps1 b/build-release.ps1 index 4c1e9a5..84c5ba3 100644 --- a/build-release.ps1 +++ b/build-release.ps1 @@ -35,6 +35,20 @@ $distDir = Join-Path $repo 'dist' $zipPath = Join-Path $distDir "RemSound-$Tag.zip" $staging = Join-Path ([System.IO.Path]::GetTempPath()) ("remsound-release-" + [guid]::NewGuid().ToString('N')) +# 0z. The -Tag MUST match the csproj . The in-app updater downloads exactly +# "RemSound-.zip" and compares the running version to the tag; a mismatch (e.g. tag v5.3 but +# the binary is still 5.2 because the version bump was forgotten) ships a zip whose contents don't +# match its name, which the updater sees as a perpetual "update available". Catch it before any work. +$csprojText = Get-Content -LiteralPath $proj -Raw +$csprojVersion = if ($csprojText -match '([^<]+)') { $Matches[1].Trim() } else { '' } +$tagVersion = $Tag.TrimStart('v') +if ($csprojVersion -ne $tagVersion) { + Write-Host "RELEASE ABORTED - tag $Tag ($tagVersion) does not match the csproj ($csprojVersion)." -ForegroundColor Red + Write-Host "Bump in RemSound.App.csproj to $tagVersion (and add the About-box changelog entry), or fix the tag, then re-run." -ForegroundColor Red + exit 1 +} +Write-Host "Version check: tag $Tag matches csproj $csprojVersion." -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 3156725..7922987 100644 --- a/deploy-test.ps1 +++ b/deploy-test.ps1 @@ -43,7 +43,13 @@ foreach ($loc in $runLocations) { # Binaries: publish\ already has them from the publish above; copy them to the other location(s). if (-not $soundOnly -and $loc -ne $publish) { Write-Host "Deploying program + binaries -> $loc (preserving user settings/logs) ..." -ForegroundColor Cyan - Invoke-Robocopy @($publish, $loc, '/E') # no /MIR: never delete the user's settings/logs/profiles + # /E copies the program + binaries; NO /MIR so we never DELETE the user's data. The /XD + # excludes make the copy incapable of OVERWRITING it either: if publish\ ever accumulated a + # user-data folder (a stray run from there), it must never land on Ed's real Dropbox profiles/ + # config/logs. The binary sync only ever carries program files, never user state, both ways. + Invoke-Robocopy @($publish, $loc, '/E', + '/XD', 'user settings and logs', 'recordings', 'logs', 'profiles', 'config', + '/XF', 'global config.json', 'remsound.config.json') } # THE point of this script: the whole source 'default sounds' folder, force-copied over THIS # location's copy, every time. /IS = copy even files robocopy thinks are identical; /IT = copy