Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

RubyGems post-install hook not triggering #5429

Closed
brandonweiss opened this issue Feb 14, 2017 · 31 comments
Closed

RubyGems post-install hook not triggering #5429

brandonweiss opened this issue Feb 14, 2017 · 31 comments

Comments

@brandonweiss
Copy link

I see a lot of talk about Bundler install hooks on different issues/PRs that (like this thread) mentions that Bundler respects RubyGems post install hooks, but I'm testing it out and that doesn't seem to be the case… if I install via gem install the hook runs, but if I add the gem to a Gemfile and install it doesn't seem to be triggering the hook. Is that unexpected?

@brandonweiss
Copy link
Author

The easiest way I found to test this out is to create a new gem. Add a file at lib/rubygems_plugin.rb with something like this:

Gem.post_install do
  File.write("~/test.txt", "it worked!")
end

If you do rake install you should see the gem install and then that file will be written to your home directory.

But if you create a new folder, add a Gemfile, and reference your gem via path: "path/to/your/gem", and then bundle install, the file won't be written.

@indirect
Copy link
Member

Thanks for reporting this! Running bundle install with path gems does not install those gems. The path feature is a shortcut to add the path to $LOAD_PATH, and does not do any of the usual gen installation procedures. Please create a gem if you need to run a post-install hook during bundle install.

@brandonweiss
Copy link
Author

Hmm, if memory serves I also tried that because I suspected path might be bypassing this… but I can't remember. Let me try that now.

@brandonweiss
Copy link
Author

Yeah, I just tried it with a private gem on GitHub… oh wait, does that not work either? Does it only trigger the install hook if the source is RubyGems?

@indirect
Copy link
Member

@brandonweiss I honestly don't know about git gems, but I would only expect a post-install hook to run from an actual .gem file coming from a gem server, yeah.

@brandonweiss
Copy link
Author

No wait, that doesn't make any sense, because if I rake install it gets run. It definitely shouldn't matter where it gets installed from.

@brandonweiss
Copy link
Author

brandonweiss commented Feb 14, 2017

OK, my theory is that it has something to do with that I install gems with bundle install --path. That sorts of makes sense, in that if it's just being dumped in a directory and Bundler is doing some magic to load the gem, and if what's actually causing the post install hook to fire is Rubygems, then maybe Rubygems never gets the chance to trigger it?

I tried to test this out by not installing using the path flag, although… that's weird, I don't see the gem when I do gem list. And when I run bundle show gem_name it's in:

/Users/brandon/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/bundler/gems/gem_name

Shouldn't it be in the outer-level gem directory? Did Bundler change at some point to nest it inside the Bundler gem?

@segiddins
Copy link
Member

Bundler only should be running the install hooks when it runs an actual gem installer, which definitely doesn't happen for path gems

@brandonweiss
Copy link
Author

brandonweiss commented Feb 15, 2017

By “path gems” do you mean a gem that is referenced in a Gemfile via the path option or when gems are installed via Bundler to a specific directory via the path flag? The former I guess makes sense, although the latter is not what I'd expect… I would not expect a gem to install differently simply because gems are being put in a specific directory.

@segiddins
Copy link
Member

Via the :path option in the Gemfile

@indirect
Copy link
Member

@brandonweiss to answer your earlier question, I believe that gems in bundler/gems are :git gems? If a .gem built gem is installed via bundle install, it shouldn't go into a directory named bundler. Maybe you have some environment variable or bundler setting changing the --path still?

@brandonweiss
Copy link
Author

@indirect Oh, well I am installing it via GitHub at the moment, so that would make sense why it's being installed there. OK, so maybe it's still bypassing the RubyGems install process and thus not triggering the post-install hook. Let me try publishing a gem to RubyGems and see if installing via bundler triggers the post-install hook.

@colby-swandale
Copy link
Member

ping @brandonweiss

@colby-swandale
Copy link
Member

I'm closing this for now but feel free to open this again if needed

@glebm
Copy link

glebm commented Jun 3, 2017

The install from path not triggering lib/rubygems_plugin.rb-registered hooks issue still exists.

@segiddins
Copy link
Member

Please share a gemfile that we can use to reproduce the issue

@glebm
Copy link

glebm commented Jun 3, 2017

Remove the workaround here:
https://github.com/glebm/critical-path-css-rails/blob/penthouse-npm/Gemfile#L7-L10

The run bundle. Note that it's using gemspec but that's effectively a path gem.

Expected behaviour: npm install from the Gem.pre_install hook runs.
Actual behaviour: No hooks are run.
Bundler version: 1.15.0 on Ubuntu 16.04.

@segiddins
Copy link
Member

Ah now I understand, thanks!

@indirect
Copy link
Member

indirect commented Jun 3, 2017

@glebm gems from paths are never installed, and that's why the post install hook is not firing. can you describe what you would expect to happen with a post install hook for gems that aren't installed? what's the goal you're trying to accomplish?

@segiddins
Copy link
Member

@indirect it's just that the plugin file should be loaded, if I'm understanding correctly. I have a patch nearly done

@brandonweiss
Copy link
Author

brandonweiss commented Jun 3, 2017

Sorry I haven't followed up with a repro 😞 Distracted by too many things.

It's possible the term “installation” might have a particular meaning here that I'm not getting, but if I made a gem, someone might “install” it in a number of ways.

Manually to global gems

gem install gem_name

From a Gemfile with Bundler to global gems

source "http://rubygems.org"

gem "gem_name"

bundle install

From a Gemfile via path with Bundler to global gems

source "http://rubygems.org"

gem "gem_name", path: "~/Code/gem_name"

bundle install

From a Gemfile with Bundler to local path

source "http://rubygems.org"

gem "gem_name"

bundle install --path vendor


It's possible there are some other permutations I'm not thinking of, but from my perspective, running bundle install is installing all of these. I get technically in some cases it's probably not (like specifying the gem via path), but I would expect every single one of these to trigger the post-install hook. Does that seem reasonable?

@segiddins
Copy link
Member

segiddins commented Jun 3, 2017

From a Gemfile via path with Bundler to global gems

This case doesn't actually install gem_name, it just puts its require paths on the $LOAD_PATH

@glebm
Copy link

glebm commented Jun 3, 2017

@segiddins True but that seems to be an implementation detail. I think the common expectation is that rubygems_plugins are loaded. Thanks for the PR!

@segiddins
Copy link
Member

Loading the plugins is separate from post install hooks, and I think loading them is totally reasonable

@glebm
Copy link

glebm commented Jun 3, 2017

If you load the plugins, their post-install hooks will run, right?

@glebm
Copy link

glebm commented Jun 3, 2017

*post- and pre-install hooks

@brandonweiss
Copy link
Author

brandonweiss commented Jun 3, 2017

Maybe I don't understand the terminology… I would assume loading the plugin would then trigger a pre/post-install hook (if one exists) because they’re defined in lib/rubygems_plugin.rb in a gem?

@glebm
Copy link

glebm commented Jun 3, 2017

Yes, that's what I think as well. Just checking as I am a bit confused by @segiddins's last comment

@glebm
Copy link

glebm commented Jun 4, 2017

Looks like hooks will not trigger during the gems installation (by design): http://help.rubygems.org/discussions/problems/378-gempre_install-does-not-working-as-it-named

bundlerbot added a commit that referenced this issue Jun 15, 2017
[Installer] Load plugin files from path gems

Closes #5429 .

Because RubyGems doesn't know about path gems before we install, we need to manually load the plugin files for the path gems we're installing. This is basically copying the logic RG uses, but scoped only to those gems that we're entirely responsible for.
@brandonweiss
Copy link
Author

Damn. That is really disappointing. npm has this ability and it's super-useful. 😞

@brandonweiss
Copy link
Author

brandonweiss commented Jul 27, 2017

OK, I sort of got it working, actually. Here's the repo: https://github.com/brandonweiss/git-hookshot

Instead of using rubygems_plugin.rb to define an install hook, I just defined it in the gemspec. The reason I thought it worked and shipped it is because when I was testing this I was using the GitHub repo as the source in my Gemfile. And when I bundle installed the first time, or any time I bundle updated the install hook would run and generate the directory and symlinks.

But someone just noticed that if they use RubyGems as a source then it doesn't work. Is that expected? That pre/post install hooks would run if the source is from GitHub but not RubyGems?

brandonweiss/git-hookshot#1

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants