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
buildRubyGem: fix to support bundler install --redownload #104977
Conversation
Please base this on staging instead of master, mass rebuilds should target staging so that they don't hold up channel builds |
@RaghavSood thanks for the feedback; changed the target branch to staging Others looking at the PR may wonder the motivation: Gems which exist in the Gemfile (direct or transitive) that bundler wants to install that were also installed via Nix succumb to the error described in the description above. |
I had a quick look and it makes sense. The main downside is that it will increase all the program's closure sizes, even those that are not being used for development. Can this be enabled with a flag instead? |
@zimbatm -- I can add a flag. |
38b68cd
to
2b00a49
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zimbatm thank you for looking at this!
I've taken your advice and added a comment.
In the spirit of getting this merged faster I've kept the default "false" although my personal opinion is it should largely be true by default.
🙏
# such as `bundler install --redownload`. | ||
# At the cost of increasing the store size, you can keep the gems to have closer | ||
# alignment with what Bundler expects. | ||
, keepGemCache ? false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zimbatm actually decided to keep it default false largely because I rather see this merged sooner
(trying to upstream my personal fixes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good
|
||
# Do not remove the cache as this is needed to make some additional Bundler commands work | ||
# such as `bundler install --redownload` | ||
# https://github.com/rubygems/rubygems/issues/4088 | ||
# https://github.com/bundler/bundler/issues/3327 | ||
# rm -fvr cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you move this comment out of the bash script, it won't cause a mass rebuild and can target the master branch directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks -- took your suggestion.
I'm curious, how does staging branch make it to master?
The way in which Nixpks builds Ruby gems means that certain operations by bundler *will not work*, namely `bundle install --redownload`. According to the source the _cache/_ directory should have been kept, however it seems through revisions to the file it has been purged. Here was the comment from the original commit that introduced buildRubyGem: ``` # Note: # We really do need to keep the $out/${ruby.gemPath}/cache. # This is very important in order for many parts of RubyGems/Bundler to not blow up. # See rubygems/bundler#3327 ``` Why is the _cache_ directory needed? Bundler and RubyGems uses the cache as a source of truth. When bundler executes `bundler install --redownload`, any gems it discovers in the _GEM_PATH_ it assums must have their _.gem_ file present in the cache (unaware it was installed from Nix). Rather than downloading the gem from RubyGems the bundler code forcibly re-installs the gem from the cache directory instead and **fails** if it does not exist. I've opened rubygems/rubygems#4088 to see if this failure should be soft and not so explicit; or fallback to fetching the gem from scratch. Without this change the following is the error: ```bash > [nix-shell:~/code/nix/playground/jruby-bundler-rake]$ bundle install --force [DEPRECATED] The `--force` option has been renamed to `--redownload` WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.jruby.ext.openssl.SecurityHelper (file:/nix/store/fis6nzrpw9pmcivr84qh5byfgm07qn10-jruby-9.2.13.0/lib/ruby/stdlib/jopenssl.jar) to field java.security.MessageDigest.provider WARNING: Please consider reporting this to the maintainers of org.jruby.ext.openssl.SecurityHelper WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release Fetching gem metadata from https://rubygems.org/. Using bundler 2.1.4 Installing hello-world 1.2.0 Bundler::GemNotFound: Could not find hello-world-1.2.0.gem for installation An error occurred while installing hello-world (1.2.0), and Bundler cannot continue. Make sure that `gem install hello-world -v '1.2.0' --source 'https://rubygems.org/'` succeeds before bundling. ``` Wth the fix the following no woccurs: ```bash [nix-shell:~/code/nix/playground/jruby-bundler-rake]$ bundle install --redownload WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.jruby.ext.openssl.SecurityHelper (file:/nix/store/69wjlj4yirp48rv1q03zxgd4xvf0150d-jruby-9.2.13.0/lib/ruby/stdlib/jopenssl.jar) to field java.security.MessageDigest.provider WARNING: Please consider reporting this to the maintainers of org.jruby.ext.openssl.SecurityHelper WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release Fetching gem metadata from https://rubygems.org/. Using bundler 2.1.4 Installing hello-world 1.2.0 Bundle complete! 1 Gemfile dependency, 2 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. ``` ``` [nix-shell:~/code/nix/playground/jruby-bundler-rake]$ ls -l /nix/store/cwl9n5073hqgpfhnw4wic13nrrgg9dn8-gem-env/lib/jruby/gems/2.5.0/cache/ total 8 lrwxrwxrwx 1 fmzakari primarygroup 102 Dec 31 1969 bundler-2.1.4.gem -> /nix/store/ifc8a0gsfkrhkv953rd4rz8bcspahi8y-bundler-2.1.4/lib/jruby/gems/2.5.0/cache/bundler-2.1.4.gem lrwxrwxrwx 1 fmzakari primarygroup 110 Dec 31 1969 hello-world-1.2.0.gem -> /nix/store/xi9ln6n1mz2is5ppykjxqhhkpjq9zm6i-hello-world-1.2.0/lib/jruby/gems/2.5.0/cache/hello-world-1.2.0.gem ``` I have a minimal project that demonstrates this issue at https://github.com/fzakaria/jruby-bundler-nix-failure
2b00a49
to
cac20fb
Compare
Motivation for this change
The way in which Nixpks builds Ruby gems means that certain operations by bundler will not work, namely
bundle install --redownload
.According to the source the cache/ directory should have been kept, however it seems through revisions to the file it has been purged.
Here was the comment from the original commit that introduced buildRubyGem (still present in the source)
nixpkgs/pkgs/development/ruby-modules/gem/default.nix
Lines 156 to 160 in 8585991
Why is the /cache directory needed?
Bundler and RubyGems uses the cache as a source of truth. When bundler executes
bundler install --redownload
, any gems itdiscovers in the GEM_PATH it assumes must have their .gem file present in the cache (unaware it was installed from Nix).
Rather than downloading the gem from RubyGems the bundler code forcibly re-installs the gem from the cache directory instead and fails if it does not exist.
I've opened rubygems/rubygems#4088 to see if this failure should be soft and not so explicit; or fallback to fetching the gem from scratch.
Without this change the following is the error:
Wth the fix the following no error occurs:
Here we can see the /cache directory hydrated.
I have a minimal project that demonstrates this issue at https://github.com/fzakaria/jruby-bundler-nix-failure however it boils down to the following shell.nix file
Things done
sandbox
innix.conf
on non-NixOS linux)nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
./result/bin/
)nix path-info -S
before and after)CC @cstrahan @zimbatm @alyssais @manveru