Search code examples
rubygitcapistrano

Tagging release before deploying with Capistrano


I'm looking to build a nice little Capistrano recipe for deploying sites version controlled in Git.

In addition to some other things I'm working on adding, my first task is to tag the current release with the current date...and when that tag already exists (e.g. multiple releases in a day), append a letter.

I've written some working code, and I've tested it in my production.rb (using multistage in capistrano-ext)...but I have to think I could have written this better. For one, there's some huge repetition in the actual checking for existence of a tag. However, no matter what order I move things around, this is the only configuration that produces results.

Any ideas? Thanks in advance.

before 'deploy' do
  # Tag name is build_YYYYMMDD
  tag_name = "build_#{Time.now.strftime('%Y%m%d')}"
  check_tag = `git tag -l #{tag_name}`
  # If the tag exists, being appending letter suffix
  if not check_tag.empty?
    suffix = 'a'
    check_tag = `git tag -l #{tag_name}#{suffix}`
    while not check_tag.empty? do
      suffix.next!
      check_tag = `git tag -l #{tag_name}#{suffix}`
    end
    tag_name = "#{tag_name}#{suffix}"
  end
  # Tag with computed tag name
  p "Tagging #{tag_name}" # TODO How to output via Capistrano?
  system "git tag #{tag_name}"
  # Push tags to origin remote
  p "Pushing tag to origin" # TODO How to output via Capistrano?
  system "git push origin master --tags"
end

Solution

  • I've done something similar with Capistrano. The easiest thing to do is tag using the timestamp name that Capistrano used during the deploy - that's YYYYMMDDHHMMSS, so it's really hard to get duplicates.

    Example:

    task :push_deploy_tag do
      user = `git config --get user.name`.chomp
      email = `git config --get user.email`.chomp
      puts `git tag #{stage}_#{release_name} #{current_revision} -m "Deployed by #{user} <#{email}>"`
      puts `git push --tags origin`
    end