Creating and Managing Private RubyGems with Jeweler, Github and Bundler

March 15, 2011
bundler, development, gems, ruby

We probably don't need to sing the praises of open source software to anyone. Of course, closed source has its place too. Not all code can or should be shared, whether it's proprietary or simply not ready to share yet.

Github has become our repository of choice for both open and closed source code. These days, much of our code is Ruby and so many of our libraries get packaged as gems. We've found Jeweler to be the easiest way to create those gems and Bundler to be the best way to manage them in projects.

This article describes how we use Jeweler, Github and Bundler to create, host and manage our private gems.

Create a new repository

Start by creating a new private repository at Github (you'll need a paid account to create private repositories). Optionally add collaborators.

Github repo

Create a Gem with Jeweler

Install the jeweler gem:

Terminal
1
$ gem install jeweler

Create your gem:

Terminal
1
$ jeweler jeweler_test

Configure the remote repository for your gem:

Terminal
1
2
3
$ cd jeweler_test
$ git remote rm origin
$ git remote add origin git@github.com:YOUR_ACCOUNT_HERE/jeweler_test.git

Check out the options that Jeweler provides:

Terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ rake -T

rake build               # Build gem into pkg/
rake clobber_rcov        # Remove rcov products for rcov
rake clobber_rdoc        # Remove rdoc products
rake console[script]     # Start IRB with all runtime dependencies loaded
rake gemcutter:release   # Release gem to Gemcutter
rake gemspec             # Generate and validate gemspec
rake gemspec:debug       # Display the gemspec for debugging purposes, as ...
rake gemspec:generate    # Regenreate the gemspec on the filesystem
rake gemspec:release     # Regenerate and validate gemspec, and then commi...
rake gemspec:validate    # Validates the gemspec on the filesystem
rake git:release         # Tag and push release to git.
rake install             # Build and install gem using `gem install`
rake rcov                # Analyze code coverage with tests
rake rdoc                # Build the rdoc HTML Files
rake release             # Release gem
rake rerdoc              # Force a rebuild of the RDOC files
rake test                # Run tests
rake version             # Displays the current version
rake version:bump:major  # Bump the major version by 1
rake version:bump:minor  # Bump the a minor version by 1
rake version:bump:patch  # Bump the patch version by 1
rake version:write       # Writes out an explicit version.

We don't want to mistakenly release our private gem to Gemcutter, so comment out the following line in your Rakefile:

Rakefile
1
# Jeweler::RubygemsDotOrgTasks.new

While you're editing your Rakefile, fill out your gem's details such as summary, description, etc. (look for the TODOs). When using Jeweler, you should edit these details in your Rakefile and not your gemspec file, which gets auto-generated.

Running rake -T again should confirm that the gemcutter:release task is now missing. Without this task, the release task will release to Github but not Gemcutter.

Let's version our gem, create a gemspec (using the details from the Rakefile) and then push an initial release to Github:

Terminal
1
2
3
4
5
$ rake version:write MAJOR=0 MINOR=1 PATCH=0
$ rake gemspec
$ git add -A
$ git commit -a -m "initial commit"
$ rake release

The process is very similar for future releases:

Terminal
1
2
3
4
$ rake version:bump:patch
$ rake gemspec
$ git commit -a -m "made some changes"
$ rake release

Include your gem with Bundler

Bundler makes it easy to include your gem in your projects. Simply add the following to your Gemfile:

Gemfile
1
gem 'jeweler_test', :git => 'git@github.com:YOUR_ACCOUNT_HERE/jeweler_test.git'

Do you want a specific version of your gem? Specify one with :tag:

Gemfile
1
gem 'jeweler_test', :git => 'git@github.com:YOUR_ACCOUNT_HERE/jeweler_test.git', :tag => 'v0.1.0'

Bundler will pull your source, build your gem and install it with a simple call to:

Terminal
1
$ bundle install

That's it! Your private gem should now be bundled with your project.

Open sourcing your gem later

If you decide to open source your gem later:

  1. Change its visibility to public in Github;
  2. Uncomment Jeweler::RubygemsDotOrgTasks.new from your gem's Rakefile; and,
  3. rake release will now release your gem to Github and Gemcutter simultaneously.

Update 3/21: John McAliley has written up a great tip for using two sources for a gem in different environments with Bundler at his "Cowboy Coded" blog. This approach works well for developing gems alongside Rails apps.

Update 7/22: Thanks to dwradcliffe's comment below, the process of removing the gemcutter:release task has been greatly simplified.