Skip to content

feat(cli): add global --output persistent flag#740

Open
nvanthao wants to merge 9 commits into
mainfrom
gerard/sc-137132/global-output
Open

feat(cli): add global --output persistent flag#740
nvanthao wants to merge 9 commits into
mainfrom
gerard/sc-137132/global-output

Conversation

@nvanthao
Copy link
Copy Markdown
Member

@nvanthao nvanthao commented May 21, 2026

Summary

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.

Resolution Order

  1. Explicit --output flag on the command line
  2. REPLICATED_OUTPUT environment variable
  3. Default: "table"

Changes

Core Infrastructure

  • Added resolveOutputFormat() to runners with resolution order: explicit flag → env var → "table" default
  • Registered global persistent flag on root command
  • Wired resolution into preRunSetupAPIs and prerunCommand
  • Added Proxy: http.ProxyFromEnvironment to the platform HTTP client transport so the CLI now respects HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables

Command Refactoring

  • Migrated version command from --json bool flag to global --output (legacy --json preserved but deprecated)
  • Refactored 17 commands that declared local outputFormat variables to use r.outputFormat directly:
    • app (ls, create, rm, hostname ls)
    • customer (ls, create, inspect)
    • policy (ls, get, create, update)
    • default (show, set)
    • enterprise-portal (status get/update, invite, user ls)
  • Removed redundant local flags from ~50 commands already binding to r.outputFormat
  • Refactored notification.go — all 10 subcommands now use r.outputFormat
  • Refactored cluster addon commandscluster_addon_ls.go and cluster_addon_create_objectstore.go
  • Added JSON output support to previously table-only commands:
    • channel adoption — full JSON marshaling of ChannelAdoption struct
    • channel counts — full JSON marshaling of LicenseCounts struct
    • release promote — structured JSON output with channel, release_sequence, and version_label
    • release image lsprint.ChannelImages now supports JSON format
  • Added SilenceUsage: true to hidden commands channel adoption and channel counts

Clean Up

  • Removed clusterAddonCreateObjectStoreOutput from runnerArgs

Tests

  • Added cli/cmd/output_test.go with 3 unit tests verifying resolution priority
  • Added cli/print/channel_adoption_test.go (5 tests)
  • Added cli/print/channel_images_test.go (4 tests)
  • Added cli/print/channel_license_counts_test.go (5 tests)

Documentation

  • Added docs/plans/global-output-flag.md containing the full design and implementation plan

Exclusions (Intentionally Left Unchanged)

  • customer download-license --output — still a file path flag
  • login, logout, completion, config — no output formatting

Verification

  • go build ./... — zero errors
  • go test ./cli/cmd/... — all pass
  • Global --output appears in replicated --help
  • REPLICATED_OUTPUT=json works without explicit --output json
  • Explicit --output wide still overrides env var
  • customer download-license --output still works as a file path flag

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
@nvanthao nvanthao marked this pull request as draft May 21, 2026 06:40
Comment thread cli/cmd/root.go
Comment thread cli/cmd/root.go
@nvanthao nvanthao marked this pull request as ready for review May 22, 2026 02:21
Comment thread docs/plans/global-output-flag.md Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is likely accidentally committed, lets not commit it

Copy link
Copy Markdown
Member

@xavpaice xavpaice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 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,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is this related to the change? Just want to understand the reason, rather than remove the change.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 029b29e. Configure here.

@nvanthao
Copy link
Copy Markdown
Member Author

@xavpaice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants