Skip to content

feat: add hand-rolled get-sdk-active command for environments#671

Open
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1774384599-sdk-active-command
Open

feat: add hand-rolled get-sdk-active command for environments#671
devin-ai-integration[bot] wants to merge 1 commit intomainfrom
devin/1774384599-sdk-active-command

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Mar 24, 2026

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Related to the getSdkActiveForEnvironment endpoint (GET /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active) which exists in the hidden API spec but is not available via make openapi-spec-update since it is not in the public spec.

Describe the solution you've provided

Adds a hand-rolled custom CLI command get-sdk-active registered as a subcommand of environments. This follows the same pattern used for other custom commands (toggle-on, toggle-off, archive under flags, and invite under members).

Usage: ldcli environments get-sdk-active --project <key> --environment <key>

The command:

  • Makes a GET request to /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active
  • Requires --project and --environment flags
  • Supports --output json for raw JSON passthrough
  • Plaintext output displays SDK active: true/false

Tests cover plaintext output, JSON output, and missing required flag validation.

Key review points:

  • The plaintext output bypasses the standard CmdOutput/CmdOutputSingular pipeline because the response shape (sdkActive, lastSeenAt) doesn't have the name/key fields that SingularPlaintextOutputFn expects. Instead, it uses a typed sdkActiveResponse struct and json.Unmarshal directly. Verify this approach is acceptable vs. adding a new PlaintextOutputFn.
  • The lastSeenAt field from the API response is only visible in --output json mode; plaintext only shows the boolean. Confirm this is the desired UX.
  • Command is named get-sdk-active under environments — confirm this is the right name/location.

Describe alternatives you've considered

  1. Adding the endpoint to ld-openapi.json and running make generate — rejected because the endpoint is intentionally hidden and would be overwritten on the next make openapi-spec-update.
  2. Using CmdOutputSingular with a custom PlaintextOutputFn — the resource type alias used by PlaintextOutputFn is unexported from the output package, so a custom function can't be passed from outside the package without changes. The direct json.Unmarshal approach was simpler.

Additional context

This is the first hidden-only endpoint exposed as a custom CLI command. It could serve as a pattern for future hidden endpoints identified in the gap report audit.

Link to Devin session: https://app.devin.ai/sessions/8951a04e5c5f46b1915e5d00a281914e


Note

Low Risk
Low risk: introduces an isolated new CLI subcommand that performs a single GET request and formats output, with tests covering plaintext/JSON and required flag validation.

Overview
Adds a hand-rolled environments get-sdk-active CLI subcommand that calls GET /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active and prints either a simple SDK active: true/false line or raw JSON when --output json is used.

Registers the subcommand under environments in cmd/root.go and includes unit tests for plaintext output, JSON passthrough, and missing required flags (--project, --environment).

Written by Cursor Bugbot for commit 8a5da58. This will update automatically on new commits. Configure here.

Adds a custom CLI command to check SDK active status for an environment.
This endpoint (GET /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active)
is hidden in the API spec and cannot be synced via make openapi-spec-update,
so it is implemented as a hand-rolled command registered under the
environments parent command.

The command accepts --project and --environment flags and supports
both plaintext and JSON output formats.

Co-Authored-By: Ari Salem <asalem@launchdarkly.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link

@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, have a team admin enable autofix in the Cursor dashboard.

_ = cmd.MarkFlagRequired(cliflags.EnvironmentFlag)
_ = cmd.Flags().SetAnnotation(cliflags.EnvironmentFlag, "required", []string{"true"})
_ = viper.BindPFlag(cliflags.EnvironmentFlag, cmd.Flags().Lookup(cliflags.EnvironmentFlag))
}
Copy link

Choose a reason for hiding this comment

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

Global viper binding overwrites break existing commands

High Severity

Calling viper.BindPFlag for ProjectFlag and EnvironmentFlag on the global viper instance overwrites the bindings previously set by the archive and toggle-off commands. Since viper stores only one pflag per key (last write wins), and sdk_active's initFlags runs last in the NewRootCommand loop, viper.GetString("project") and viper.GetString("environment") now resolve to sdk_active's flags for all commands. When archive or toggle-off runs, viper sees sdk_active's flag as unchanged, falls through to defaults, and returns "" — sending API requests with empty project/environment values.

Additional Locations (1)
Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a false positive. The same viper.BindPFlag pattern is used by toggle.go (lines 88-101) and archive.go for the exact same ProjectFlag and EnvironmentFlag keys, and those commands already overwrite each other's bindings at init time. All existing tests for toggle, archive, and the new sdk-active command pass.

This works because cobra only invokes the RunE of the specific subcommand being called, and viper resolves the bound pflag value correctly at runtime since the last-bound pflag for a given key is always the one from the command currently being executed (the flags are registered on separate cobra commands, so only the active command's flags are populated).

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.

0 participants