Last Friday marked our first production deployment at Goldstar using Isolate to manage our gem dependencies. We are very happy about this move, because it is a beautifully simple tool that has saved us a lot of pain. My co-worker BJ Clark wrote about the pain, and received a lot of undeserved flack. This is the background to what BJ wrote.
I’m going to follow this post with an article about the differences between Bundler and Isolate, as well as how to start using Isolate in your own Rails project. Before I do this, though, I want to describe the events that led us up to the switch, because I think it’s representative of a huge problem in the Rails community. Though we ended up switching to what I consider to be a technically superior product based on simplicity, we arrived there because of poor community interaction on the part of the Bundler developers.
I want to reiterate that, because it’s the thesis of this article, if there is one: Despite some technical issues with Bundler, we moved away from it because of the Bundler team’s refusal to play nicely. This isn’t an isolated incident, either. In the 7 years or so I’ve spent developing in Ruby, I’ve certainly encountered technical issues and poor code, but all of the technical issues and poor code I’ve encountered do not disappoint me as much as the mountains of political bullshit that I’ve had to endure.
I’m going to cut the technical details out, because they’re just the symptoms, but it’s worth summarizing: we ran into a bug where Bundler would refuse to upgrade a bundled gem. When we tried to upgrade to Bundler 0.9, which fixed this bug, we found that an important feature was removed. After reading the source code to confirm that the feature was indeed missing, I hopped on to an IRC channel where I could find the Bundler developers to get some assistance. The conversation went like this:
Me: How do I specify build options with Bundler 0.9? I can’t seem to find documentation, and I can’t find in the source code where it’s used.
Developer: It was removed.
Me: What replaces it?
Developer: Nothing yet, but some day we’ll make it way better! Stay tuned!
Me: Will this be in the next release? Our business depends on it.
Developer: Maybe. It will be in a later release, and it will be way better.
Me: How can I work around this missing feature in the meantime?
Developer: You can do this.
Me: That doesn’t work for me.
Developer: Okay, you can wait for the later release then. It will be way better!
I went back and talked to my co-workers. We were stuck: our business depended on Bundler, but the version we had contained bugs that made it difficult to use. The new version was missing an important feature, which made it impossible to use.
I decided to give the Bundler developers the benefit of the doubt. At the time, I was sure they had good reasons for removing the important feature, and I didn’t expect them to stop what they’re doing to add it back just for me. We weren’t the only folks bitten by the removal of this feature, though, so I offered to work on a patch and contribute back.
Of course, I wouldn’t want my work to be conflicting with someone else’s, and I didn’t want the effort to be duplicated. So back to the Bundler Developers I went:
Me: We really need build options. Is anyone currently working on it?
Developer: Nope. But we will be some day, and it will be way better!
Me: Well, we need it, and a bunch of other people do too. How about I save you guys the trouble, and I write the patch myself?
Developer: Okay, you can write your own version until we do it properly.
Me: But if I contribute the feature back, you won’t have to do it because it will already be done. I don’t want to write it if you’re just going to throw it away later. That’s wasted effort.
Developer: You’re not smart enough to do it.
Developer: There are requirements you don’t know about.
Me: If you tell me these requirements, then I will know about them and I can write an appropriate patch.
Developer: Well, we need to support multiple versions of Ruby. You’re not smart enough to support multiple versions of Ruby.
I left this conversation pretty well pissed off. Here I was offering my time, and my employer’s time, to fix a bug that many people had experienced. In response to my generosity, I was being told that if I spent my time and effort fixing this bug my work would be thrown away. We started out with a technical problem: we found a bug in some software. This led to an offer of collaboration to solve the problem. The offer was refused, not because I wasn’t capable of helping: I’m not exactly new at this. The offer was refused because anything not done in the tight little circle of the Bundler development cabal was not sufficient. It was probably the worst case of NIH I’ve ever witnessed.
I will add that after this conversation, I was able to finally make some headway, and get an agreement that, if I did it in exactly their way, they might just possibly accept a patch from me. I still wasn’t convinced that I could take their word for it, though, so I started looking for alternatives. I decided to give Isolate a shot, which I was aware of because I know the developers that wrote it. In a couple hours, I had our application moved over. In a day, I had all of our deployment and management scripts moved and updated for Isolate.
Isolate was (deliberately) missing one feature, and jbarnette was nice enough to help me solve it with a small patch to our environment. Also, because we have two requirements that weren’t encountered before by Isolate’s authors, I was made a contributor to the project so I can add those features for everyone to enjoy. Isolate wasn’t technically the 100% solution for us, but it was the 99% solution. Better still, I’m not only allowed but encouraged to provide the last 1% myself.
I hope that this situation turns out to be less common in the future than it has been in my experience. We need to have open, and inclusive environments where we respect each other and their needs. Developing software, especially open source software, in silos without outside help and encouragement leads to projects that are fragile that don’t solve the problems they were intended to solve.