feat(cli): add global --output persistent flag#740
Conversation
Introduce a global --output (-o) persistent flag on the root command that all subcommands inherit, replacing ~78 local --output flag registrations. Also adds support for a new REPLICATED_OUTPUT environment variable for setting a default output format. Key changes: - Added resolveOutputFormat() with resolution order: explicit flag, REPLICATED_OUTPUT env var, then 'table' default - Migrated version command from --json bool to global --output - Refactored 17 commands that used local outputFormat variables - Removed redundant local --output flag registrations from ~50 commands - Added unit tests for output format resolution - Cleaned up runnerArgs by removing clusterAddonCreateObjectStoreOutput
- add JSON output for release promote - hide usage text for channel adoption and counts
There was a problem hiding this comment.
this file is likely accidentally committed, lets not commit it
There was a problem hiding this comment.
- Clean consolidation of output formatting logic. Using r.outputFormat everywhere and resolving it via resolveOutputFormat() in the two persistent pre-run hooks is the right approach.
- Explicit flag correctly wins over env var, and env var correctly wins over default. Tests cover this.
- JSON support added for channel adoption, channel counts, release image ls, and release promote is consistent with the rest of the CLI.
- version --json deprecation path is handled gracefully.
- Good test coverage for the new print functions.
Issues
cli/cmd/network_update.go:51 still registers its own local --output flag:
cmd.Flags().StringVar(&r.outputFormat, "output", "table", "The output format to use. One of: json|table|wide"), was this one missed?
cli/cmd/customer_download_license.go:42 uses -o / --output for a file path:
cmd.Flags().StringVarP(&output, "output", "o", "-", "Path to output license to. Defaults to stdout")
The local flag shadows the global format flag, so the command still works for its intended purpose. However, this means --output json on this command writes the license to a file literally named json instead of formatting as JSON. Rather than change the command in this PR, let's open a followup issue for this inconsistency. We don't want to make a breaking change here, but a future PR could add a --output-file or --path for the file output and consider if the json output is useful for this command.
I haven't yet run each command to test the look of the json output. When we discuss 'wire format' in the Shortcut, are we suggesting that the entire API json response should be posted? Is that huge and problematic, or deliberate?
| // This is a singleton that's reused for all requests to avoid leaking connections. | ||
| var httpClient = &http.Client{ | ||
| Transport: &http.Transport{ | ||
| Proxy: http.ProxyFromEnvironment, |
There was a problem hiding this comment.
nit: is this related to the change? Just want to understand the reason, rather than remove the change.
There was a problem hiding this comment.
I saw this during testing the changes, the CLI currently not respecting HTTP proxy env vars (HTTP_PROXY, HTTPS_PROXY, NO_PROXY), adding this here so that the CLI will respect the proxy settings.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 029b29e. Configure here.
| log := logger.NewLogger(r.w).SetIsTerminal(r.stdoutIsTTY) | ||
| if r.outputFormat == "json" { | ||
| log.Silence() | ||
| } |
There was a problem hiding this comment.
JSON promote hides airgap errors
Medium Severity
When release promote runs with JSON output (including via REPLICATED_OUTPUT) and --wait-for-airgap, the waiter logger is silenced before waitForAirgapBuilds. Per-channel failure and warning text only goes through that logger, so users get a generic error without the detailed airgap status that table mode still shows.
Reviewed by Cursor Bugbot for commit 029b29e. Configure here.
|


Summary
Introduce a global
--output(-o) persistent flag on the root command that all subcommands inherit, replacing ~78 local--outputflag registrations. Also adds support for a newREPLICATED_OUTPUTenvironment variable for setting a default output format.Resolution Order
--outputflag on the command lineREPLICATED_OUTPUTenvironment variable"table"Changes
Core Infrastructure
resolveOutputFormat()to runners with resolution order: explicit flag → env var → "table" defaultpreRunSetupAPIsandprerunCommandProxy: http.ProxyFromEnvironmentto the platform HTTP client transport so the CLI now respectsHTTP_PROXY,HTTPS_PROXY, andNO_PROXYenvironment variablesCommand Refactoring
versioncommand from--jsonbool flag to global--output(legacy--jsonpreserved but deprecated)outputFormatvariables to user.outputFormatdirectly:r.outputFormatr.outputFormatcluster_addon_ls.goandcluster_addon_create_objectstore.gochannel adoption— full JSON marshaling ofChannelAdoptionstructchannel counts— full JSON marshaling ofLicenseCountsstructrelease promote— structured JSON output withchannel,release_sequence, andversion_labelrelease image ls—print.ChannelImagesnow supports JSON formatSilenceUsage: trueto hidden commandschannel adoptionandchannel countsClean Up
clusterAddonCreateObjectStoreOutputfromrunnerArgsTests
cli/cmd/output_test.gowith 3 unit tests verifying resolution prioritycli/print/channel_adoption_test.go(5 tests)cli/print/channel_images_test.go(4 tests)cli/print/channel_license_counts_test.go(5 tests)Documentation
docs/plans/global-output-flag.mdcontaining the full design and implementation planExclusions (Intentionally Left Unchanged)
customer download-license --output— still a file path flaglogin,logout,completion,config— no output formattingVerification
go build ./...— zero errorsgo test ./cli/cmd/...— all pass--outputappears inreplicated --helpREPLICATED_OUTPUT=jsonworks without explicit--output json--output widestill overrides env varcustomer download-license --outputstill works as a file path flag