An unset HOST_CER_PATH is $null, and a null hash key is fatal — not an empty key #231

Merged
enricobuehler merged 1 commits from fix-host-cer-alias-null-key into main 2026-08-14 18:08:37 +00:00
Owner

Follow-up fixing a bug I introduced in #228.

Azure signing produces no .cer, so HOST_CER_PATH is deliberately unset. The publish step built its alias map as one hash literal with $env:HOST_CER_PATH as a key, and an unset $env: var is $null:

A null key is not allowed in a hash literal.

Canary run 18256: the installer signed and published fine to its versioned path, then this line failed the step, so the canary/punktfunk-host-setup.exe alias never refreshed and is stale.

I looked at this exact line while making the .cer optional and concluded an unset variable would produce an empty-string key, which is legal. It doesn't — that only happens via string interpolation. The $files guard immediately above filters the missing .cer correctly, but the hash literal runs before anything can use it.

The map is now built incrementally, adding the .cer entry only when there is one, so the legacy .pfx modes still alias it.

windows-client.yml survived the same change only by accident: it writes "$($env:MSIX_CER_PATH)", and interpolating $null yields an empty string, which is a legal key. That's why both client jobs went green while the host failed. Made it explicit there too, rather than leaving correctness resting on quotes someone could reasonably tidy away.

Verification

Reproduced and fixed under pwsh 7:

  • old literal, var unset → A null key is not allowed in a hash literal (the exact CI message)
  • new form, var unset → 1 entry, no error
  • new form, var set → 2 entries, .cer alias intact (legacy pfx path unaffected)

Both workflows still parse as valid YAML.

Worth noting what this does not affect: signing itself was already proven in that same run — "Pack + sign installer" succeeded, and both client jobs signed their MSIX and verified the Publisher subject against the Azure profile.

Follow-up fixing a bug I introduced in #228. Azure signing produces no `.cer`, so `HOST_CER_PATH` is deliberately unset. The publish step built its alias map as one hash literal with `$env:HOST_CER_PATH` as a **key**, and an unset `$env:` var is `$null`: ``` A null key is not allowed in a hash literal. ``` Canary run [18256](https://git.unom.io/unom/punktfunk/actions/runs/18256): the installer **signed and published fine** to its versioned path, then this line failed the step, so the `canary/punktfunk-host-setup.exe` alias never refreshed and is stale. I looked at this exact line while making the `.cer` optional and concluded an unset variable would produce an empty-string key, which is legal. It doesn't — that only happens via string interpolation. The `$files` guard immediately above filters the missing `.cer` correctly, but the hash literal runs before anything can use it. The map is now built incrementally, adding the `.cer` entry only when there is one, so the legacy `.pfx` modes still alias it. `windows-client.yml` survived the same change **only by accident**: it writes `"$($env:MSIX_CER_PATH)"`, and interpolating `$null` yields an empty string, which *is* a legal key. That's why both client jobs went green while the host failed. Made it explicit there too, rather than leaving correctness resting on quotes someone could reasonably tidy away. ## Verification Reproduced and fixed under pwsh 7: - old literal, var unset → `A null key is not allowed in a hash literal` (the exact CI message) - new form, var unset → 1 entry, no error - new form, var **set** → 2 entries, `.cer` alias intact (legacy pfx path unaffected) Both workflows still parse as valid YAML. Worth noting what this does *not* affect: signing itself was already proven in that same run — "Pack + sign installer" succeeded, and both client jobs signed their MSIX and verified the Publisher subject against the Azure profile.
enricobuehler added 1 commit 2026-08-14 18:08:22 +00:00
fix(ci): an unset HOST_CER_PATH is $null, and a null hash key is fatal — not an empty key
ci / bun-nix (pull_request) Successful in 16s
ci / web (pull_request) Successful in 1m4s
ci / rust-arm64 (pull_request) Failing after 1m42s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 2m43s
ci / docs-site (pull_request) Successful in 8m29s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 6m18s
ci / rust (pull_request) Failing after 21m4s
80061fbf6b
Azure signing produces no .cer, so HOST_CER_PATH is deliberately unset. The publish step then built
its alias map as a single hash literal containing $env:HOST_CER_PATH as a KEY, and an unset $env:
var is $null — "A null key is not allowed in a hash literal", which failed the whole step. Canary
run 18256: the installer signed fine and published to its versioned path, then this line killed the
alias refresh, so `canary/punktfunk-host-setup.exe` went stale.

I reasoned about this line while making the .cer optional and concluded an unset variable would give
an empty-string key, which is legal. It does not — that only happens through string interpolation.
The $files guard just above filters the missing .cer correctly; the hash literal ran before anything
could use it.

Build the map incrementally instead, adding the .cer entry only when there is one, so the legacy
.pfx modes still alias it.

windows-client.yml survived the same change only by accident: it writes "$($env:MSIX_CER_PATH)",
and interpolating $null yields an empty string, which IS a legal key. Made that explicit too rather
than leaving correctness resting on quotes someone could reasonably tidy away.

Verified under pwsh 7: the old literal reproduces the exact CI message with the var unset; the new
form yields one entry unset and two entries set, with the .cer alias intact.
enricobuehler merged commit aa53f1e5ef into main 2026-08-14 18:08:37 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#231