Commercial Products
Sep '09
14

Releasing with Rudy

posted by delano

I have about 10 active opensource projects. I’m lucky because most of them aren’t that popular so there’s not a lot of overhead. Beyond other people using your work there are some significant advantages in maintaining projects as opensource (I’ll talk more about that in a future post). That said, there is additional effort involved so I’ve automated some tasks with Rudy to reduce the repetitive tasks. One such task is the release process.

Minor warning: The following is specific to Ruby development on Linux/Unix with git because that where I do most of my work. If you’ve created configurations for other languages (including projects on Windows) let me know and I’ll post them or include them in the arcade.

My Rudy Configuration

One of the core features of Rudy is the routines configuration. A routine is like a really concise Rake task that can be associated to a particular machine role. A little known fact is that Rudy also supports defining global routines which are available to all machines.

Rudy looks for global routines in two places:

  • ~/.rudy/
  • /etc/ (linux only)

I put the following configuration into a file called ~/.rudy/release-routines.rb.

commands do
  allow :rm
end

routines do
  
  publish do
    before :package_test, :publish_docs
    local do
      project = File.basename pwd.first
      puts "PUBLISH #{project}", $/
    end
    after :publish_github, :publish_gem
  end
  
  package_test do
    local do
      puts 'Creating Test package...'
      rake 'package', 'clean'
    end
  end
  
  publish_docs do
    before :publish_rubyforge_docs, :publish_github_docs
  end
  
  publish_rubyforge_docs do
    local do
      puts 'Updating Rubyforge docs...'
      rake 'publish:rdoc', 'clean'
    end
  end
  
  publish_github_docs do
    local do
      rake 'rdoc'
      if file_exists?('doc')
        puts 'Updating Github Pages...'
        git 'checkout', 'gh-pages'
        rm :r, :f, 'files', 'classes' 
        unsafely { mv 'doc/*', '.' }
        rm :r, :f, 'doc'
        git 'add', '.'
        git 'commit', :a, :m, 'Updated docs'
        
        git 'checkout', 'master'
        git 'push'
      else
        puts 'No docs directory'
      end
    end
  end
  
  publish_github do
    local do
      puts 'Pushing to GitHub...'
      git 'tag', :f, 'latest'
      git 'push', '--all'
      git 'push', '--tags'
    end
  end
  
  publish_gem do
    local do
      puts 'Publishing Rubyforge gem...'
      rake 'publish:gem', 'clean'
    end
  end
  
end

The Rudy configuration I use to create releases of my open source projects.

My Release Process

With the configuration above in place, I can run the release routines I created from any directory on my machine. But before I run the automated process, there are a few tasks that still require manual attention.

  • Update the change log
  • Update file manifest and dependencies in the gemspec file (if necessary)
  • Increment the release number
  • Commit all local changes
  • Create a release tag

Then I run the following simple command from the project directory:

$ rudy publish

There’s huge value in being able to define a routine in one location yet be able to run it from each individual project directory. It establishes a standard process for all of your projects which reduces overhead (including the mental workload) and increases consistency.

For example, you’ll note the publish_github routine creates a tag called “latest”. That allows me to refer to that tag in long-running or rarely updated documentation when I talk about the most recent release. It’s little things like that that make a big difference over the long run. Both in terms of my time and the visible consistency of a project.

Future Additions

Astute readers will note a couple glaring improvements than can and should be made to this process. The first is creating the release tag automatically based on the gemspec (or possibly library version). The second is removing the reliance on Rake. There are some tasks that Rake is specifically suited for, but in this case it’s possible to cleanly migrate the calls for building the documentation and Rubygems into Rudy directly.

And that’s it. Do you automate your release process?

I'm Delano Mandelbaum, the founder of Solutious Inc. I've worked for companies large and small and now I'm putting everything I've learned into building great tools. I recently launched a monitoring service called Stella.

You can also find me on:

-       Delano (@solutious.com)

Solutious is a software company based in Montréal. We build testing and development tools that are both powerful and pleasant to use. All of our software is on GitHub.

This is our blog about performance, development, and getting stuff done.

-       Solutious