i stuck my cucumber in it
We’re building out an application to support this high profile effort that involves something like 10 different teams. My team’s application has over a million lines of code, 8000 classes, and Needs To Work(tm). Or heads will roll. And mine doesn’t like to do that, because it might get all scruffed up. So naturally we decided to get down with the BDD and use the Cucumber. But since we’re enterprise Java developers, things get a little more complicated. Because that’s how we roll.
We use JRuby so our Ruby code can talk to our Java code and it’s totally awesome and all that. But when it comes to deploying, right now we have a simple process that involves a script (using a proprietary internal tool that is kind of like SCP except it leaves me wishing it actually was) that bundles up all my deliverables and sticks it on the target server. The application servers and Java platforms and so on are already there, usually maintained by other teams.
I wanted to build the application on a build server where the features will be run whenever code changes (using hudson to trigger the scripts). I know what versions of Java will be available on the target servers, since there are architectural standards within the enterprise that I can count on. And, among those standards, I can count on not having any variety of Ruby anywhere unless I put it there myself. But that complicates our process, because I really shouldn’t be adding things to the server (which my team doesn’t own or control). And even if I did, then the server would have an additional component that existed nowhere else which would need to be maintained and loved and cared for, and I’m not at all into that sort of thing.
So I says to myself: how do I simplify this process? And myself says back: stick your cucumber in it.
So I did. But what does that mean, you say? Well, besides being what the cool Java kids are calling it these days, what I mean is that I stuck Cucumber and its dependent gems inside the JRuby jar which meant that all I needed to do was bundle a single extra jar in with the application that we build. This makes deploying the exact same version of Ruby with the exact same gems to any machine or environment really easy: you just copy one file around the network. Even a caveman could do it. But TCP/Smoke Signal was notoriously slow and error prone so they usually didn’t.
The process is super easy to do. First of all, you need to download the source code. You can get it from github (http://github.com/jruby/jruby) or just download the source jar: http://jruby.org/download
What we want to do is build the jar-complete version of the distributable, which is a completely standalone JRuby environment encapsulated as a single jar. If you inspect the ant build script (which is like a make file in the Java world), you’ll see the target “jar-complete” invokes a command to install additional gems defined in the “complete.jar.gems” property. This will by default be found in the “default.build.properties” file. I just edited it directly, and added a reference to a new property “cucumber.gems” to the end:
complete.jar.gems=${rspec.gem} ${rake.gem} {$ruby.debug.gem} ${ruby.debug.base.gem} ${columnize.gem} ${cucumber.gems}
Then we need to define the cucumber gems we want. To ensure the build is predictable, I specify each gem and dependency along with its version:
cucumber.gems=${build.lib.dir}/cucumber-0.9.2.gem ${build.lib.dir}/builder-2.1.2.gem ${build.lib.dir}/diff-lcs-1.1.2.gem ${build.lib.dir}/gherkin-2.2.9-java.gem ${build.lib.dir}/json-1.4.6-java.gem ${build.lib.dir}/term-ansicolor-1.0.5.gem
Now you need to get the gem files and put them in the jruby_src/build_lib folder. When you run the build, it will download the actual gem sources. I just copied the gem files from an existing JRuby installation’s gem cache (jruby/lib/ruby/gems/1.8/cache), but you can do it any way you want.
Now run “ant dist-jar-complete” and you’ll be presented with a lovely, customized version of jruby-complete-1.x.y.jar in your jruby_src/dist folder ready for the cukes or whatever else you want.
You could then invoke it by calling:
java -jar jruby-complete-1.5.3.jar -S cucumber features