Summary
The "new release available" version-check banner is emitted via logrus.Infof to stdout, and the check runs in rootCmd.PersistentPostRun, which executes after every subcommand — including completion. As a result, when shell completions are generated (e.g. updatecli completion bash), the banner is captured into the completion script itself, producing an invalid file that breaks the user's shell on startup.
This is especially impactful for the Homebrew formula, which generates completions at install time. End users get a broken bash completion file and a syntax error on every new shell.
Version
updatecli v0.117.1 (latest release at time of writing)
- Reproduced via the Homebrew-generated completion; the relevant code on
main is unchanged.
Steps to reproduce
$ updatecli completion bash > updatecli.bash
$ tail -n 3 updatecli.bash
# ex: ts=4 sw=4 et filetype=sh
| A new release is available: "unknown" -> "v0.117.0"
| More information on https://www.updatecli.io/changelogs/updatecli/changelogs/v0.117.0/
$ bash -n updatecli.bash
updatecli.bash: line 427: syntax error near unexpected token `|'
When this file is installed as a bash completion (e.g. under /opt/homebrew/etc/bash_completion.d/), every new shell prints:
bash: /opt/homebrew/etc/bash_completion.d/updatecli: line 427: syntax error near unexpected token `|'
bash: /opt/homebrew/etc/bash_completion.d/updatecli: line 427: `| A new release is available: "unknown" -> "v0.117.0"'
Root cause
cmd/root.go calls logrus.SetOutput(os.Stdout), so info-level logs (including the version banner) go to stdout rather than stderr.
- The version check is wired into
rootCmd.PersistentPostRun, so it runs for all subcommands, including completion / __complete / docs / man:
rootCmd.PersistentPostRun = func(cmd *cobra.Command, args []string) {
err := engine.CheckLatestPublishedVersion()
...
}
CheckLatestPublishedVersion() in pkg/core/engine/version.go emits the banner with logrus.Infof("| A new release is available..."), which therefore lands on stdout and is captured by any command that redirects stdout (such as completion/doc generation).
Suggested fixes (any one, ideally a combination)
- Route the banner to stderr. Informational/diagnostic output should not pollute stdout, which is reserved for the command's actual output (the completion script, generated docs, etc.).
- Skip the version check for non-interactive/generator commands in
PersistentPostRun — e.g. completion, __complete, __completeNoDesc, docs, man, jsonschema.
- Add an opt-out env var / flag, e.g.
UPDATECLI_DISABLE_VERSION_CHECK (mirroring the existing UPDATECLI_DISABLE_CHANGELOG), so it can be disabled in CI and by packagers.
Impact / workarounds
- Affects anyone generating completions or docs from a release binary; Homebrew users hit it automatically.
- Current workaround is to strip the banner from generated output, e.g.
updatecli completion bash | sed '/^| /d', or manually delete the trailing | ... lines from the installed completion file. This does not survive package upgrades.
Happy to open a PR if a preferred direction is confirmed.
Summary
The "new release available" version-check banner is emitted via
logrus.Infofto stdout, and the check runs inrootCmd.PersistentPostRun, which executes after every subcommand — includingcompletion. As a result, when shell completions are generated (e.g.updatecli completion bash), the banner is captured into the completion script itself, producing an invalid file that breaks the user's shell on startup.This is especially impactful for the Homebrew formula, which generates completions at install time. End users get a broken bash completion file and a syntax error on every new shell.
Version
updatecliv0.117.1 (latest release at time of writing)mainis unchanged.Steps to reproduce
When this file is installed as a bash completion (e.g. under
/opt/homebrew/etc/bash_completion.d/), every new shell prints:Root cause
cmd/root.gocallslogrus.SetOutput(os.Stdout), so info-level logs (including the version banner) go to stdout rather than stderr.rootCmd.PersistentPostRun, so it runs for all subcommands, includingcompletion/__complete/docs/man:CheckLatestPublishedVersion()inpkg/core/engine/version.goemits the banner withlogrus.Infof("| A new release is available..."), which therefore lands on stdout and is captured by any command that redirects stdout (such as completion/doc generation).Suggested fixes (any one, ideally a combination)
PersistentPostRun— e.g.completion,__complete,__completeNoDesc,docs,man,jsonschema.UPDATECLI_DISABLE_VERSION_CHECK(mirroring the existingUPDATECLI_DISABLE_CHANGELOG), so it can be disabled in CI and by packagers.Impact / workarounds
updatecli completion bash | sed '/^| /d', or manually delete the trailing| ...lines from the installed completion file. This does not survive package upgrades.Happy to open a PR if a preferred direction is confirmed.