Wednesday, May 02, 2007

Plugems - More than dependency management

In our previous post, we attempted to compare plugems to various other techniques in the community. James Adam, of Rails Engines responded here and here, and raises some interesting points I'd like to address.

First, all of the comments comparing engines referred to the engines plugin that enhances rails, as described in this post, but I added an updated note to the Engines comparison section for clarification.

That being said, we believe versioned dependencies provide more value than vendoring all dependencies for medium to large rails applications. We do suggest you start all shared code as plugins, and move towards a plugems approach when multiple applications want to leverage it.


Version Policy Adherence

Our group strongly follows the versioning policy outlined in the Rubygems User Guide . Which is:

  • Versions shall be represented by three non-negative integers, separated by periods (e.g. 3.1.4). The first integer is the "major" version number, the second integer is the "minor" version number, and the third integer is the "build" number.

  • A category 1 change (implementation detail) will increment the build number.

  • A category 2 change (backwards compatible) will increment the minor version number and reset the build number.

  • A category 3 change (incompatible) will increment the major build number and reset the minor and build numbers.

We have a test harness that wraps each plugem, that helps our team adhere to the backwards compatibility, and as always TEST!!! TEST!!! TEST!! Our applications are safer because we lock most plugem dependencies pessimistically, e.g.:

'foo', ' ~> 1.0.0'

This states we'll load any plugem where the revision is: 1.0.0 > revision < 1.1.0

If the author of the plugem has non-backwards compatible changes, he can simply branch the plugem, update the manifest by incrementing the minor, and redeliver. All existing applications will NOT be affected, even if its installed on the same host.

In the majority of cases, the machine-wide updates are for picking up pure bugfixes (which should be safe) via the increment of micro. Bigger releases aren't automatically picked up due to the pessimistic lock.


Plugem Deployment

But Plugems is not just dependency management! If you vendor everything, you lose the ability to push micro changes out quickly to other developers and the ability to deploy with dependencies.

Lets say I have a foo application, with a bar dependency. When i've made a change to the bar dependency that I'd like to share with others, I do plugem publish bar, which pushes the change to our gem repository. Then when Eddie is working on the foo application he can run: plugem up foo . If the recently published bar gem conforms to the manifest in the foo application, he'll get an update. He restarts his application, and he can go on developing.

Even better, the foo application is also a plugem! So I can publish the foo application in the same way. plugem publish foo. Then on each deployment host, plugem up foo. There are obviously more details, but this gets why we think having dependency information in the application is important. And we cant take credit for this. It was Dave Thomas at RailsConf 2006 that had the idea of using gems for deployment.

ScribeMedia has a great video series from RailsConf 2006. See Part 5



We've talked about it a bit before
, and plan to dive into the details of plugem deployment in the next few days and look forward to feedback from the community.

No comments: