Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using spring does not work from subdirectories #644

Open
ccutrer opened this issue Apr 5, 2021 · 10 comments
Open

using spring does not work from subdirectories #644

ccutrer opened this issue Apr 5, 2021 · 10 comments

Comments

@ccutrer
Copy link
Contributor

ccutrer commented Apr 5, 2021

having a rails project with a spec directory:

spring rspec lib/acts_as_list_spec.rb
>> Spring was unable to find your config/application.rb file. Your project root was detected at /Users/cody/src/canvas-lms/spec, so Spring looked for /Users/cody/src/canvas-lms/spec/config/application.rb but it doesn't exist. You can configure the root of your application by setting Spring.application_root in config/spring.rb.

But non-springified works fine, properly searching the parent dir for the Gemfile, and then booting the app.

I've explored this quite a bit by monkey patching, and even if you can get the Spring client to boot via enough tricks, the server will still try to launch from the wrong directory and throw the same error. If you're sneaky and boot the server from the actual project root, and then run spring rspec from the spec directory, it will not have the some working directory, and just be confusing. It seems like the server needs to be directory aware - having the client pass its working directory through, and the server changing to that before running the command.

@ccutrer
Copy link
Contributor Author

ccutrer commented Apr 5, 2021

Note that getting this working would almost certainly open avenues for proper spring usage from the dummy app of an engine, or the reverse case - from within an engine embedded in a larger app, or the spring binstub being a symlink (again, from an engine embedded in a larger app)

@deivid-rodriguez
Copy link
Contributor

This could be the regression in 2.1.1. Can you try either the latest code in the master branch, or 2.1.0?

@JuPlutonic
Copy link

JuPlutonic commented Apr 7, 2021

Same error using spring (2.1.0):

spring rspec ...
/home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/soap4r-ruby1.9-2.0.5/lib/soap/mapping/encodedregistry.rb:150: warning: constant ::Fixnum is deprecated
/home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/soap4r-ruby1.9-2.0.5/lib/soap/mapping/encodedregistry.rb:216: warning: constant ::Fixnum is deprecated
/home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/application/configuration.rb:241:in `database_configuration': Cannot load database configuration:
Could not load database configuration. No such file - ["config/database.yml"] (RuntimeError)
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.6/lib/active_record/railtie.rb:200:in `block (2 levels) in '
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:71:in `class_eval'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:71:in `block in execute_hook'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:61:in `with_execution_control'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:66:in `execute_hook'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:43:in `block in on_load'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:42:in `each'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/lazy_load_hooks.rb:42:in `on_load'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.6/lib/active_record/railtie.rb:198:in `block in '
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:32:in `instance_exec'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:32:in `run'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:61:in `block in run_initializers'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:228:in `block in tsort_each'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:431:in `each_strongly_connected_component_from'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:349:in `block in each_strongly_connected_component'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `each'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `call'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:347:in `each_strongly_connected_component'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:226:in `tsort_each'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/2.6.0/tsort.rb:205:in `tsort_each'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/initializable.rb:60:in `run_initializers'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/application.rb:363:in `initialize!'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/railtie.rb:190:in `public_send'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/railties-6.0.3.6/lib/rails/railtie.rb:190:in `method_missing'
	from /home/X/canvas-lms/config/environment.rb:29:in `'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:324:in `require'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:324:in `block in require'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:291:in `load_dependency'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.6/lib/active_support/dependencies.rb:324:in `require'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:106:in `preload'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:157:in `serve'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:145:in `block in run'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:139:in `loop'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:139:in `run'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application/boot.rb:19:in `'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:85:in `require'
	from /home/X/dotfiles/common/.anyenv/envs/rbenv/versions/2.6.6/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_require.rb:85:in `require'
	from -e:1:in `'

@chriscz
Copy link

chriscz commented Apr 7, 2021

I ran a git bisect against spring (v2.0.0 to master) with a new rails 6.1 app but I was unable to find a good commit where the error message doesn't come up.

Here's the test code: https://github.com/chriscz/spring-nested-bug

@JuPlutonic
Copy link

I did installation of spring.2.1.1 master
And with it (pkg/spring-2.1.1.gem) inside canvas-lms application also got:
Could not load database configuration. No such file - ["config/database.yml"] (RuntimeError)

@deivid-rodriguez
Copy link
Contributor

Then that's not the culprit :(. The repro posted should be very helpful for anyone wanting to investigate the issue 👍.

@chriscz
Copy link

chriscz commented Apr 8, 2021

The bug is in the spring/configuration.rb code that uses gemfile which returns an absolute path to the Gemfile (at least in Bundler 2.2.14). Joining an absolute path with any other path always returns the absolute path and so the exists? check succeeds.

def find_project_root(current_dir)
if current_dir.join(gemfile).exist?
current_dir
elsif current_dir.root?
raise UnknownProject.new(Dir.pwd)
else
find_project_root(current_dir.parent)
end
end

I'm not entirely sure what the best fix would be, but maybe one of the following:

  1. checking whether the Gemfile is absolute and checking that config/application.rb exists and returning that directory?
    def find_project_root(current_dir)
      if gemfile.absolute? && gemfile.dirname.join('config/application.rb').exist?
        return gemfile.dirname
      end

      if current_dir.join(gemfile).exist?
        current_dir
      elsif current_dir.root?
        raise UnknownProject.new(Dir.pwd)
      else
        find_project_root(current_dir.parent)
      end
    end
  1. Otherwise we could try just walking up the current path to find the first one that defines config/application.rb?
    def find_project_root(current_dir)
      if current_dir.join('config/application.rb').exist?
        current_dir
      elsif current_dir.root?
        raise UnknownProject.new(Dir.pwd)
      else
        find_project_root(current_dir.parent)
      end
    end
  1. To support engines as well we could just walk up the tree and find the first directory that contains a Gemfile.lock
    def find_project_root(current_dir)
      if current_dir.join('Gemfile.lock').exist?
        current_dir
      elsif current_dir.root?
        raise UnknownProject.new(Dir.pwd)
      else
        find_project_root(current_dir.parent)
      end
    end

Any other ideas?

I can submit a PR if you are happy with any of these proposals.

@deivid-rodriguez
Copy link
Contributor

Just to make it clear, I don't maintain this repo. I just noticed this issue and thought the pointer to the regression in 2.1.1 could be helpful.

@JuPlutonic
Copy link

JuPlutonic commented Apr 8, 2021

@chriscz my coin: 3rd needs to be much more complex:

if current_dir.join('Gemfile.lock').exist? || current_dir.join('gems.locked').exist?

@chriscz
Copy link

chriscz commented Apr 9, 2021

Come to think of it, just looking for Gemfile + application config sounds like a good solution @JuPlutonic, should actually work for the dummy-app case as well.

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

No branches or pull requests

4 participants