feat(cli): add machineid update self-update command - #17
Merged
Merged
Conversation
CLI only: the importable library gains no code, no network access and no dependencies. All logic lives in internal/selfupdate (standard library only) and cmd/machineid/update.go is a thin adapter. Release lookup for a public repository - The newest tag is read from the redirect that github.com/<repo>/releases/latest returns; a tag's existence from its release page; assets from releases/download/<tag>/<name>. No REST API, no gh, no token, so the unauthenticated 60/h quota never applies. - Redirects are followed only to github.com and *.githubusercontent.com. Hourly budget - At most 5 live lookups per rolling hour per user (MACHINEID_UPDATE_BUDGET overrides, 0 disables), the last answer cached for an hour in the user cache directory (0600). -check serves the cache; over budget it still answers from the stale cache while a real update refuses with the next allowed time. 429/403 Retry-After is persisted as a backoff. A corrupt or unwritable state file never blocks an update. Install - Linux zip and the new macOS universal zip replace the binary in place with an atomic rename staged in the target's directory. The macOS .pkg is used only when the running binary is in /usr/local/bin and needs root, which is never requested: the remedy prints the sudo command. `go install` is the fallback and the only method on Windows. - Both fixed-destination methods are guarded against installing somewhere other than the running binary; -force overrides. - SHA-256 is mandatory. Sigstore bundles are verified with cosign when present, Apple signatures with pkgutil/codesign; -require-signature makes a skipped check fatal. - Exit codes: 0 ok/current/-check/declined, 1 prerequisite (nothing attempted), 2 bad arguments, 3 attempted and failed. Release pipeline - Publish machineid-darwin-universal.zip + .zip.sha256 from the signed universal binary, so go-installed macOS copies can update in place. Docs - README "Updating the CLI" section and security bullets, CONTRIBUTING asset-name contract, package docs, copilot-instructions layout. Tests use an in-memory fake GitHub (httptest.NewTestServer), a fake exec and an injected clock; nothing reaches the real network. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…or machineid update - Skip the POSIX file-mode and executable-bit assertions on Windows. - The fake go env returns GOBIN verbatim so filepath.Join cannot rewrite separators on Windows; a new test covers the GOPATH/bin fallback. - docs/updating.md: quick start, walkthrough, flags, exit codes, per-platform table, install-target guard, cache and hourly budget with state-file paths, verification, script/cron/CI recipes, privacy, troubleshooting keyed by error text, FAQ. README links to it. Co-Authored-By: Claude Fable 5.1 <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.
Summary
Adds
machineid update, a self-update verb for the CLI only. The importable library gains no code, no network access and no dependencies; everything lives ininternal/selfupdate(standard library only) andcmd/machineid/update.gois a thin adapter.Builds on #15 (Go 1.27 bump), now merged. Design and rationale:
.plan/update-command.md(local, not committed), modelled onrrcli updatein ds-utils with the private-repo machinery removed.How it works
github.com/slashdevops/machineid/releases/latestreturns, a tag's existence from its release page, and assets fromreleases/download/<tag>/<name>. None of these carry the REST API's 60 req/h unauthenticated quota. Downloads only follow redirects togithub.comand*.githubusercontent.com.0600).-checkserves the cache and, over budget, still answers from the stale cache with the next allowed time; a real update refuses with exit 1.MACHINEID_UPDATE_BUDGEToverrides,0disables. A GitHub429/403Retry-Afteris persisted as a backoff. A corrupt or unwritable state file never blocks an update.machineidruns never touch the network; there is no background check and no nag. Root is never requested; the remedy prints thesudocommand..pkgis used only when the running binary is in/usr/local/bin.go installis the fallback and the only method on Windows (no Windows assets are published). Both fixed-destination methods are guarded against installing somewhere other than the running binary;-forceoverrides.cosignwhen installed, Apple signature viapkgutil/codesign;-require-signaturemakes a skipped check fatal.0ok / current /-check/ declined,1prerequisite not met (nothing attempted),2bad arguments (as elsewhere in the CLI),3attempted and failed.Release pipeline
release.ymlnow also publishesmachineid-darwin-universal.zip+.zip.sha256from the signed universal binary. Asset names are pinned byinternal/selfupdate/asset_test.goand documented in CONTRIBUTING as a contract.Decisions taken (say if you want any changed)
0/1/2/3, keeping2= invalid arguments CLI-wide-require-signatureinternal/selfupdate, unimportable from outside the moduleVerification
go test -race ./...on darwin; vet + test binaries compile for linux and windows; go fix / betteralign / modernize clean.httptest.NewTestServer), a fake exec and an injected clock; nothing reaches the real network.4 of 5 checks left this hour), a second-checkwas served from cache, and the install-target guard refused a binary outside/usr/local/binwith the-forceremedy (exit 1). A normalmachineid -debugrun logged no network activity.The first release the updater can move from is the one that ships it; it can move to any tag that carries assets, including older ones via
-version.🤖 Generated with Claude Code