From d013dc79f104f8603b682b2266713ff886c9a421 Mon Sep 17 00:00:00 2001 From: KellyMichels Date: Tue, 25 Aug 2026 15:34:55 -0500 Subject: [PATCH] feat: two blank lines after every z-script run zdeploy ended with two blank lines and nothing else did, so its output was the only one that did not butt up against the next prompt. Applied everywhere. Implemented in Stop-ZTracking rather than per script, because every tracked script ends by calling it - including the usage and guard paths that do `Stop-ZTracking; exit 1`. One place therefore covers every exit of sixteen scripts. * Write-ZTrailer emits the two lines. Stop-ZTracking calls it on both paths, including the early return when tracking never started - a script that printed output still deserves the separation. * -FinalNote prints one last line AFTER the tracking footer and BEFORE the blanks. zdeploy's "Last deployed at ..." now goes through it, so it stays the last thing on screen instead of being followed by the token count. * The standalone tools (zchecksums, zversion, zrelease) get a local three-line copy at each exit rather than dot-sourcing ZHelpers - they are deliberately dependency-free so they run from an extracted release zip with nothing beside them. * Redundant trailing blanks were removed where a script already printed one before exiting, so the count is exactly two, not three. Also fixes a related gap found while testing: the error exits inside Get-ZConfig and Get-ZProject bypassed Stop-ZTracking entirely, so a run that died on a missing zconfig.json printed no trailer AND no token footer. Those three exits now route through Stop-ZTracking. zkill/zrestart are one-line wrappers around scripts that already trail, so they are untouched - adding it would double the blanks. Verified by running each script and counting the trailing blank lines in its captured output: 2 on every success path, every usage path, and the config-error path. Suite 231/231. CHECKSUMS.txt refreshed. --- CHECKSUMS.txt | 14 +++++++------- ZHelpers.ps1 | 30 ++++++++++++++++++++++++++---- setup_backup_schedule.ps1 | 2 ++ token-count.ps1 | 2 +- zchecksums.ps1 | 14 +++++++++++--- zdeploy.ps1 | 16 ++++++---------- zrelease.ps1 | 21 ++++++++++++++++----- zversion.ps1 | 14 +++++++++++++- 8 files changed, 82 insertions(+), 31 deletions(-) diff --git a/CHECKSUMS.txt b/CHECKSUMS.txt index aa635ee..4eaa2ec 100644 --- a/CHECKSUMS.txt +++ b/CHECKSUMS.txt @@ -1,27 +1,27 @@ -66ed14be538677f84983d9a3f474b3d4293d90ff9e64e172c7ebc52a7ff54b13 setup_backup_schedule.ps1 -51a29d81dd5b8792a2262e8977b37a0db3172751ed510507ff6579e625837efd token-count.ps1 +445b3783d6f7babb50faf6c2ebc755bc5a320208c5a37b32756ef64f6dc70330 setup_backup_schedule.ps1 +77015a96b6b48a3b6edea287862f1913946ecc909e7456d72ce4e88f92160811 token-count.ps1 a8a0e4449750df0599424608766d871fca1462d85086f82eec5a9e0d02545ad5 zbackup.cmd 272f14751b7e5976a1c33024df57c237cb48c74fd44bc64e144f09700eaef493 zbackup.ps1 22269ebf3db51ff82324bc56b529bd8b28708a8a52457fb041b2147f1883c072 zbackup_and_sync.ps1 d03d5adfbae02afaa158c76a9e8d22e0a3e4a0260b5d5b4707e6f6450f764d01 zbackup_ec2.cmd dbd1b9c64fba16a308ffa8fa936f1bfda556b049aaa30ebe5400ca74b7e6aa5d zbackup_ec2.ps1 e03075f367a9ecee0f97438bc381044c74b7bd4e8cb4ff66b40048bba7ffd25a zchecksums.cmd -8382ad5f972405678b73616f608a80e3eb1814c927ba104e446d36c4f9f5c66d zchecksums.ps1 +21b95ceab2c7e2348aaf0cfe98f569bc6921745d3378d7e1557ce7ea02c0ae14 zchecksums.ps1 3d1064817ace57fe61c54104900775a0208fdf7e782043cced84b002347acb11 zdeploy.cmd -463cd3e3f4c24614e8894be94d1b7aa8446bd603d341c49c82a61fc811a9094f zdeploy.ps1 +f60ec2bb0d79f82269065409716514fcb5a298db2c7e2da7e37c63de58d9b389 zdeploy.ps1 6fa05d7c47992801d0ad65095146764cc207b566dca85956b3152221ef9af368 zec2.cmd 72217c04e8975f46b489bd7e223f9fda926d982a8e418fc2825c6aa4657f73b7 zec2.ps1 d0702f372ec5e47e2632229c61b71a9184edf0775d6e23af74e3f919d13eadb9 zec2_rotatekeys.cmd 0dd4e6fda06dbb023884d051851bf4700c8db020b7ac319bb44c5974990839f7 zec2_rotatekeys.ps1 70b3833c4e9e3232f2b694768fb3c14434157cc9ec746f1dd39b3dedbfdb180e zec2online.cmd c3d5cca9cc94f51c97db01d22ceb140ef324e6f34c2fd1d4a3d0abbc0c3da263 zec2online.ps1 -e806692a113bac17f364cbdf7167f4c86513819ee65733be997588355db57cdb ZHelpers.ps1 +efd6ebb3c1024960538f788e904bafe220768f5112dc43575ef860efb489582b ZHelpers.ps1 c62535257a4af8d7b08ef00a98c4d0ce907c91bf905bed478e4bef7eaea2c3a5 zkill.cmd 0b58265cab05f1fe86a4707b6c6c5c4c492192b1a3176951141399a44a5e26ca zkill.ps1 88db51d332c3439ccdf85aa4196fec1a6db4b5289eb18065ea7f881d37f625d4 ZKiller.ps1 32573d676ceabadee0d89b46de05b73deec5489a317771e13c4b15f7d34d8427 ZKillOnly.ps1 392bddfa7e1c0fc21a828fa5af06d19156fd7305edfa2d5408f6335c3900716e zrelease.cmd -58b85d9a664d80d440be6b24332f3cec7d3fafb9021591e545a1ea916a17734a zrelease.ps1 +f767919315a1c847cb2d88819b2bad75eee98ff43157f01ed1b41d1058cddf53 zrelease.ps1 5ee7d7363362fab926487b8a622b9a0b7716ed08b2a74679e1d0e33659f58eec zrepair.cmd 48b00d3443e001f7265d8cda85b384f5b5ce39bf5eda5bcf711492da147c455f zrepair.ps1 4258b613e3913fbb24a54009452e829881a07a56956cd94b6878a1890d9cc422 zrestart.cmd @@ -39,4 +39,4 @@ b937fa0786eaccab596e5cdf67f40f0abadc1c52b3bef5e896e3cf16563d7b63 zstart_docker. e4dc95d5c8749c22fa85c4885ab8d65e7bb37a543260709fca0cac3fa0380e62 zsync.cmd 0d8615e7d4078e5bbeee8b6373302a3eb138709863256e982b06a3882613123c zsync.ps1 32b5a359a6d3e3006879eac8ecca112990d07c5993e0feeec29de5666a555e4e zversion.cmd -327ca6074139fa696db8d1e4d2e4e01bf4bbbcb9145b8384de10fee14d564911 zversion.ps1 +58974b7b9fc466d69890d72878957589f879794f9ea933bce96d379e5ead5aee zversion.ps1 diff --git a/ZHelpers.ps1 b/ZHelpers.ps1 index add557c..51e3a95 100644 --- a/ZHelpers.ps1 +++ b/ZHelpers.ps1 @@ -61,13 +61,13 @@ function Get-ZConfig { if (-not (Test-Path -LiteralPath $configPath)) { Write-Host "ERROR: zconfig.json not found at $configPath" -ForegroundColor Red Write-Host " Copy zconfig.example.json to zconfig.json and fill in your values." -ForegroundColor DarkGray - exit 1 + Stop-ZTracking; exit 1 } try { $script:ZConfigCache = Get-Content -LiteralPath $configPath -Raw -Encoding UTF8 | ConvertFrom-Json } catch { Write-Host "ERROR: Failed to parse zconfig.json - $($_.Exception.Message)" -ForegroundColor Red - exit 1 + Stop-ZTracking; exit 1 } return $script:ZConfigCache } @@ -87,7 +87,7 @@ function Get-ZProject { if (-not $proj) { $available = (Get-ZProjectKeys) -join ', ' Write-Host "ERROR: Unknown project key '$Key'. Available: $available" -ForegroundColor Red - exit 1 + Stop-ZTracking; exit 1 } return $proj } @@ -720,8 +720,29 @@ function Add-ZTokensRecord { } catch { } } +# Two blank lines below every z-script's output, so a run is visually separated +# from the next prompt instead of butting up against it. Emitted here because +# every script ends by calling Stop-ZTracking - including the usage and guard +# paths that `Stop-ZTracking; exit 1` - so one place covers every exit. +# +# -FinalNote prints one last line AFTER the tracking footer but BEFORE the blank +# lines, for a script that wants the bottom of the screen to say something more +# useful than a token count (zdeploy's "Last deployed at ..."). +function Write-ZTrailer { + param([string]$FinalNote) + if ($FinalNote) { + Write-Host "" + Write-Host $FinalNote -ForegroundColor Cyan + } + Write-Host "" + Write-Host "" +} + function Stop-ZTracking { - if (-not $global:_ZTrackPath) { return } + param([string]$FinalNote) + # The trailer is owed whether or not tracking ever started - a script that + # printed output still deserves the separation. + if (-not $global:_ZTrackPath) { Write-ZTrailer -FinalNote $FinalNote; return } try { Stop-Transcript | Out-Null } catch {} $tp = $global:_ZTrackPath $global:_ZTrackPath = $null @@ -747,4 +768,5 @@ function Stop-ZTracking { Add-ZTokensRecord -Lines $lc -Chars $cc -Est $tok } catch {} Remove-Item -LiteralPath $tp -Force -ErrorAction SilentlyContinue + Write-ZTrailer -FinalNote $FinalNote } diff --git a/setup_backup_schedule.ps1 b/setup_backup_schedule.ps1 index b42156c..82df2f7 100644 --- a/setup_backup_schedule.ps1 +++ b/setup_backup_schedule.ps1 @@ -27,6 +27,7 @@ Write-Host "" if (-not (Test-Path -LiteralPath $ScriptPath)) { Write-Host "ERROR: Script not found: $ScriptPath" -ForegroundColor Red Write-Host " Check paths.scriptsRoot in zconfig.json" -ForegroundColor DarkGray + Write-ZTrailer exit 1 } @@ -40,6 +41,7 @@ if ($existingTask) { Write-Host "Deleted existing task." -ForegroundColor Green } else { Write-Host "Keeping existing task. Exiting." -ForegroundColor Yellow + Write-ZTrailer exit 0 } } diff --git a/token-count.ps1 b/token-count.ps1 index 433729b..52fcab5 100644 --- a/token-count.ps1 +++ b/token-count.ps1 @@ -170,4 +170,4 @@ Write-Host "" Write-Host "Note: zdeploy output varies significantly between runs." -ForegroundColor DarkGray Write-Host " First run after package updates can be 2-3x larger than a cached run." -ForegroundColor DarkGray Write-Host " Run zdeploy twice and use the second (cached) figure for TOKEN_SAVINGS.md." -ForegroundColor DarkGray -Write-Host "" +Write-ZTrailer diff --git a/zchecksums.ps1 b/zchecksums.ps1 index a7d573f..13ac5ae 100644 --- a/zchecksums.ps1 +++ b/zchecksums.ps1 @@ -54,6 +54,13 @@ param( $ErrorActionPreference = "Stop" +# Two blank lines after this script's output, matching every other z-script, so +# a run is visually separated from the next prompt. Local rather than from +# ZHelpers: this script is deliberately standalone, so it can run from an +# extracted release zip with nothing beside it. +function Write-ZTrailer { Write-Host ""; Write-Host "" } + + $ManifestName = "CHECKSUMS.txt" $Manifest = Join-Path $PSScriptRoot $ManifestName @@ -99,13 +106,14 @@ if ($Update) { Write-Host "=== zchecksums (updated) ===" -ForegroundColor Cyan Write-Host (" Wrote {0} with {1} entries." -f $ManifestName, $files.Count) -ForegroundColor Green Write-Host " Commit it alongside the script change, or verification will fail." -ForegroundColor DarkGray - Write-Host "" + Write-ZTrailer exit 0 } $expected = Read-Manifest if ($null -eq $expected) { Write-Host "ERROR: $ManifestName not found. Run 'zchecksums -Update' to create it." -ForegroundColor Red + Write-ZTrailer exit 1 } @@ -134,11 +142,11 @@ if (-not $Quiet) { if ($bad -eq 0) { Write-Host (" OK - {0} file(s) match {1}." -f $ok, $ManifestName) -ForegroundColor Green - Write-Host "" + Write-ZTrailer exit 0 } Write-Host (" FAILED - {0} ok, {1} changed, {2} missing, {3} unlisted." -f $ok, $changed.Count, $missing.Count, $unlisted.Count) -ForegroundColor Red Write-Host " If you changed a script on purpose, run: zchecksums -Update" -ForegroundColor DarkGray -Write-Host "" +Write-ZTrailer exit 1 diff --git a/zdeploy.ps1 b/zdeploy.ps1 index 05de906..0af2b83 100644 --- a/zdeploy.ps1 +++ b/zdeploy.ps1 @@ -904,13 +904,9 @@ foreach ($key in $Projects) { default { throw "No deploy handler for kind '$($proj.kind)' (project '$key'). Add an Invoke-Deploy function in zdeploy.ps1." } } } -Stop-ZTracking - -# Last line of the run, after the tracking footer: scroll to the bottom and you -# can see how long ago this deployed. Only reached on success - a failed deploy -# throws out of the loop above, so this never claims a deploy that didn't happen. -Write-Host "" -Write-Host ("Last deployed at {0}" -f (Get-Date -Format "MM/dd/yyyy hh:mm:ss tt")) -ForegroundColor Cyan -# Two blank lines below, so the timestamp isn't crowded by the next prompt. -Write-Host "" -Write-Host "" +# The timestamp goes through Stop-ZTracking as the FinalNote so it lands after +# the tracking footer and before the trailing blank lines - the last thing on +# screen, which is the point: scroll to the bottom and you can see how long ago +# this deployed. Only reached on success; a failed deploy throws out of the loop +# above, so this never claims a deploy that didn't happen. +Stop-ZTracking -FinalNote ("Last deployed at {0}" -f (Get-Date -Format "MM/dd/yyyy hh:mm:ss tt")) diff --git a/zrelease.ps1 b/zrelease.ps1 index 32551b7..e338b84 100644 --- a/zrelease.ps1 +++ b/zrelease.ps1 @@ -40,16 +40,25 @@ param( $ErrorActionPreference = "Stop" +# Two blank lines after this script's output, matching every other z-script, so +# a run is visually separated from the next prompt. Local rather than from +# ZHelpers: this script is deliberately standalone, so it can run from an +# extracted release zip with nothing beside it. +function Write-ZTrailer { Write-Host ""; Write-Host "" } + + $ReleasesDir = Join-Path $PSScriptRoot "releases" $VersionFile = Join-Path $PSScriptRoot "build-version.json" if (-not (Test-Path -LiteralPath $VersionFile)) { Write-Host "ERROR: build-version.json not found. Run 'zversion set v1.0.0.0.0' first." -ForegroundColor Red + Write-ZTrailer exit 1 } $version = (Get-Content -LiteralPath $VersionFile -Raw -Encoding UTF8 | ConvertFrom-Json).version if ($version -notmatch '^v\d+\.\d+\.\d+\.\d+\.\d+$') { Write-Host "ERROR: build-version.json holds an invalid version '$version'." -ForegroundColor Red + Write-ZTrailer exit 1 } @@ -65,10 +74,12 @@ function Get-Sha256([string]$Path) { if ($Verify) { if (-not (Test-Path -LiteralPath $zipPath)) { Write-Host "ERROR: $zipName not found in releases/." -ForegroundColor Red + Write-ZTrailer exit 1 } if (-not (Test-Path -LiteralPath $shaPath)) { Write-Host "ERROR: $zipName.sha256 not found." -ForegroundColor Red + Write-ZTrailer exit 1 } $expected = ((Get-Content -LiteralPath $shaPath -Raw) -split '\s+')[0].ToLowerInvariant() @@ -77,11 +88,11 @@ if ($Verify) { Write-Host "=== zrelease (verify) ===" -ForegroundColor Cyan if ($actual -eq $expected) { Write-Host " OK - $zipName matches its .sha256." -ForegroundColor Green - Write-Host "" + Write-ZTrailer exit 0 } Write-Host " FAILED - $zipName does not match its .sha256." -ForegroundColor Red - Write-Host "" + Write-ZTrailer exit 1 } @@ -91,7 +102,7 @@ if ((Test-Path -LiteralPath $zipPath) -and -not $Force) { Write-Host "ERROR: releases/$zipName already exists." -ForegroundColor Red Write-Host " A released version is immutable - bump instead: zversion bump" -ForegroundColor DarkGray Write-Host " (or pass -Force if you are rebuilding one that was never published)" -ForegroundColor DarkGray - Write-Host "" + Write-ZTrailer exit 1 } @@ -101,7 +112,7 @@ if ($LASTEXITCODE -ne 0) { Write-Host "" Write-Host "ERROR: checksum verification failed - refusing to package." -ForegroundColor Red Write-Host " Run 'zchecksums' to see what differs, then 'zversion bump' to restamp." -ForegroundColor DarkGray - Write-Host "" + Write-ZTrailer exit 1 } @@ -142,5 +153,5 @@ Write-Host " SHA-256: $hash" -ForegroundColor Gray Write-Host " Digest: releases/$zipName.sha256" -ForegroundColor Gray Write-Host "" Write-Host " Commit both files - a release lives in the repo under releases/." -ForegroundColor DarkGray -Write-Host "" +Write-ZTrailer exit 0 diff --git a/zversion.ps1 b/zversion.ps1 index b5a590a..0f3e4ce 100644 --- a/zversion.ps1 +++ b/zversion.ps1 @@ -43,6 +43,13 @@ param( $ErrorActionPreference = "Stop" +# Two blank lines after this script's output, matching every other z-script, so +# a run is visually separated from the next prompt. Local rather than from +# ZHelpers: this script is deliberately standalone, so it can run from an +# extracted release zip with nothing beside it. +function Write-ZTrailer { Write-Host ""; Write-Host "" } + + $VersionFile = Join-Path $PSScriptRoot "build-version.json" $VersionRe = '^v(\d+)\.(\d+)\.(\d+)\.(\d+)\.(\d+)$' $DefaultVersion = "v1.0.0.0.0" @@ -113,11 +120,13 @@ $current = Read-Version switch ($Command.ToLowerInvariant().TrimStart('-')) { "get" { Write-Host $current + Write-ZTrailer exit 0 } "bump" { $p = Split-Version $current Update-Everything ("v{0}.{1}.{2}.{3}.{4}" -f $p[0], $p[1], $p[2], $p[3], ($p[4] + 1)) + Write-ZTrailer exit 0 } "bump-stage" { @@ -130,16 +139,19 @@ switch ($Command.ToLowerInvariant().TrimStart('-')) { "alpha" { $alpha++ } default { Write-Host "ERROR: stage must be one of: release, rc, beta, alpha" -ForegroundColor Red + Write-ZTrailer exit 1 } } # Bumping a stage zeroes every lower segment, build included. Update-Everything ("v{0}.{1}.{2}.{3}.0" -f $major, $rc, $beta, $alpha) + Write-ZTrailer exit 0 } "set" { [void](Split-Version $Value) Update-Everything $Value + Write-ZTrailer exit 0 } default { @@ -148,7 +160,7 @@ switch ($Command.ToLowerInvariant().TrimStart('-')) { Write-Host " Scheme: v{major}.{rc}.{beta}.{alpha}.{build} (current: $current)" -ForegroundColor Gray Write-Host " bump build + 1 - one per PR, one per defect fix" -ForegroundColor Gray Write-Host " bump-stage raise a stage; every lower segment resets to 0" -ForegroundColor Gray - Write-Host "" + Write-ZTrailer exit 1 } }