Babushka shell commands patched to work with rbenv and .ruby-version

46 views
Skip to first unread message

Matthew Hutchinson

unread,
Aug 31, 2014, 4:22:41 PM8/31/14
to babush...@googlegroups.com
Hi Ben,

First up, many thanks for creating Babushka! I've just introduced it to our dev team (at HouseTrip) to help bootstrap laptops for developing various apps, services and gems.

Two questions,

1)  I'm using an rbenv dep successfully to install rbenv (including various Ruby versions, and the necessary rbenv hooks to a bash profile). What I couldn't figure out how to do (cleanly), was to continue after installing rbenv (in further nested babushka deps) to use the Ruby versions I'd just installed (mostly due to PATH issues and rbenv not being initialised).

To solve this, I ended up patching the shell command directly with this;


So, when running, the shell will be properly setup to use the ruby (or gems) that have been installed and chosen with rbenv and the local ~/.ruby-version.

My real question is, do you know of a better (more conventional) way to do this? 
I've seen mention of a `login_shell` method on other topics in this mailing list, but I think its now gone.

Maybe this patch could be formalized with a `rbenv: true` param on the `shell` and `shell?` commands? If you'd be agreeable to this I could prepare a PR.


2) When boot-strapping laptops I use Babushka to ask? for several things, (location of local profile e.g. ~/.bash_profile, where to install apps etc.)  My question here is how to avoid nagging all the time, my idea is to store dep choices in a local yml I can load later to avoid asking again.  Does something like this exist in Babushka somewhere already, and again, if not, would you consider a PR for something like this?

Thanks again!

Matt

Ben Hoskings

unread,
Sep 1, 2014, 12:52:52 PM9/1/14
to babush...@googlegroups.com
Hi Matt, thanks for your post.

On Mon, 1 Sep 2014, at 06:22 AM, Matthew Hutchinson wrote:
> *1) *I'm using an rbenv dep successfully to install rbenv (including
> various Ruby versions, and the necessary rbenv hooks to a bash profile).
> What I couldn't figure out how to do (cleanly), was to continue after
> installing rbenv (in further nested babushka deps) to use the Ruby versions
> I'd just installed (mostly due to PATH issues and rbenv not being
> initialised).

There's been discussion on this issue in the past:
https://groups.google.com/forum/#!topic/babushka_app/Qklvy3rzxLQ

I don't think it can be solved within babushka, because these changes (adding rbenv, changing the locale, and so on) affect the environment in which babushka runs.

In particular, if you simulate the new environment within babushka, then it can appear to succeed -- but the changes that it would be claiming to make would not be applied to the returning prompt. That is, babushka would say "rbenv installed" but then the shell would be missing rbenv.

You need to do something outside babushka (manually load rbenv, recycle the shell, etc) to have the changes take effect; this is something that babushka (or any other process on the shell) can't control.


> To solve this, I ended up patching the shell command directly with this;
>
> https://gist.github.com/matthutchinson/f2d1346a62651c5a9b5c -
>
> So, when running, the shell will be properly setup to use the ruby (or
> gems) that have been installed and chosen with rbenv and the local
> ~/.ruby-version.
>
> *My real question is*, do you know of a better (more conventional) way to
> do this?

On a remote box, this is an easy problem to solve -- you just log out and back in (which is easy to automate as part of the process). That's what I do during provisioning to have the correct locale take effect:
https://github.com/benhoskings/corkboard-babushka-deps/blob/master/provision.rb#L153-L158

For local babushka jobs, perhaps there could be some sort of automation for running sub-babushkas in new sessions. I don't believe it's the answer, though, because the problem of the containing session becoming stale isn't solved. (Babushka aside, I don't know a way to solve that problem.)


> I've seen mention of a `login_shell` method on other topics in this mailing
> list, but I think its now gone.

ShellHelpers#login_shell hasn't gone anywhere :) It runs a command in a login shell (i.e. the shell's full rc script should be loaded), but it doesn't start a new session. I don't know a way to do that without a new console.


> Maybe this patch could be formalized with a `rbenv: true` param on the
> `shell` and `shell?` commands? If you'd be agreeable to this I could
> prepare a PR.

I don't think that's the place for it, I'm sorry. I want ShellHelpers and so on to be generic helper methods, rather than make them aware of the specifics of certain commands.

As above, the rbenv changes have to take effect outside babushka; I don't think simulating them inside will get us very far.


> *2) *When boot-strapping laptops I use Babushka to ask? for several things,
> (location of local profile e.g. ~/.bash_profile, where to install apps
> etc.) My question here is how to avoid nagging all the time, my idea is to
> store dep choices in a local yml I can load later to avoid asking again.
> Does something like this exist in Babushka somewhere already, and again,
> if not, would you consider a PR for something like this?

This did exist in the past, but it was fiddly and rarely used. I removed it along with the old shared variable system in favour of dep parameters.

You can achieve the same thing by passing dep arguments on the commandline:

$ babushka dep_name key=value etc=etc

The difference is that because dep parameters are properly localised, they have to be passed from the top down to the dep that requires them, and that's not always feasible.

The alternative was much worse, because it involved global mutable state :) Here are some details:
https://github.com/benhoskings/babushka/commit/40054c2e7b9c382ff01ea26b70725a3271ac3eda

- Ben

Matthew Hutchinson

unread,
Sep 1, 2014, 6:34:24 PM9/1/14
to babush...@googlegroups.com
Hi Ben,

Many thanks for your quick reply.  Apologies for not spotting that earlier thread you had with Torsten.

So basically following your advice (and some of the chat on that thread), you recommend recycling the shell.  Either with a 2 step (prepare then provision approach) or something else.  Otherwise (with something like my patch) - you quite rightly point out that I will have deps that are depend on a certain state?  Is that correct.  I guess my patch is highly dependent on rbenv and its syntax/setup, and not generic at all.

Also with a remote session, you mentioned you can recycle the shell by logout/in and continuing from there.  How about ssh'ing to localhost (the laptop itself) to solve this problem when running babushka?  I wonder if that would work?


On the 2nd point, I'll give the command line arguments a go, do they only apply to the top level dep, or do the values persist further in nested deps? 

Once again, thanks for such an awesome tool!

Matt

Ben Hoskings

unread,
Sep 1, 2014, 10:48:53 PM9/1/14
to babush...@googlegroups.com
On Tue, 2 Sep 2014, at 08:34 AM, Matthew Hutchinson wrote:
> So basically following your advice (and some of the chat on that thread),
> you recommend recycling the shell. Either with a 2 step (prepare then
> provision approach) or something else. Otherwise (with something like my
> patch) - you quite rightly point out that I will have deps that are depend
> on a certain state? Is that correct. I guess my patch is highly dependent
> on rbenv and its syntax/setup, and not generic at all.

Right. Once rbenv is set up correctly, then future shell commands don't have to be aware of it: they can just run 'ruby' and rbenv will take effect.

Apart from the coupling problem, though, there are ways that the rbenv install could fail, while the patch loads it correctly, which would mean babushka thinks the dep is met when it's not. That's the worst kind of failure: it's hard to find, because there's no failing dep to flag the problem, and it erodes the trust that "✔️ met" actually means that thing is done.

This has an analogue in testing: it's about unit vs. integration testing (i.e. testing in isolation vs. testing live). The patch would be akin to stubbing rbenv, running a shell command assuming rbenv is installed. That makes it a more isolated operation, because a runtime component has been replaced with a test-only version.

In testing a stub is sometimes what we want, depending on the situation, but babushka's met? blocks should never be isolated tests. They shouldn't ask "does this thing work if its collaborators are assumed to work", but rather, "does this thing work in the real system right now".

To that end, I think it's important to keep methods like these blind to details of the system, and incapable of anything but working with the underlying system as it stands.


> Also with a remote session, you mentioned you can recycle the shell by
> logout/in and continuing from there. How about ssh'ing to localhost (the
> laptop itself) to solve this problem when running babushka? I wonder if
> that would work?

That's definitely a possibility, and one I've toyed with in the past. To be honest, I haven't found a solution I like yet.


> On the 2nd point, I'll give the command line arguments a go, do they only
> apply to the top level dep, or do the values persist further in nested
> deps?

Only the top-level dep receives them; it's that dep's job to pass them onwards. In that way they're just like method arguments: there's never any implicit sharing. They have to be explicitly passed into a scope in order to be used there.


> Once again, thanks for such an awesome tool!

You're welcome, cheers :)

- Ben
Reply all
Reply to author
Forward
0 new messages