check / check (push) Failing after 1s
A failed command printed the whole usage text after its error, burying it. The root command's PersistentPreRunE now turns usage off, so an error from running the command is printed once on its own. Wrong arity, an unknown flag, a bad flag value, a missing required flag and broken flag groups still get usage: cobra checks arguments and flag values before that hook but required flags and flag groups only after it, so the hook checks those two first. Root SilenceUsage was not used: in this cobra version it hides usage for argument and flag errors too. Cobra still prints the error; Entry is unchanged. Model: opus-5-5
97 lines
2.7 KiB
Go
97 lines
2.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"os"
|
|
|
|
"git.eeqj.de/sneak/secret/internal/secret"
|
|
"github.com/awnumar/memguard"
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/sys/unix"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
// Entry runs the secret CLI and returns the process exit code. It wipes
|
|
// every memguard buffer before it returns, so the caller must do nothing
|
|
// but exit with the code.
|
|
func Entry() int {
|
|
// On SIGINT or SIGTERM memguard runs this function, wipes every buffer
|
|
// and exits with status 1. The passphrase prompt turns terminal echo
|
|
// off until the read finishes, so a signal there would leave echo off.
|
|
// Only a process in the terminal's foreground process group may reset
|
|
// it: one in the background that tries is stopped instead of exiting.
|
|
terminalState, terminalErr := term.GetState(unix.Stdin)
|
|
|
|
memguard.CatchSignal(func(os.Signal) {
|
|
foreground, err := unix.IoctlGetInt(unix.Stdin, unix.TIOCGPGRP)
|
|
if terminalErr == nil && err == nil && foreground == unix.Getpgrp() {
|
|
_ = term.Restore(unix.Stdin, terminalState)
|
|
}
|
|
}, os.Interrupt, unix.SIGTERM)
|
|
|
|
defer memguard.Purge()
|
|
|
|
err := newRootCmd().Execute()
|
|
if err != nil {
|
|
return 1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func newRootCmd() *cobra.Command {
|
|
secret.Debug("newRootCmd starting")
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "secret",
|
|
Short: "A simple secrets manager",
|
|
Long: `A simple secrets manager to store and retrieve sensitive ` +
|
|
`information securely.`,
|
|
// Cobra prints the error a command returns; Entry does not.
|
|
SilenceErrors: false,
|
|
// Usage belongs only to a command called wrongly. Cobra has
|
|
// checked its arguments and flag values before this runs, but
|
|
// checks required flags (ValidateRequiredFlags) and flag groups
|
|
// (ValidateFlagGroups) only after it, so both are checked here
|
|
// to keep usage for them. An error after that comes from running
|
|
// the command, and usage would only bury it. A subcommand that
|
|
// sets its own PersistentPreRun replaces this one.
|
|
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
|
err := cmd.ValidateRequiredFlags()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cmd.ValidateFlagGroups()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd.SilenceUsage = true
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
secret.Debug("Adding subcommands to root command")
|
|
// Add subcommands
|
|
cmd.AddCommand(NewInitCmd())
|
|
cmd.AddCommand(newGenerateCmd())
|
|
cmd.AddCommand(newVaultCmd())
|
|
cmd.AddCommand(newAddCmd())
|
|
cmd.AddCommand(newGetCmd())
|
|
cmd.AddCommand(newListCmd())
|
|
cmd.AddCommand(newRemoveCmd())
|
|
cmd.AddCommand(newMoveCmd())
|
|
cmd.AddCommand(newUnlockerCmd())
|
|
cmd.AddCommand(newImportCmd())
|
|
cmd.AddCommand(newEncryptCmd())
|
|
cmd.AddCommand(newDecryptCmd())
|
|
cmd.AddCommand(newVersionCmd())
|
|
cmd.AddCommand(newInfoCmd())
|
|
cmd.AddCommand(newCompletionCmd())
|
|
|
|
secret.Debug("newRootCmd completed")
|
|
|
|
return cmd
|
|
}
|