emyl / vagrant-triggers

Allow the definition of arbitrary scripts that will run on the host before and/or after Vagrant commands.
MIT License
546 stars 35 forks source link

Use Bundler.with_clean_env to remove bundler artefacts from environment. #25

Closed jperville closed 9 years ago

jperville commented 10 years ago

Summary

I am running into bundler issues trying to run local rake tasks from a vagrant trigger (eg. run "bundle exec rake -T"). The symptoms are that the bundler won't load because of missing dependencies. The reason is that bundler is trying to look for the bundle somewhere in /opt/vagrant rather than in the current directory.

How to reproduce

Have a trigger like this in Vagrantfile:

 config.trigger.before [:up, :reload, :destroy], :stdout => true do
    run "bundle exec rake -T"
  end

And a project that use bundler and has some dependencies that are not Vagrant's dependencies (eg. a typical rails project).

Try to run the trigger : vagrant destroy (safe to use if the VM is not created yet).

Fail with this kind of backtrace:

==> default: Executing command "bundle exec rake -T"...
The command "bundle exec rake -T" returned a failed exit code. The
error output is shown below:

/opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/spec_set.rb:92:in `block in materialize': Could not find builder-3.2.2 in any of the sources (Bundler::GemNotFound)
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/spec_set.rb:85:in `map!'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/spec_set.rb:85:in `materialize'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/definition.rb:133:in `specs'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/definition.rb:178:in `specs_for'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/definition.rb:167:in `requested_specs'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/environment.rb:18:in `requested_specs'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/runtime.rb:13:in `setup'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler.rb:120:in `setup'
    from /opt/vagrant/embedded/gems/gems/bundler-1.6.6/lib/bundler/setup.rb:17:in `<top (required)>'
    from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'

Even if the builder gem is present in my own bundle:

$ bundle list | grep builder
  * builder (3.2.2)

The fix

Use Bundler.with_clean_env to remove bundler-related environment variable before executing the subcommand.

In this PR I have left the env customizations (such as append_to_path) but removed everything bundler-related (such as removal of GEMRC, GEM_PATH etc). I have adapted the tests to match the new code.

After the fix:

$ vagrant destroy
==> default: Running triggers before destroy...
==> default: Executing command "env NORAILS=1 bundle exec rake -T"...
==> default: Command output:
==> default: ---------------
==> default: rake deploy:prod             # Deploy the application on Production
==> default: rake deploy:staging          # Deploy the application on Staging
==> default: rake docker:build            # Builds a docker image from current directory
==> default: rake docker:check            # Ensures that docker image can be built
==> default: rake docker:pre-build        # Runs pre-build script to prepare files that go in the image
==> default: rake docker:promote:prod     # Pushes the published docker image to the prod repository
==> default: rake docker:promote:staging  # Pushes the published docker image to the staging repository
==> default: rake docker:publish          # Publishes the docker image to the local (dev) repository
==> default: 
==> default: ---------------
==> default: The container hasn't been created yet.
jperville commented 10 years ago

Dear @emyl any chance to get this PR in? It would make my Vagrantfiles a lot more efficient ! Thank you very much.

emyl commented 9 years ago

Thanks!