Search code examples
rubydeploymentcapistranowebistrano

Capistrano recipe to automatically run deploy:cleanup only when needed


We do over 20 deployments a day using capistrano (actually webistrano) and we have a problem where the disk space on our servers get full of old deployment folders.

Every now and again I run the deploy:cleanup task to clean out all deployments (it keeps the last :keep_releases, currently set to 30). I would like to automate the cleanup.

One solution would be to add the following to the recipe to automatically run the cleanup after every deployment:

after "deploy", "deploy:cleanup"

But, I don't want to do this after every deployment, I'd like to limit it to only when the number of previous deployments gets to a threashold, e.g. 70. Does anyone know how I can do this?


Thoughts:

  • Does Capistrano provide a variable that holds the number of previous deployments?
    • If not, does anyone know a way to calculate it. i.e. set :num_releases, <what-can-I-put-here-to-count-previous-deployments>
  • Is there a way to pimp deploy:cleanup so it uses a minimum threshold, i.e. exit if < :max_releases previous deployments (where :max_releases is different from :keep_releases).
  • Could the except keyword be used? i.e. something like :except => { :num_releases < 70}.

Solution

  • Does Capistrano provide a variable that holds the number of previous deployments?

    Yes, releases.length

    Is there a way to pimp deploy:cleanup so it uses a minimum threshold?

    Yes, here is a privately namespaced task that will trigger the normal cleanup task ONLY if a certain number of release folders have built up:

    namespace :mystuff do
      task :mycleanup, :except => { :no_release => true } do
        thresh = fetch(:cleanup_threshold, 70).to_i
        if releases.length > thresh
          logger.info "Threshold of #{thresh} releases reached, runing deploy:cleanup."
          deploy.cleanup
        end
      end
    end
    

    To have this run automatically after a deploy, put this at the top of the recipe:

    after "deploy", "mystuff:mycleanup"
    

    The good thing about this is that, before and after directives set on deploy:cleanup are executed as normal. For example we require the following:

    before 'deploy:cleanup', 'mystuff:prepare_cleanup_permissions'
    after 'deploy:cleanup', 'mystuff:restore_cleanup_permissions'