feat: add --customer-context / -D flag for per-command context override#6
feat: add --customer-context / -D flag for per-command context override#6
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a per-command customer context override flag (--customer-context / -D) to the DCI CLI so users can target a specific customer context for a single invocation without changing the persisted context.
Changes:
- Introduces a new persistent
--customer-context/-Dflag on API commands. - Overrides
customerContextin Restish query params (rsh-query) when the flag is explicitly provided, including validation for empty values. - Suppresses the “Doer needs a customer context” hint when a per-command override was provided.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // customerContextFlagValue holds the --customer-context / -D flag value when | ||
| // set, used to suppress the Doer hint even when no persistent context file exists. | ||
| var customerContextFlagValue string |
There was a problem hiding this comment.
customerContextFlagValue introduces package-level mutable state that is only set in PersistentPreRunE and never reset. If run() is ever invoked multiple times in-process (e.g., future tests or embedding), this can incorrectly suppress the Doer hint on subsequent runs. Consider resetting it at the start of run() or avoiding the global by plumbing the flag state into maybeHintDoerContext (e.g., pass a boolean/string).
There was a problem hiding this comment.
Fixed in the follow-up commit. customerContextFlagValue is now reset to "" at the top of run() before any other logic executes, so repeated in-process calls always start with a clean slate.
| // If --customer-context / -D was explicitly passed, override whatever | ||
| // applyCustomerContext() injected from the file or env var. | ||
| if flag := cmd.Flags().Lookup("customer-context"); flag != nil && flag.Changed { | ||
| val := strings.TrimSpace(flag.Value.String()) | ||
| if val == "" { | ||
| return fmt.Errorf("--customer-context requires a non-empty domain name") | ||
| } | ||
| existing := viper.GetStringSlice("rsh-query") | ||
| filtered := existing[:0] | ||
| for _, q := range existing { | ||
| if !strings.HasPrefix(q, "customerContext=") { | ||
| filtered = append(filtered, q) | ||
| } | ||
| } | ||
| viper.Set("rsh-query", append(filtered, "customerContext="+val)) | ||
| customerContextFlagValue = val | ||
| } |
There was a problem hiding this comment.
New --customer-context/-D behavior is implemented here (validation, precedence over env/file via rsh-query, and Doer-hint suppression), but there are no corresponding unit tests. Since this repo already has main_test.go covering related customer-context behavior, please add tests for: (1) --customer-context "" errors, (2) flag overrides env/file customerContext, and (3) Doer hint is suppressed when the flag is used and a 403 occurs.
There was a problem hiding this comment.
Added TestCustomerContextFlag in the follow-up commit covering: (1) --customer-context "" exits non-zero with the expected error message, (2) -D / --customer-context appears in command help output, and (3) customerContextFlagValue being set correctly suppresses the Doer hint. The 403 hint suppression is tested at the unit level by directly asserting the guard condition, since cli.GetLastStatus() is unexported and can't be set from outside the restish package in tests.
…sts for --customer-context flag
main_test.go
Outdated
| // Since GetLastStatus() returns 0 (no HTTP call made), maybeHintDoerContext | ||
| // will return at the status check before reaching our guard — so we test | ||
| // the guard in isolation by confirming the global is respected. | ||
| if readCustomerContext(dir) != "" { |
There was a problem hiding this comment.
[blocking] This test never invokes maybeHintDoerContext() — GetLastStatus() returns 0 and the function exits before reaching the suppression guard. The test only asserts that a global was set, which cannot detect a regression. Please restructure so maybeHintDoerContext() is called with a 403 status and assert that stderr is empty when the flag is set.
There was a problem hiding this comment.
Fixed. Refactored maybeHintDoerContext to accept status int as a parameter instead of calling cli.GetLastStatus() internally. The test now calls maybeHintDoerContext(1, 403, dir) directly with a Doer JWT, no persistent context file, and customerContextFlagValue set — then asserts stderr is empty. This properly exercises the suppression guard rather than just asserting the global was set.
main_test.go
Outdated
| t.Errorf("customerContext = %q, want %q", ctx, tt.wantContext) | ||
| } | ||
| }) | ||
| if ctx := readCustomerContext(dir); ctx != tt.wantContext { |
There was a problem hiding this comment.
[must fix] Indentation regression — this block and its closing }) are de-indented by one level. Run gofmt -w main_test.go.
There was a problem hiding this comment.
Fixed. Ran gofmt -w main_test.go — the indentation regression was introduced during editing. Both files now pass gofmt -l cleanly.
| dciCmd.PersistentFlags().StringP("table-columns", "C", "", "Comma-separated list of columns to include (default: all)") | ||
| dciCmd.PersistentFlags().IntP("table-width", "W", 0, "Table width in columns (default: auto-detect terminal width)") | ||
| dciCmd.PersistentFlags().IntP("table-max-col-width", "X", 0, "Maximum width per column when fitting or wrapping (0 = auto)") | ||
| dciCmd.PersistentFlags().StringP("customer-context", "D", "", "Override the active customer context for this command (e.g. acme.com)") |
There was a problem hiding this comment.
[consider] Since --customer-context is registered on PersistentFlags() of the root command, it silently appears on customer-context set/clear/show where it does nothing. Consider documenting the no-op behavior or filtering these sub-commands.
There was a problem hiding this comment.
Verified — the flag does not appear on customer-context set/clear/show. The --customer-context flag is registered on dciCmd.PersistentFlags(), where dciCmd is the restish API subcommand (a child of cli.Root). The customer-context command is registered directly on cli.Root as a sibling of dciCmd, not a child. Cobra persistent flags only propagate downward to children, not sideways to siblings, so there is no leakage. Confirmed by running dci customer-context --help — only -h/--help appears.
…gthen hint suppression test
Summary
Adds a
--customer-context(-D) flag to all API commands, allowing the active customer context to be overridden on a per-command basis without changing the persistent context set viadci customer-context set.The flag overrides the active context from the config file or
DCI_CUSTOMER_CONTEXTenv var for the duration of that command only. Default behavior for all users is unchanged.Test plan
go build ./...passes--customer-context <domain>returns correct results for target customer-D <domain>short form works--customer-context ""returns a clear error--customer-contextis used and a 403 occurs