Repository navigation
Check for new version of extension when invoked, print message notifying user of upgrade #8183
Description
Describe the feature or problem you’d like to solve
GitHub CLI extension authors want to ensure users are running the newest version of extensions.
Like the GitHub CLI checks for updates every 24 hours when invoked, the GitHub CLI could perform the same logic when an extension command is invoked.
This would ensure GitHub CLI extension users knew about potentially necessary or valuable updates while minimizing the amount of effort on extension authors from reimplementing the logic already within GitHub CLI.
Proposed solution
-
Refactor the update logic within
cmd/gh/main.goto be reusableLines 59 to 68 in 64f4660
updateCtx, updateCancel := context.WithCancel(ctx) defer updateCancel() updateMessageChan := make(chan *update.ReleaseInfo) go func() { rel, err := checkForUpdate(updateCtx, cmdFactory, buildVersion) if err != nil && hasDebug { fmt.Fprintf(stderr, "warning: checking for update failed: %v", err) } updateMessageChan <- rel }() Lines 165 to 182 in 64f4660
updateCancel() // if the update checker hasn't completed by now, abort it newRelease := <-updateMessageChan if newRelease != nil { isHomebrew := isUnderHomebrew(cmdFactory.Executable()) if isHomebrew && isRecentRelease(newRelease.PublishedAt) { // do not notify Homebrew users before the version bump had a chance to get merged into homebrew-core return exitOK } fmt.Fprintf(stderr, "\n\n%s %s → %s\n", ansi.Color("A new release of gh is available:", "yellow"), ansi.Color(strings.TrimPrefix(buildVersion, "v"), "cyan"), ansi.Color(strings.TrimPrefix(newRelease.Version, "v"), "cyan")) if isHomebrew { fmt.Fprintf(stderr, "To upgrade, run: %s\n", "brew upgrade gh") } fmt.Fprintf(stderr, "%s\n\n", ansi.Color(newRelease.URL, "yellow")) } -
Enhance dynamic extension command generation to ensure extension release is checked independently of one another or GitHub CLI
Lines 170 to 175 in 64f4660
// Extensions em := f.ExtensionManager for _, e := range em.List() { extensionCmd := NewCmdExtension(io, em, e) cmd.AddCommand(extensionCmd) } -
Ensure latest release information logic supports GitHub Enterprise users
Lines 58 to 80 in 64f4660
func getLatestReleaseInfo(ctx context.Context, client *http.Client, repo string) (*ReleaseInfo, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repo), nil) if err != nil { return nil, err } res, err := client.Do(req) if err != nil { return nil, err } defer func() { _, _ = io.Copy(io.Discard, res.Body) res.Body.Close() }() if res.StatusCode != 200 { return nil, fmt.Errorf("unexpected HTTP %d", res.StatusCode) } dec := json.NewDecoder(res.Body) var latestRelease ReleaseInfo if err := dec.Decode(&latestRelease); err != nil { return nil, err } return &latestRelease, nil }
cc: @samcoe @nickfyson
Additional context
I was originally attempting to move the internal/update package to cli/go-gh, requiring the standardization on its api clients for the function. After talking with @samcoe about the process going from cli/cli api clients to cli/go-gh api clients, Sam's suggestion of having GitHub CLI do the checking would benefit all extensions without effort.
Activity
andyfeller commentedon Oct 23, 2023
Realizing there is duplication between this and #5964. I believe the thoughts here echo those made by @vilmibm about not wanting to impact the experience, primarily focusing on notifying the user the extension has a newer release available.
dylan-smith commentedon Oct 23, 2023
would this approach work for non-Go based extensions?
andyfeller commentedon Oct 24, 2023
@dylan-smith : personally, I would like some way that we could detect this for either binary and script based extensions. I'm not sure how this would work for extensions that are locally installed; likely nothing happens to them. The main challenge I can see is that script based extensions are cloned repositories even when installing via a pinned tag.
cli/pkg/cmd/extension/manager.go
Lines 211 to 237 in 20baccf
nickfyson commentedon Nov 1, 2023
Just wanted to officially 'plus 1' this issue, as having this functionality provided by the default CLI would enable us to take the duplicated functionality out of
github/gh-autofix. 🙂Also wanted to comment as a reminder to myself of the need for some coordination to avoid users getting double-notified (at least not too many times 😆).
andyfeller commentedon Nov 13, 2023
While discussing this with @samcoe today, we largely reaffirmed initial points above in that it made sense to add this logic specifically to the commands for extensions and that we would need to maintain state information for the extension.
The only unanswered question is: do we manage cached release information for extensions differently than GitHub CLI?
The GitHub CLI checks at the least every 24 hours whether there is a new version available and caches that information under state:
$ cat ~/.local/state/gh/state.yml checked_for_update_at: 2023-11-13T08:07:36.475011-05:00 latest_release: version: v2.38.0 url: https://github.com/cli/cli/releases/tag/v2.38.0 publishedat: 2023-11-01T10:52:41ZThe GitHub CLI manages extensions under data directory:
This division is based upon XDG Base Directory Specification, which causes us to question which trade off we're willing to make:
Treat the extension release information like state and maintain in
$XDG_STATE_HOMEdirectory, separate from the extensions themselves and their manifestsCouple the extension release information like extension artifacts and maintain in
$XDG_DATA_HOMEdirectory, spreading release information in multiple placesBetween these 2 approaches, it is arguable that the latter is more important the former.
0xdevalias commentedon Nov 14, 2023
Not to de-rail the discussion here too much, but I just opened a new semi-related issue that proposes adding a
gh extensions outdatedcommand, and it would seem that the update check+cached versions discussion here would work well for that feature too:gh extensions outdatedcommand + indicate outdated extensions ingh extensions listand similar #8327