Recently we worked with a client where we had to run a part of their multi-threaded code in JRuby for performance reasons. They have been using CircleCI with MRI for running tests. In this post I will explain how we configured CircleCI to run the same tests using both JRuby and MRI.

CircleCI uses circle.yml file for configuration. Before configuring JRuby, this is how it looked like:

  machine:
    ruby:
      version:
        2.1.5

  dependencies:
    pre:
      - ./bundle_install_circle_ci.sh
    cache_directories:
      - "~/vendor/bundle"

  test:
    override:
      - bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app.xml:
          parallel: true
          pwd: app
          files:
            - spec/**/*_spec.rb


Here are the steps to enable JRuby in CircleCI.

Specify the JDK version

We need to specify a JDK version before using JRuby.

  machine:
    java:
      version:
        openjdk7

Install proper dependencies

We needed to use JRuby 9.0.4.0 but the version of JRuby that came with Ubuntu 12.04 image of CircleCI was different. We added rvm install command as follows to install specific version that we wanted. Also we can configure any script (like bundle install) that needs to run before running tests.

  dependencies:
    pre:

      - rvm install jruby-9.0.4.0
      - ./bundle_install_jruby_circle_ci.sh

    cache_directories:
      - "~/vendor/bundle"

Configure JRuby

We used rvm-exec to set JRuby for running tests for this particular component in the test section. Otherwise by default it picks up MRI.

  test:
    override:

      - rvm-exec jruby-9.0.4.0 bash -c "bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_jruby.xml":
          parallel: true
          pwd: app
          files:
            - spec/**/*_spec.rb

Improving test runs on JRuby

Once we started running tests with JRuby, we observed it was taking comparatively slower to finish all tests. Most of the time was spent in starting the JVM. We made it faster by setting --dev parameter in JRUBY_OPTS environment variable. This parameter improves JRuby boot time and it shaved more than a minute time for us.

  machine:
    environment:
      JRUBY_OPTS: '--dev'

Here is the final circle.yml file:

# circle.yml

machine:
  ruby:
    version:
      2.1.5

  java:
    version:
      openjdk7

  environment:
    JRUBY_OPTS: '--dev'

dependencies:
  pre:
    - rvm install jruby-9.0.4.0
    - ./bundle_install_jruby_circle_ci.sh

  cache_directories:
    - "~/vendor/bundle"

test:
  override:
    - rvm-exec jruby-9.0.4.0 bash -c "bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_jruby.xml":
        parallel: true
        pwd: app
        files:
          - spec/**/*_spec.rb

    - bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_mri.xml:
        parallel: true
        pwd: app
        files:
          - spec/**/*_spec.rb