Skip to content

Make the update check source a choice of four - #7785

Merged
proggeramlug merged 1 commit into
PerryTS:mainfrom
jdalton:feat/update-check-sources
Aug 11, 2026
Merged

Make the update check source a choice of four#7785
proggeramlug merged 1 commit into
PerryTS:mainfrom
jdalton:feat/update-check-sources

Conversation

@jdalton

@jdalton jdalton commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Stacked on #7784, which is stacked on #7749. Until those merge this branch's diff includes their commits; I will rebase as each lands.

Where Perry asks "what is the latest version?" becomes a choice

It used to walk one fixed list — an override, the config, Perry Hub, then the GitHub releases API — and read a GitHub-releases-shaped document from whichever answered first.

That is fine while everyone installs the same way, and wrong as soon as they do not. An npm user's "latest" is whatever the registry's latest dist-tag says, so asking GitHub instead can announce a version their package manager cannot install yet — a notice telling someone to upgrade to something they cannot get.

[update]
source = "npm"              # gh-releases | npm | gh-registry | custom
package = "@perryts/perry"  # npm-shaped sources; defaults to Perry's own
registry = "..."            # npm-shaped sources; defaults to the public registry
server = "..."              # the URL for `custom`, and the mirror override

Leaving source unset keeps today's behaviour exactly, except on an npm-managed install, which now defaults to asking npm — because that is the version its own package manager can actually install.

The split that matters: checking is not downloading

A source answers one question and returns a version, a link, a publish time and a headline. It does not decide where the binary comes from. Artifacts and their signed manifest always resolve from the release infrastructure, whatever the source is.

That separation is load-bearing rather than tidy. The manifest — Ed25519 over the artifact's digest and version — is what makes a self-update trustworthy, and source is a URL a user can point anywhere. If it could redirect the download, this setting would be a way to install arbitrary code. Whoever answers "what is new?" never gets to answer "what should I run?", and there is a test that fails if a source ever leaks into the artifact ladder.

Why the old ladder is deleted rather than left underneath

get_update_servers and its private config reader are gone, not kept beside the new code.

Leaving them would produce the shape where four sources exist, pass their own unit tests, and are never actually reached, because the call sites still walk the old list. Deleting them makes the compiler prove both sites moved — there is no version of this change that builds while the new abstraction is dead.

Credentials go to exactly one of the four

The npm shapes request the abbreviated packument (Accept: application/vnd.npm.install-v1+json) — smaller, cacheable, and the document npm itself asks for. It also sidesteps GitHub's unauthenticated API rate limit, which the old ladder shared with everything else on the machine.

The public registry is asked without credentials, and a test asserts no Authorization header is sent: a token there would be a leak, not a convenience. GitHub Packages does need one, so that shape reads GH_TOKEN / GITHUB_TOKEN and fails with a sentence naming the fix when neither is set — rather than retrying anonymously and reporting the resulting 404 as "up to date".

A configured source does not fall back to the ladder when it errors. Somebody who said "ask npm" and got a failure wants to hear that, not a version from somewhere they never named.

Tests

11 new, all parsing real response shapes from string fixtures, so no network is involved:

  • a GitHub release document, including that the v prefix is stripped;
  • an abbreviated packument, which carries no time map — so the publish date reads "unknown" rather than being invented, which matters because the release cooldown in the next slice depends on it;
  • a full packument, which does supply it;
  • a custom manifest with only a version, and one with every optional field;
  • that each shape rejects the others' documents rather than reading whichever field happens to be present — a registry answering a gh-releases request must be an error, not a version of "";
  • that a scoped package's / is percent-encoded, or the registry reads the scope as a path segment and answers 404;
  • that an unknown source falls back to the default instead of failing, because an update check is the wrong place to turn a config typo into a hard error;
  • that custom with no URL is a missing key rather than a default;
  • that an npm install defaults to npm while every other channel keeps the ladder;
  • that no source can reach the artifact ladder;
  • and both credential rules.

cargo test -p perry: 932 passed, 0 failed.

No version bump — the maintainer bumps at merge, per the external-contributor flow.

Summary by CodeRabbit

  • New Features
    • Configure update behavior with off, notify, prompt, or auto using perry update --mode.
    • Update checks now recognize installation channels and display channel-specific upgrade guidance.
    • Configure update-check sources, including GitHub Releases, npm, package registries, and custom HTTPS endpoints.
    • Notifications are version-aware and better respect configured intervals.
  • Bug Fixes
    • Improved update-cache reliability and compatibility with existing cache files.
    • Prevented malformed configuration files from being overwritten.
  • Documentation
    • Added guidance for update modes, installation channels, check sources, and related safeguards.

Loading
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.

2 participants