Wednesday, February 14, 2007

Locking down a deployed application

A single host might have multiple applications installed each on a different release track. Since all our applications are distributed as a bunch of gems, there is a potential issue with shared components. Even though the whole portal is being tested when some application or component is being pushed through the stack, there is always a possibility of incompatibility of on of the upgraded shared component with another dependent application. In some other environments there would only one solution - to roll back the whole new application. In our environment we have another option - to lock down the affected application. When an application is deployed, one of the deployment steps is to create a gem repository inside the application structure. The application gem repository has the sources gem installed and the rest of gems sym-linked as in this example:

actionmailer-1.2.5 -> /usr/lib/ruby/gems/1.8/gems/actionmailer-1.2.5
actionpack-1.12.5 -> /usr/lib/ruby/gems/1.8/gems/actionpack-1.12.5
...
sources-0.0.1

Gems put into an internal gem structure are those it was tested with, so they are guarantee to work. All is needed to lock down an application now is to set the GEM_HOME environment variable on a web server instance, serving the application, and to point it to the application internal gem repository. After that the application won't use the latest versions of the gems but those specific it is locked to.

7 comments:

Anonymous said...

Nice site. Out of curiosity, why aren't you just freezing Gems within the vendor directory for each separate application?

Anonymous said...

"why aren't you just freezing Gems within the vendor directory...?"

I could be very wrong here, but isn't it plugins that can be frozen in the vendor directory, not gems?

Anonymous said...

The plugins already live in the vendor/ directory, and so freezing them would be redundant. I have seen at least one sample rake task that purports to let one freeze gems to the same location, but haven't tried it (no need yet). Maybe they want to update an app's gems without redeploying?

Val Aleksenko said...

I guess you are asking not about using the rake task to freeze gems, since it only does that for the rails gems (actionpack, activerecord, etc.) itself, but about conversion of gems to plugins before deployment. The major drawback is that you loose an ability to upgrade shared components of an application without re-freezing. Since a shared component can be delivered with any of multiple applications installed on the box, it upgrades all of them. When gems frozen, it is not the case anymore.

Unknown said...

I believe anonymous was talking about Rick Olson's gems plugin which can unpack gems into the vendor directory, not as plugins, and then include them in the load path.

Eddie Frederick said...

Ahh... you're probably right.

Val's argument still applies, though.

Under the plugem freeze, you can freeze a -suite- of applications, not each application. That way you can deploy a hotfix to one shared component and simply bounce all of the apps using that repository (as opposed to refreezing them all.)

Craig Buchek said...

From another site, it appears that you actually want to set GEM_PATH, not GEM_HOME.