Skip to content

feat: add an install script for macOS and Linux - #27

Merged
bsg62 merged 1 commit into
mainfrom
feat/install-script
Jul 30, 2026
Merged

feat: add an install script for macOS and Linux#27
bsg62 merged 1 commit into
mainfrom
feat/install-script

Conversation

@bsg62

@bsg62 bsg62 commented Jul 30, 2026

Copy link
Copy Markdown
Member

Adds install.sh, a package-manager-free installer for macOS and Linux:

curl -fsSL https://jwtd.sh/install.sh | sh

What it does

  • Maps uname -s/uname -m onto the GoReleaser archive names (jwtd-<os>-<arch>.tar.gz), with a Rosetta correction so a translated shell on Apple silicon does not get the Intel binary. Unsupported platforms — including Windows kernels — fail before any download and point at WinGet/Scoop.
  • Downloads that archive plus checksums.txt from the latest release, or from --version v5.3.0.
  • Installs into ~/.local/bin (--dir / JWTD_INSTALL_DIR to override) and warns, with bash/zsh and fish hints, when that directory is not on PATH.

Verification

The archive is always checked against its checksums.txt entry (sha256sum, falling back to shasum -a 256). When cosign is on PATH, the keyless bundle over checksums.txt is verified against the release workflow's certificate identity, and a cosign failure aborts. cosign stays optional because most machines do not have it and the checksum already pins the bytes — but a present cosign is never advisory. Nothing is written to the install directory before verification passes.

The script runs under POSIX sh (it is piped into whatever /bin/sh the user has) and never calls sudo, so piping it into a shell is not a privilege decision. The binary is copied into the install directory under a temporary name and renamed within it, making the replacement a same-filesystem rename(2): an upgrade cannot leave a half-written binary behind and does not fail with ETXTBSY when the running shell's own jwtd is replaced.

Delivery

pages.yml copies the repository-root script into the Pages artifact (install -m 0755 install.sh site/install.sh, git-ignored), so https://jwtd.sh/install.sh serves the reviewed file byte-for-byte, and redeploys when install.sh changes. There is one copy of the script.

Documented in the README installation section and in the macOS and Linux install panels on the site; the release-security section notes the installer runs the same verification. RELEASE_NOTES.md carries prose for the next release.

Testing

install_test.go pins the archive naming to .goreleaser.yaml, the verify-before-install ordering, the Cosign identity matching the README, the sh/no-sudo properties, and the README/site/Pages wiring. Its behavior tests are hermetic: platform rejection is driven by a stubbed uname, so no test touches the network.

Manually verified against the real release: fresh install, pinned --version 5.2.0 over an existing binary, relative --dir, and — via a stubbed curl serving doctored assets — that a checksum mismatch, a missing checksum entry, and a bogus Cosign bundle each abort with nothing written to the install directory.

gofmt, go vet, go test ./..., the site JS tests, and shellcheck -s sh are clean.

🤖 Generated with Claude Code

install.sh downloads the release archive matching the detected OS and
architecture, verifies it against the release's checksums.txt, and installs
the binary into ~/.local/bin without root privileges or a package manager.
When cosign is present the keyless bundle over checksums.txt is verified too,
and a failure aborts; nothing is written before verification passes.

The Pages workflow copies the root script into the site artifact so
https://jwtd.sh/install.sh serves the reviewed file byte-for-byte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bsg62
bsg62 merged commit 606c9cb into main Jul 30, 2026
7 checks passed
@bsg62
bsg62 deleted the feat/install-script branch July 30, 2026 22:19
@bsg62
bsg62 temporarily deployed to github-pages July 30, 2026 22:20 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant