English

Navigation
Powered by Squarespace
Foobaruy mwe

Buy my book on <a href="lulu.com">lula</a>

« Exprix Forum for Excellence | Main | Hiring process »
Freitag
Nov272009

Gitting things done

If there's one tool which streamlined our production workflow it must be git. We started using it about a year ago - like everyone else. We joined Github for our own projects, and the open source ones, too. But one post from Bryan Helmkamp helped us getting the server setup streamlined, particularly, the multistage Setup. So this is mixing gits' and capistranos' best aspects. Why Multiple Stages? For many, bliss is when you can deploy with one command. This is great at the start of the project and the default for capistrano. The problem is that as soon as the project has a certain size, the speed at which one can deploy actually slows stuff down. This is because everyone has to wait with adding stuff until the deployment is done and agreed upon by the customer. How it works Now with multiple stages, at one point we decide that a number of features are complete and can be tested by users. We update the staging branch and deploy that with capistrano to the stage server. There, the customer can check out the new features while we continue developing. When we reach an agreement we can deploy we update the production branch from the staging branch and deploy that. So let's jump in.

Installation

We are using the capistrano-ext gem and the gitworkflow.rb from Brian's post in lib/tasks to standardize branching for deployment, and the actual deployment process. If you want to set up a new project to use those methods, you need to create

  • config/deploy.rb
  • config/deploy/*.rb
  • lib/tasks/gitworkflow.rb
  • Capfile

into your application. You can look here for some explanation - basically, you have to 'capify' the application and create deploy/envs.rb for each environment. If it’s aready capified, check the differences.The project should be in sync with a master branch (on github in my example).

Setup

This deployment setup requires two extra branches on github. This can be done with:

git checkout -b staging             # creates a branch locally
git push origin staging             # pushes the branch to github
git checkout -b production          # same for the production branche
git push origin production
git checkout master
git branch -d staging
git branch -d production

The local branches are deleted after each deploy.

For the following to work, the git config needs to be right. Much of this (maybe all of it) will be set correctly when cloning the project from github. Check:

git config --list

If the variables are not set right you can use

git config remote.origin.url git@github.com:simplificator/yourapp.git
git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git config branch.master.remote origin
git config branch.master.merge master

Or alternatively, perform a new git clone git@github.com:simplificator/yourapp.gitin another directory and work from there.

Then, the deployment targets need to be set up.

cap staging deploy:setup
cap staging deploy
cap production deploy:setup
cap production deploy

It’s likely you need to go to the server to set up the databases. One way of doing this is going to the deployment location into the current checkout and then running

rake db:create:all

We need

  • yourapp_production
  • yourapp_staging

Here you need to do some badly documented magic:

  • get gems
  • setup apache for passenger
  • run the migrations

 

Workflow

  • Branch for working.
  • Add and commit in your branch. Stash everything else.
  • Unit test.
  • Checkout master, pull, and merge your branch.
  • Unit test.
  • Push the master up.

 

Staging

When you’re happy with what you’ve done you can stage your work:

rake tag:staging
cap staging deploy:migrations

or the shortcut rake deploy:staging. When you do that, the staging branch is replaced with your local master branch.

Production deploy

When you want to push the staging branch into production, do

rake tag:production
cap production deploy:migrations

When you do that, the production branch is replaced with the staging branch from github.

Fixing

When you have to do a fix for the production server:

export BRANCH=hotfix
rake branch:production

hackhackhack…

git commit
export BRANCH=hotfix #(unless it's the same shell still)
rake tag:staging BRANCH=hotfix
cap staging deploy

After this, your staging server is running your corrected production code. If it works, you can redeploy this using

rake tag:production
cap production deploy

from the same shell (because of the BRANCH variable). Then the stage server is free again to take the more recent code.

New development doesn't affect that process.

Conclusion

I'm sure a lot more of this could be automated (like the initial db setup) - I'm not claiming we got all edges out of the process. But it can give you some ideas on how to do it yourself. For us, it has rendered our deployments much more professional, without adding too much cruft (after the initial setup of the first project). The stage server helps us to train ourselves with deployments of complicated software involving many moving parts until they run smoothly and will execute on production without trouble.

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>