-
Notifications
You must be signed in to change notification settings - Fork 248
Failure to recognize custom Gemfile during initial bundler setup #4043
Description
Description
Ruby LSP Information
VS Code Version
1.105.1
Ruby LSP Extension Version
0.10.2
Ruby LSP Server Version
0.26.9
Ruby LSP Add-ons
- Standard Ruby (unknown)
- Ruby LSP Rails (0.4.8)
Ruby Version
3.3.10
Ruby Version Manager
rbenv
Installed Extensions
Click to expand
- catppuccin-vsc (3.18.1)
- catppuccin-vsc-icons (1.26.0)
- ruby-lsp (0.10.2)
- scala (0.5.9)
- terraform (2.39.2)
- theme-dracula (2.25.1)
- vscode-kubernetes-tools (1.3.26)
- vscode-yaml (1.21.0)
Ruby LSP Settings
Click to expand
Workspace
{
"rubyVersionManager": {
"identifier": "rbenv",
"rbenvExecutablePath": "/opt/homebrew/bin/rbenv"
}
}User
{
"enabledFeatures": {
"codeActions": true,
"diagnostics": true,
"documentHighlights": true,
"documentLink": true,
"documentSymbols": true,
"foldingRanges": true,
"formatting": true,
"hover": true,
"inlayHint": true,
"onTypeFormatting": true,
"selectionRanges": true,
"semanticHighlighting": true,
"completion": true,
"codeLens": false,
"definition": true,
"workspaceSymbol": true,
"signatureHelp": true,
"typeHierarchy": true
},
"featuresConfiguration": {},
"addonSettings": {},
"rubyVersionManager": {
"identifier": "rbenv",
"rbenvExecutablePath": "/opt/homebrew/bin/rbenv"
},
"customRubyCommand": "",
"formatter": "auto",
"linters": null,
"bundleGemfile": "",
"testTimeout": 30,
"pullDiagnosticsOn": "both",
"useBundlerCompose": false,
"bypassTypechecker": false,
"rubyExecutablePath": "",
"indexing": {},
"erbSupport": true,
"featureFlags": {},
"sigOpacityLevel": "1"
}Background
I'm working in a legacy enterprise Ruby on Rails application with a fairly unusual Bunder setup that requires us to use a custom BUNDLE_GEMFILE, and this is causing some trouble when first bootstrapping the Ruby LSP plugin in my editor. This is my first time diving into this plugin so will certainly consider the possibility of user error here, so wanted to start with an issue to discuss!
Basically, our repository has a Gemfile/Gemfile.lock, but they are not used for Ruby/Rails development (they are relics for some old scripts). Instead of those, we have a different set of explicitly named Gemfiles like:
Gemfile.ruby33.rails42/Gemfile.ruby33.rails42.lockGemfile.ruby4.rails5/Gemfile.ruby4.rails5.lock
For local development, in the project's .bundle/config, we set a gemfile override depending on which versions we want to use, eg:
# .bundle/config
BUNDLE_GEMFILE: "Gemfile.ruby4.rails5"
When the Ruby LSP gem starts for the first time, it runs without bundler or a BUNDLE_GEMFILE env variable set. As such, this code in lib/ruby_lsp/setup_bundler.rb does not account for special configuration set in the .bundle/config and will always use Gemfile/Gemfile.lock:
# Regular bundle paths
@gemfile = begin
Bundler.default_gemfile
rescue Bundler::GemfileNotFound
nil
end #: Pathname?
@lockfile = @gemfile ? Bundler.default_lockfile : nil #: Pathname?
So, for our codebase, things fall apart and the incorrect configuration is used during initial setup.
Potential solution
I was able to address this issue for myself with this patch, but I didn't want to immediately jump to a PR since I'm not sure I've thought through this well enough yet:
diff --git a/lib/ruby_lsp/setup_bundler.rb b/lib/ruby_lsp/setup_bundler.rb
--- a/lib/ruby_lsp/setup_bundler.rb
+++ b/lib/ruby_lsp/setup_bundler.rb
@@
def initialize(project_path, **options)
@project_path = project_path
@launcher = options[:launcher] #: bool?
@beta = options[:beta] #: bool?
force_output_to_stderr! if @launcher
- # Regular bundle paths
- @gemfile = begin
- Bundler.default_gemfile
- rescue Bundler::GemfileNotFound
- nil
- end #: Pathname?
- @lockfile = @gemfile ? Bundler.default_lockfile : nil #: Pathname?
+ gemfile, lockfile = project_gemfile_names
+ @gemfile = gemfile #: Pathname?
+ @lockfile = lockfile #: Pathname?
@gemfile_hash = @gemfile ? Digest::SHA256.hexdigest(@gemfile.read) : nil #: String?
@lockfile_hash = @lockfile&.exist? ? Digest::SHA256.hexdigest(@lockfile.read) : nil #: String?
@@
private
+ #: -> [String, String]
+ def project_gemfile_names
+ configured_gemfile = bundler_settings_as_env["BUNDLE_GEMFILE"]
+ original_bundle_gemfile = ENV["BUNDLE_GEMFILE"]
+
+ if configured_gemfile && !configured_gemfile.empty?
+ ENV["BUNDLE_GEMFILE"] = File.expand_path(configured_gemfile, @project_path)
+ end
+
+ begin
+ [Bundler.default_gemfile, Bundler.default_lockfile]
+ rescue Bundler::GemfileNotFound
+ [nil, nil]
+ end
+ ensure
+ ENV["BUNDLE_GEMFILE"] = original_bundle_gemfile
+ end
+
#: -> Hash[String, untyped]
def composed_bundle_dependencies
@composed_bundle_dependencies ||= begin
original_bundle_gemfile = ENV["BUNDLE_GEMFILE"]
Reproduction steps
- Start the Ruby LSP in Cursor
- Bundler setup falls back to
GemfileandGemfile.lockin spite ofBUNDLE_GEMFILEoverride specifying a different Gemfile bundle installetc attempt to run based on the incorrect Gemfile and it fails