Skip to content

chore(setup): add SDK installer library - #750

Open
ffantl-ld wants to merge 2 commits into
ffantl/setup-ld/1-detectorfrom
ffantl/setup-ld/2-installer
Open

chore(setup): add SDK installer library#750
ffantl-ld wants to merge 2 commits into
ffantl/setup-ld/1-detectorfrom
ffantl/setup-ld/2-installer

Conversation

@ffantl-ld

@ffantl-ld ffantl-ld commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Describe the solution you've provided

Second layer of the guided setup command: the SDK installer. Given a detection result, installs the SDK via the project's package manager (Installer interface, PackageInstaller, InstallArgs, IsInstalled), and flags SDKs that require manual install.

Builds on the detection library (DetectResult).

Related issues

Part of the setup-ld feature. Stacked PR — base is ffantl/setup-ld/1-detector.

Requirements

  • I have added test coverage for new or changed functionality

Note

Medium Risk
Runs real package-manager commands in the user’s project directory (mutable dependency files), though behavior is bounded by SDK ID mapping and is covered by tests via a stubbed runner.

Overview
Adds the guided setup install layer: given a DetectResult, it installs the matching LaunchDarkly SDK via the project’s package manager (or reports that manual steps are required).

PackageInstaller implements Installer by resolving install commands with InstallArgs (Node npm/yarn/pnpm/bun, Python pip/poetry/uv/pipenv, go get, Ruby gem vs bundle add, dotnet add package) and running them in the target directory via an injectable run hook (defaults to exec). IsInstalled scans common manifests (package.json, go.mod, pyproject.toml, Gemfile, *.csproj, etc.) and skips the command when the dependency is already present.

Manual-install SDKs (Java, Android, Swift/iOS) return Success: false without error and a package coordinate for the wizard; unknown SDK IDs error instead of no-op. A StubInstaller remains for callers not wired yet. installer_test.go covers command selection, install/skip/failure paths, and manual/unknown behavior.

Reviewed by Cursor Bugbot for commit 1f13de3. Bugbot is set up for automated code reviews on this repo. Configure here.

@ffantl-ld
ffantl-ld marked this pull request as ready for review July 27, 2026 17:23
@ffantl-ld
ffantl-ld requested review from Vadman97 and erangeles July 27, 2026 17:23
Comment thread internal/setup/installer.go
Comment thread internal/setup/installer.go
Comment thread internal/setup/installer.go Outdated
@ffantl-ld
ffantl-ld requested review from a team and removed request for Vadman97 July 28, 2026 16:37
@ffantl-ld
ffantl-ld force-pushed the ffantl/setup-ld/2-installer branch from 536ddf1 to fb2c630 Compare July 31, 2026 17:47
func fileContains(path, substr string) bool {
b, err := os.ReadFile(path)
return err == nil && strings.Contains(string(b), substr)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Substring match skips SDK install

Medium Severity

IsInstalled treats any manifest substring match as proof the SDK is present. Related packages such as @launchdarkly/node-server-sdk-redis contain @launchdarkly/node-server-sdk as a prefix, so setup can skip installing the real SDK when only an integration package is listed.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fb2c630. Configure here.

return []string{"gem", "install", pkg}, pkg
case "dotnet-server-sdk":
pkg = "LaunchDarkly.ServerSdk"
return []string{"dotnet", "add", "package", pkg}, pkg

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dotnet install breaks on solutions

High Severity

Detection accepts a root .sln with no adjacent .csproj, but install always runs dotnet add package without a project path and only looks for *.csproj in the root. Typical solution layouts therefore fail install even though detection succeeds.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fb2c630. Configure here.

ffantl-ld and others added 2 commits July 31, 2026 14:24
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`gem install` left the Gemfile untouched, so the SDK stayed unavailable under
bundler and IsInstalled kept returning false. Use `bundle add` when the project
is Bundler-managed, and poetry, uv or pipenv when one of those manages the
Python dependencies.

Unrecognised package managers fall back to pip rather than being run as a
command, since the value reaches InstallArgs from the detector.

InstallArgs added launchdarkly-react-native-client-sdk, which npm marks
deprecated in favour of @launchdarkly/react-native-client-sdk. The unscoped
launchdarkly-js-client-sdk is the v3 package whose initialize API the init
template uses; the scoped one is v4 and exposes createClient.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ffantl-ld
ffantl-ld force-pushed the ffantl/setup-ld/2-installer branch from fb2c630 to 1f13de3 Compare July 31, 2026 18:25

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 using default effort and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

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.

Reviewed by Cursor Bugbot for commit 1f13de3. Configure here.

case "python-server-sdk":
manifests = []string{"requirements.txt", "pyproject.toml", "setup.py", "Pipfile", "uv.lock"}
case "ruby-server-sdk":
manifests = []string{"Gemfile", "Gemfile.lock"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Lockfiles fake installed status

Low Severity

IsInstalled treats go.sum, Gemfile.lock, and uv.lock as proof the SDK is a project dependency. Those lockfiles can retain package names after removal from go.mod / Gemfile / pyproject.toml, or list transitive-only hits, so setup can set AlreadyInstalled and skip adding a direct dependency the app still needs. Node correctly checks only package.json.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1f13de3. Configure here.

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.

2 participants