[ruby] Using bundlerApp with local private ruby gem

I have a local gem that I want to keep private on my local disk.

This is a gem that includes a CLI. Let’s say my gem is called buddy.
So there is a buddy tool in the exe folder of the gem.
The gemspec correctly lists the executable with:

  spec.bindir = "exe"
  spec.executables = ["buddy"]

I used bundix to generate a gemset.nix for my gem. No issues.

I then have a derivation in the gem folder looking like:

{pkgs ? import <nixpkgs> {}}: let
  app = pkgs.bundlerApp {
    pname = "buddy";
    exes = ["buddy"];
    installManpages = false;
    gemdir = ./.;
  };
in
  app

If I try to build this with nix-build -v -E '(import <nixpkgs> {}).callPackage ./buddy.nix {}'. At first glance, it seems to be working, but in fact it doesn’t. I get in result:

result
└── bin
    └── buddy -> /nix/store/qkjf129lic2dqrw6k6visansxkay85qw-buddy-0.1.0/bin/buddy

That link is actually broken, that /nix/store/qkjf129lic2dqrw6k6visansxkay85qw-buddy-0.1.0/bin/buddy does not exist.

What am I doing wrong?

Packaging Ruby in NixOS is a rather meh experience IMO – bundix can get pretty buggy if you’re doing something non-standard (personally had problem with groups and local sems) – but I think in this case it’s working as intended. As far as I understand, bundlerApp is meant to point at a Gemfile that lists your gem as a dependency, like this, not at the gem sources directly. Another option could be doing something like this (can’t guarantee it’s kosher, just that it worked for me in a case similar to yours):

let
  ruby = pkgs.ruby_3_2;
  src = ./your-path;
  rubyEnv = bundlerEnv {
    inherit ruby;

    name = "your-gem";
    gemdir = src;
  };
in
  buildRubyGem rec {
    inherit src ruby;

    gemName = "your-gem";
    pname = gemName;

    buildInputs = [ rubyEnv ];
  };
2 Likes

Thanks Jaen,

The thing is I did have a Gemfile too. My gemfile basically looked like:

source "https://rubygems.org"
gemspec

And if I check the gemset.nix, it does contain the dependencies to my gem + my gem with a type: path.
I could not put in my Gemfile directly gem 'buddy', because my gem is not on rubygems.org anyway, so that would fail.

But your suggestion actually worked! :tada: Thanks @jaen !
I wrongly assumed buildRubyGem would not be the good choice for a CLI tool, the exes = [] of bundlerApp made me think this was the better choice.

Glad it worked!

Re: having the Gemfile – right, but as far as I understand, using gemspec just imports your gem’s dependencies into the Gemfile, while what bundlerApp wants is for the Gemfile to depend on the gem being packaged, which is why it didn’t work.

Re: not being published on Rubygems – well, you could have probably tried a :git or :path dependency, but my expectation is it would’ve hit some bundix corner case and fail.