feat: add update subcommand for managed binaries

What does this MR do?

Closes #8570 (closed).

  • update subcommand on glab duo cli and glab orbit. glab duo cli update used to be passed through to the Duo CLI binary, which rejected it. It now updates the managed binary, the same as --update, which keeps working. Neither binary has its own update command (checked against Duo CLI 9.26.0 and Orbit 0.136.0). Only the first positional word is matched, so glab duo cli run --goal update still passes through.
  • glab check-update reports managed binaries. When the Duo CLI or Orbit CLI is installed, an explicit glab check-update also prints available updates for it. The automatic 24-hour check doesn't, because each binary already checks when it runs. Binaries that aren't installed, or that come from a custom binary path, are skipped without a request. A managed binary below the spec's MinVersion is still reported, even though InstalledBinary counts it as not installed.
  • The update hint now reads Run 'glab duo cli update' (and glab orbit update).

Structure

  • The Duo CLI and Orbit specs move from their command packages to internal/binarymgr/binaries. The subcommands and check-update both need them, and importing the parent command packages would either cycle or break the layering rule. The spec tests move with them.
  • Spec gains a Command field, which replaces Runner.UpdateCommand.
  • Runner.ReportUpdate is the exported, unthrottled update check.
  • Two Cobra details: both parents now set Args: cobra.ArbitraryArgs, because legacyArgs rejects pass-through words once a command has children and no parent (as in tests). The Duo CLI help footer is now limited to glab duo cli, since subcommands inherit its help function.
  • binarymgr update notices now go to stderr, like glab's own check-update banner. They used to go to stdout, which also put the automatic notice into redirected glab duo cli and glab orbit output.

Also included

test(orbit): TestOrbitCredentialEnv_SkipsWhenUnauthenticated picked up a token from the developer's keyring and failed locally on main, which blocked pre-push. It now calls keyring.MockInit(), as auth/docker tests do.

Example output

From glab check-update with Duo CLI 9.6.0 and Orbit CLI 0.104.0 installed:

$ glab check-update
You are using the latest version of glab

• New GitLab Duo CLI version available: 9.6.0 → 9.27.0
Run 'glab duo cli update' to update to the latest version

• New Orbit CLI version available: 0.104.0 → 0.136.0
Run 'glab orbit update' to update to the latest version

How to test

glab check-update          # with an older Duo CLI installed, shows the Duo CLI update line
glab duo cli update
glab orbit update
glab duo cli --update      # still works

🤖 Generated with Claude Code

Edited by Kai Armstrong

Merge request reports

Loading
Loading