Documentation
¶
Overview ¶
Package cobracmd provides a ready-made update command for CLIs built with cobra.
It is a separate package so that importing goselfupdate does not impose a CLI framework on projects using flag, urfave/cli or anything else.
root.AddCommand(cobracmd.New(goselfupdate.Config{
Owner: "datapointchris",
Repo: "todoui",
Binary: "todoui",
Version: version,
}))
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrReported = errors.New("already reported")
ErrReported wraps every error New's command returns, marking it as already written to stderr. A program whose main prints the error returned by Execute should skip anything matching this, otherwise the failure is reported twice:
if err := root.Execute(); err != nil {
if !errors.Is(err, cobracmd.ErrReported) {
fmt.Fprintln(os.Stderr, "error:", err)
}
os.Exit(1)
}
Cobra's own error printing is already suppressed on the command.
var ErrUsage = errors.New("usage error")
ErrUsage marks a failure caused by how the command was typed rather than by the command running and failing: an unknown or malformed flag, or an unknown subcommand. Select exit code 2 for it, as the shell convention and Python's argparse do, so a caller can tell "you typed it wrong" from "it ran and failed" -- only the former is worth retrying with different arguments.
Cobra reports both as ordinary errors, which is what flattens every failure to exit 1 without this.
Argument-count and custom cobra.Command.Args validation failures are not classified: cobra returns them as plain errors indistinguishable from a RunE failure without matching on message text, which callers must never have to do.
Functions ¶
func Execute ¶ added in v0.3.0
Execute runs root with an update check racing alongside it.
The check starts before the command and the notice prints after it, so a fast command pays nothing and the line is not buried in the command's output. This is gh's shape, and it is the reason there is no blocking mode.
func main() {
if err := cobracmd.Execute(context.Background(), rootCmd, autoConfig()); err != nil {
if !errors.Is(err, cobracmd.ErrReported) {
fmt.Fprintln(os.Stderr, err)
}
if errors.Is(err, cobracmd.ErrUsage) {
os.Exit(2)
}
os.Exit(1)
}
}
Deliberately not a PersistentPreRun: cobra runs only the *closest* PersistentPreRunE in the ancestry, so a hook here would work for a root that has none and silently do nothing for one that does.
func New ¶
func New(cfg goselfupdate.Config, options ...Options) *cobra.Command
New returns an update command for cfg.
func UsageError ¶ added in v0.7.0
UsageError marks err as ErrUsage so Execute's caller selects exit code 2 for it, leaving the message alone.
For the mistakes this package cannot detect on its own: an argument-count or custom cobra.Command.Args failure, which cobra returns indistinguishably from a RunE failure, and a required-flag or mutually-exclusive-flag rule a command validates itself.
Args: func(cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return cobracmd.UsageError(fmt.Errorf("unknown command %q", args[0]))
}
return nil
},
Without this a consumer has to declare its own marker type to say the same thing, which is how four CLIs here ended up with four copies of it.
Types ¶
type Options ¶
type Options struct {
// Use overrides the command name. Defaults to "update".
//
// There is deliberately no alias knob. `update` is the fleet's one
// self-update verb, and an alias is what let `upgrade` coexist with it
// across every CLI without anyone choosing it.
Use string
// Changelog prints the commits between the two versions after a
// successful update. Enabled by default; it costs one extra request and is
// skipped silently when the source cannot produce one.
SkipChangelog bool
}
Options adjusts the generated command.