inscapist / ruby-nix

Generates reproducible ruby/bundler app environment with Nix
MIT License
118 stars 5 forks source link

Is there any way to isolate a ruby-nix environment from system gems? #55

Open nyghtly-derek opened 3 days ago

nyghtly-derek commented 3 days ago

We've been using ruby-nix for a few weeks now, and overall it's an excellent tool! In particular, our workflow to upgrade gems is much improved.

However, we've been encountering a lot of problems with individual environments not working because of ruby gems from outside the nix environment leaking in. Here's an example of a nasty error:

/nix/store/1cqxdibgsfyhfzkslf4hvqmzmcwimpmn-ruby-3.1.6/lib/ruby/3.1.0/bundler/definition.rb:507:in `materialize': Could not find prism-0.24.0 in locally installed gems (Bundler::GemNotFound)

Consequently, we've been maintaining a troubleshooting guide which has become somewhat lengthy. For example, here's a list of remediation steps that we recommend:

rm -rf <project>/.bundle # a local bundle config that interferes with the gem path
rm -rf ~/.gem # delete gem cache outside of nix... it seems that prism is getting cached here for some reason; as if our ruby env is leaking out of nix
rm -rf ~/.local/share/gem # another gem cache outside of nix...
rm -rf <project>/tmp/cache/bootsnap # remove bootsnap cache
# check your ~/.zshrc or ~/.bashrc and remove any PATH exports which point to ruby stuff
# remove other ruby installations, such as rbenv or rvm

However, there are still occasions where environments get broken and require repeated remediation. In one case we had to revert back to the system bundle to manage gems outside of nix, because we couldn't find any more gem caches or ruby installations to remove outside of the above.

An added complexity is that we are developing on MacOS, which means that there will always exist a version of ruby (usually 2.6.0) and a set of ruby gems at the system level. From what I understand, this cannot be removed.

All that said, I'm wondering if you have any ideas for how to isolate a nix environment entirely from the system, with respect to ruby-nix?

Something I've tried already is to set these values in the .bundle/config. Unfortunately, it did not work:

---
BUNDLE_DISABLE_SHARED_GEMS: "true"
BUNDLE_GLOBAL_GEM_CACHE: "false"

Anything else I could try?

inscapist commented 21 hours ago

@nyghtly-derek does your team make use of direnv or nix develop?

/nix/store/1cqxdibgsfyhfzkslf4hvqmzmcwimpmn-ruby-3.1.6/lib/ruby/3.1.0/bundler/definition.rb:507:in `materialize': Could not find prism-0.24.0 in locally installed gems (Bundler::GemNotFound)

I presume this error happens when you are trying to run rails or irb. The error message would mean different things depending on how the nix environment is built. In the former, it is likely that the direnv context is stale (a known issue). In the latter, it is most likely caused by gemset.nix not being in sync with Gemfile.lock.

I would first recommend trying with nix develop -c zsh, as this has the least interference with the environment. If it builds and you still can't run rails, you should look at your gemset.nix.

If it works, then I believe it's the same scenario as this. You can just rm -rf .direnv && direnv reload to rebuild the environment correctly. Most of the time, this is the issue.

nyghtly-derek commented 12 hours ago

Ah, thank you for the helpful advice, inscapist!

We're using direnv at the moment. I'll test out nix develop to see if that has an impact.

I'm sure it will trigger during rails as well, although we usually see it before getting to that point. We have a build phase that runs rubocop, tapioca, that sort of thing. I can reproduce easily just by calling a gem, such as these:

tapioca -v
rake -v
rubocop -v

Anyways, I'll give these ideas a try, thank you ☺️

nyghtly-derek commented 10 hours ago

Hm, unfortunately rm -rf .direnv && direnv reload did not work for the particular case I'm debugging. We also aren't setup to use nix flakes in this project currently, so I can't test it with nix develop yet. However, I'll likely be trying that next. Requires some code change, but we've been considering a migration to nix flakes anyways.

Thanks again for the advice. We can probably close this, unless you have any other ideas.

Finally, maybe it's worth adding a note to the readme like "works best with a nix flakes environment"?

inscapist commented 5 hours ago

Honestly, nix flakes is really a lot better in this respect. I would strongly recommend it. The official installation includes a flake template too so I reckoned more people would use that over shell.nix. Guess I am wrong :laughing:

inscapist commented 5 hours ago

let me know if you need help with migrating to nix flakes, I would be glad to help.