feat: add a windows install script - #28
Merged
Merged
Conversation
install.ps1 is the Windows counterpart to install.sh, served at https://jwtd.sh/install.ps1 and published by the same Pages step. It keeps the Unix installer's contract - verify before writing anything, checksum always, a present cosign never advisory, the same certificate identity and issuer, no elevation - and differs only where Windows forces it to: - It consumes the windows .zip rather than the .tar.gz, because Expand-Archive ships with PowerShell 5.1 and tar does not. The zips already exist for WinGet and are covered by the signed checksums.txt. - Errors throw instead of exiting: under `irm | iex` an exit would close the user's shell. Preference variables are set inside Install-Jwtd for the same reason, so they do not leak into the caller's session. - It edits the user PATH itself, which install.sh can only hint at. The HKCU value is read unexpanded and written back as ExpandString, since [Environment]::SetEnvironmentVariable would rewrite %USERPROFILE%-style entries the installer never touched. - An upgrade renames the installed binary aside before moving the new one into place, because Windows cannot overwrite a running .exe. - Options come from environment variables, as Invoke-Expression cannot forward arguments. - Architecture detection corrects for x64-on-ARM64 emulation. install_test.go asserts the script's shape; the behaviour needs a real Windows host, so a windows-installer job installs the latest release for real, reinstalls over it, checks that an unavailable release writes nothing, and verifies the PATH edit leaves a seeded %USERPROFILE% entry verbatim. WebCodr.jwtd is not in winget-pkgs yet, so the site's Windows hero pointed at a command that fails today. It now offers the install script, and the Windows panel lists script, Scoop, then WinGet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
install.ps1is the Windows counterpart toinstall.sh, served athttps://jwtd.sh/install.ps1and published by the same Pages step:Same contract as install.sh
Verify before writing anything, checksum always, a present
cosignnever advisory, the same certificate identity and OIDC issuer, no elevation — user directory plusHKCUonly.Where Windows forced a different design
.zip, not the.tar.gz—Expand-Archiveships with PowerShell 5.1, tar does not. The zips already exist for WinGet and are covered by the signedchecksums.txt, so no new release artifact.throw, neverexit— underirm | iex,exitwould close the user's shell.$ErrorActionPreference/$ProgressPreferenceare set insideInstall-Jwtdfor the same reason: preference variables are dynamically scoped, so setting them at script scope would leave them applied to the caller's session.PATHitself, whichinstall.shcan only hint at. TheHKCU:\Environmentvalue is read withDoNotExpandEnvironmentNamesand written back asExpandString—[Environment]::SetEnvironmentVariableexpands%USERPROFILE%-style entries and writes the expanded text back, corrupting parts ofPATHthe installer never touched.WM_SETTINGCHANGEis broadcast (best-effort) so a new terminal sees it without signing out.-NoModifyPath/JWTD_NO_MODIFY_PATHopts out.jwtd.exeaside, move the new one in, then delete best-effort — Windows won't overwrite a running exe but will rename one. The analogue of install.sh's stage-then-rename(2)handling ofETXTBSY.JWTD_VERSION,JWTD_INSTALL_DIR,JWTD_NO_MODIFY_PATH) sinceInvoke-Expressioncannot forward arguments; theparam()block serves& ([scriptblock]::Create((irm …))) -Version ….Verification
install_test.gogains 8 tests mirroring the sh ones: archive naming pinned to.goreleaser.yaml, verify-before-write ordering, the shared Cosign trust root, noexit, no elevation, the registry handling, and the publication path. Comment lines are stripped before the "must not call" assertions, so a comment explaining why the script avoids an API cannot satisfy the check for it.The behaviour needs a real Windows host, so a
windows-installerjob intest.ymlinstalls the latest published release the way a user would, reinstalls over it to exercise the upgrade path, checks that an unavailable release writes nothing, and asserts thePATHedit adds the directory while leaving a seeded%USERPROFILE%\seededentry verbatim and the value stillREG_EXPAND_SZ.Locally, the helper functions were exercised under
pwsh: checksum match / mismatch / missing entry / exact-name-not-substring, architecture mapping, the non-Windows rejection, and that the embedded P/Invoke C# compiles.Site change beyond the installer
WebCodr.jwtdis not in winget-pkgs yet (moderation pending), so the site's Windows hero offeredwinget install WebCodr.jwtd— a command that fails today. It now offers the install script, and the Windows panel lists script → Scoop → WinGet. The WinGet instructions stay in place for when it merges.🤖 Generated with Claude Code