Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Introducing AutoTagger – easy multi-stage deployment tagging with git

AutoTagger is a gem that helps you automatically create a date-stamped tag for each stage of your deployment, and deploy from the last tag from the previous environment.

Let’s say you have the following workflow:

  • Run all test on a Continuous Integration (CI) server
  • Deploy to a staging server
  • Deploy to a production server

You can use the autotag command to tag releases on your CI box, then use the capistrano tasks to auto-tag each release.

Installation

gem sources -a http://gems.github.com
sudo gem install zilkey-auto_tagger

To contribute, you can fork the github repository.

You can also visit the tracker project

The autotag executable

Installing the gem creates an executable file named autotag, which takes two arguments: the stage, and optionally the path to the git repo:

$ autotag demo  # => creates a tag like demo/200804041234 in the current directory
$ autotag demo . # => same as above
$ autotag demo /Users/me/foo # => cd's to /Users/me/foo before creating the tag

Running autotag does the following:

$ git fetch origin --tags
$ git tag <stage>/<timestamp>
$ git push origin --tags

Capistrano Integration

AutoTagger comes with 2 capistrano tasks:

  • release_tagger:set_branch tries to set the branch to the last tag from the previous environment.
  • release_tagger:create_tag runs autotag for the current stage

Example config/deploy.rb file:

require 'release_tagger'

# The :stages variable is required
set :stages, [:ci, :staging, :production]

# The :working_directory variable is optional, and defaults to Dir.pwd
# :working_directory can be an absolute or relative path
set :working_directory, "../../"

task :production do
  # In each of your environments that need auto-branch setting, you need to set :current_stage
  set :current_stage, :production
end

task :staging do
  # If you do not set current_stage, it will not auto-set your branch
  # set :current_stage, :staging
end

# You need to add the before/ater callbacks yourself
before "deploy:update_code", "release_tagger:set_branch"
after  "deploy", "release_tagger:create_tag"

Assume you have the following tags in your git repository:

  • ci/01
  • staging/01
  • production/01

The deployments would look like this:

cap staging deploy    # => sets branch to ci/01
cap production deploy # => sets branch to staging/01

You can override with with the -Shead and -Stag options

cap staging deploy -Shead=true      # => sets branch to master
cap staging deploy -Stag=staging/01 # => sets branch to staging/01

Known Issues

  • DOES NOT work with capistrano ext multi-stage
  • It will accept invalid tag names (if you specify a tag name with a space, it will blow up when you try to create the tag)

I have this working on a single project, and there is a fairly complete spec suite, but use at your own risk. It’s probably worth setting up on a demo project before adding it to a production repo.

Over time it would be nice to add other scms like subversion as well, so that you have a single way of tagging, regardless of scm.

Acknowledgments

Special thanks to Brian Takita, who gave me an initial implementation. Another useful link is http://codeintensity.blogspot.com/2008/06/changelogs-and-deployment-notification.html.

Happy tagging!

Comments
  1. Chad Woolley says:

    This is nice, Brian and I just rolled this from scratch on the current project. I had wished it was a gem, then lo and behold, here it is!

    It is a bit strange when you are used to pushing the *same* tag through all environments, but Brian eventually convinced me of the value of this.

    One of the main benefits is that it enforces the deploy order – ci, then staging, then production. You can also tell from the tag itself when a build was deployed to a given environment.

    However, one thing I miss is the traceabilty back to the original green CI tag. I’d really like to have a cap/rake task which would print out the “history” of the tags back all the way to the original CI tag. In other words, in Gitx/Gitk, you can see that all of these tags really point to the same commit (the last one before the green CI tag). It would be good to be able to verify that is actually the case, and that someone didn’t actually manually deploy an untested tag to demo, and that got pushed to production.

    It would also be nice to have an option to spit out the tag name somewhere (ideally default to /public/version.txt or something if in a Rails project) – so you can easily view the tag from the web interface. If this also included the tag traceability history back to the Green CI tag, that would be really cool, and make this the most perfect Gem ever.

    — Chad

  2. Jeff Dean says:

    Spitting out the version would be an easy task to write. I would probably put this in a non-public place, and if you want to display it somewhere you could write your own cap task to symlink it to public (or maybe I’d provide a cap task for that as well).

    I hadn’t thought of the history part – that seems pretty straightforward. It would really just be a list of all tags that point to the same commit. We should talk about how this would work in more detail – it sounds like there are two things here: view the history, and optionally run a verification to fail if the history doens’t follow the flow.

    Unfortunately, I have no idea how to find the commits for tags, but I know folks that do (ahem, Mike Dalessio…)

    I’ve created a public tracker project at http://www.pivotaltracker.com/projects/11988 and added these as 3 separate stories.

  3. Jeff Dean says:

    Chad – your comment made me realize that there is a big flaw in AutoTagger. I tag locally, not remotely, so the history you were talking about is completely lost and wrong.

    I’ve entered a bug for this on tracker, and I’ll fix it up this week.

  4. Jeff Dean says:

    You can now see the latest tags, and their corresponding commits, via a cap task:

    after “deploy”, “release_tagger:print_latest_tags”

    This will produce output like:

    ** AUTO TAGGER: release tag history is:
    ** ci ci/20090331045345 8031807feb5f4f99dd83257cdc07081fa6080cba once more
    ** staging staging/20090331050908 8031807feb5f4f99dd83257cdc07081fa6080cba once more
    ** production production/20090331050917 8031807feb5f4f99dd83257cdc07081fa6080cba once more

    I’ve also added tasks to write-to and read-from a text file on the remote server with the latest tag info:

    after “deploy”, “release_tagger:write_tag_to_shared”

    cap staging release_tagger:read_tag_from_shared

    Also, when the `release_tagger:create_tag` runs, it creates a tag based on the latest tag from the previous environment, which is what I believe to be the correct behavior.

    That, combined with the ability to see which commits they point to, is the first step in seeing a commit move from ci to staging to production.

  5. Chad Woolley says:

    I think that writing the tag to shared and letting people symlink it is probably a good idea.

    This is especially true on environments like EngineYard, where new slices have the shared dir on GFS (global across slices) but releases/current dir is not on GFS (separate filesystem on each slice). This means that writing the tag to shared must happen only once, but the symlink would have to happen on all slices.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *