fix(deploy): decode the box's output as UTF-8, so progress bars are bars and not "Γöü"

Mirror of the same change in the private scripts repo: [Console]::OutputEncoding is switched to UTF-8 (no BOM) around the deploy loop and restored in a finally. PowerShell 5.1 decodes ssh's stdout with the OEM code page, where the UTF-8 bytes of a progress bar read as three characters each.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
KellyMichels 2026-09-30 11:13:58 -05:00
parent 73dd27c4f1
commit 1a5a42fc33

View File

@ -1304,7 +1304,17 @@ function Invoke-ZTokensPublish {
# ── Dispatch ───────────────────────────────────────────────────────────────── # ── Dispatch ─────────────────────────────────────────────────────────────────
foreach ($key in $Projects) { # pip, uv and docker draw progress bars with box-drawing characters: "━" is
# the bytes E2 94 81. PowerShell 5.1 decodes a native command's stdout - ssh's,
# here - with [Console]::OutputEncoding, which on Windows is the OEM code page
# (437 on this machine), where those three bytes read "Γöü". Forty per bar.
# Decode the box's output as the UTF-8 it is for the duration of the deploy,
# and put the console back in the finally so a deploy that throws does not
# leave the session changed.
$prevConsoleEncoding = [Console]::OutputEncoding
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
try {
foreach ($key in $Projects) {
# 'ztokens' matches the tool it runs (ztokens.cmd / ztokens.ps1). The old # 'ztokens' matches the tool it runs (ztokens.cmd / ztokens.ps1). The old
# singular 'ztoken' still works so existing habits and any script that # singular 'ztoken' still works so existing habits and any script that
# already calls it keep running. # already calls it keep running.
@ -1320,6 +1330,9 @@ foreach ($key in $Projects) {
"static" { Invoke-StaticDeploy -Key $key -Proj $proj } "static" { Invoke-StaticDeploy -Key $key -Proj $proj }
default { throw "No deploy handler for kind '$($proj.kind)' (project '$key'). Add an Invoke-<Kind>Deploy function in zdeploy.ps1." } default { throw "No deploy handler for kind '$($proj.kind)' (project '$key'). Add an Invoke-<Kind>Deploy function in zdeploy.ps1." }
} }
}
} finally {
[Console]::OutputEncoding = $prevConsoleEncoding
} }
# The timestamp goes through Stop-ZTracking as the FinalNote so it lands after # 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 # the tracking footer and before the trailing blank lines - the last thing on