pezra / rspec-mode

An RSpec minor mode for Emacs
257 stars 112 forks source link

Wrong Ruby version used during test invocation with Rbenv + ZSH + Spacemacs #166

Closed Dangeranger closed 7 years ago

Dangeranger commented 7 years ago

Problem:

When invoking rspec-verify-all from within any spec file using the keybinding CTRL+c , ,, a instead of using the Ruby binary version specified in the .ruby-version located at the project root, rspec-mode is invoking rspec with the default system ruby instead.

Expected behavior:

rspec-mode was expected to invoke rspec with the Ruby version installed via ruby-build at /Users/username/.rbenv/versions/2.2.3/bin/ruby.

Error message:

-*- mode: rspec-compilation; default-directory: "~/Dev/projects/some-project/" -*-
RSpec Compilation started at Tue Aug 29 11:52:40

bundle exec rspec --options /Users/username/Dev/projects/some-project/.rspec /Users/username/Dev/projects/some-project/spec
/Library/Ruby/Site/2.0.0/rubygems.rb:243:in `bin_path': can't find gem bundler (>= 0) (Gem::GemNotFoundException)
    from ./bin/bundle:3:in `<main>'

RSpec Compilation exited abnormally with code 1 at Tue Aug 29 11:52:40

Environment notes:

OS: MacOS Sierra 10.12.6 (16G29)
rbenv version: 1.0.0
ruby-build version: 20170726
emacs version: GNU Emacs 25.1.1 (x86_64-apple-darwin14.5.0, Carbon Version 157 AppKit 1348.17)
spacemacs version:   0.200.9@25.1.1 (spacemacs)

Thanks for your help 👍

dgutov commented 7 years ago

Try https://github.com/purcell/exec-path-from-shell, maybe.

This problem is probably not rspec-mode-specific.

Dangeranger commented 7 years ago

@dgutov Yeah maybe that's possible, I just invoked RSpec from within a Dired buffer by using shell-command with bin/rspecand received

/Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- bundler (LoadError)
    from /Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/username/Dev/projects/project/bin/spring:8:in `<top (required)>'
    from bin/rspec:3:in `load'
    from bin/rspec:3:in `<main>'
Dangeranger commented 7 years ago

Looks like that package is included within the base packages.

https://github.com/syl20bnr/spacemacs/blob/8e1af145480d53e8d32cdff2c83291889903164b/layers/+distributions/spacemacs-base/packages.el#L30

And the function is defined within the packages.el

(defun spacemacs-base/init-exec-path-from-shell ()
  (use-package exec-path-from-shell
    :init (when (or (spacemacs/system-is-mac)
                    (spacemacs/system-is-linux)
                    (memq window-system '(x)))
            (exec-path-from-shell-initialize))))
Dangeranger commented 7 years ago

Created new issue in Spacemacs https://github.com/syl20bnr/spacemacs/issues/9512

Dangeranger commented 7 years ago

@dgutov So I've checked the ruby version used by other packages, specifically inf-ruby-console-rails and found that when using the console from within Emacs, correct Ruby binary and versions are used. rspec-mode seems to be the only package NOT using the rbenv binaries.

For example, M-x ruby-switch-to-inf

Error message when starting an interactive ruby console session from Emacs. Console still starts anyway.

mapcar: Wrong type argument: stringp, ((path . "/Users/username/Dev/projects/project-name/lib"))

Resulting ruby version within the inf-ruby interactive session.

Running via Spring preloader in process 89593
Loading development environment (Rails 4.2.7.1)
[1] pry(main)> => "robe on 49355"
[2] pry(main)> RUBY_VERSION
=> "2.2.3"
[3] pry(main)> 

Results of checking the environment variables from within Emacs

// M-x getenv PATH

=> /Users/username/.rbenv/bin:/Users/username/.rbenv/shims:/Users/mansfield/.exenv/shims: ... rest of path follows

// M-x describe-variable exec-path 

=> exec-path is a variable defined in ‘C source code’.
Its value is
("/Users/username/.rbenv/bin" "/Users/username/.rbenv/shims" ... rest of path)

Original value was 
("/Users/username/.rbenv/bin" "/Users/username/.rbenv/shims" ... rest of path)

  This variable may be risky if used as a file-local variable.

Documentation:
List of directories to search programs to run in subprocesses.
Each element is a string (directory name) or nil (try default directory).

By default the last element of this list is ‘exec-directory’. The
last element is not always used, for example in shell completion
(‘shell-dynamic-complete-command’).

You can customize this variable.
Dangeranger commented 7 years ago

Found a fix, solution below:

Solution:

Within my .zshrc I had initialized rbenv with

# Within ~/.zshrc

# Setup rbenv shims, completion, and path
eval "$(rbenv init -)"

After moving this into my ~/.zshenv instead, restarting my shell, and restarting Spacemacs, rspec-mode found the correct Ruby version managed by rbenv and invoked the tests as expected.

# Within ~/.zshenv

## Default PATH foundation
PATH=/usr/local/bin:/usr/local/sbin:...lots-more-dirs-here...$PATH;
export PATH

# Setup rbenv shims, completion, and path
eval "$(rbenv init -)"
dgutov commented 7 years ago

Ouch, zsh.

I just put the rbenv config into ~/.profile. On Ubuntu, that is.

Dangeranger commented 7 years ago

It's my fault for not paying attention to how Emacs invokes your environment as it boots. The strange part is that non of the other packages exhibit this problem. 🤷‍♂️

dgutov commented 7 years ago

If we're talking about inf-ruby, then Spring might be calling the shell, and perform initialization doing that... IDK.