Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Rolling back to previous release #9

Open
thelucid opened this Issue · 20 comments

16 participants

Jamie Hill Michael Galero Rico Sta. Cruz clodeindustrie Raphael Randschau Nihad Abbasov Nathan Bertram Gabrijel Škoro Vinh Quốc Nguyễn mbahar Tyler Mandry Daniel R. railsme Jérémy FRERE Joshua Muheim Dieulivol
Jamie Hill

I am currently using Vlad and Mina looks like a much cleaner alternative as Vlad isn't maintained much anymore.

I might be missing something obvious but is there a way to roll back to a previous release?

Michael Galero
Owner

Not yet. But it's next in our list:

https://trello.com/c/tdnUZtqL

Jamie Hill

Great, thanks.

I must say, I've just switched my first project to Mina from Vlad which was largely painless and the deployment is much simpler all in all. Many thanks for a great project.

One other problem I ran into was when some existing Vlad releases existed and I ran mina deploy:cleanup, it completely blitzed my current release, leaving no current release... this was a bit of a showstopper and deploys wouldn't work until I manually cleaned up the releases directory.

One other small niggle is that I'm not keen on the to :launch etc. syntax, it's not entirely clear what is going on... maybe just an explicit method that excepts a block would be better e.g.

task :deploy do
  deploy do
    # Put things that prepare the empty release folder here.
    # Commands queued here will be ran on a new release directory.
    invoke :'git:clone'
    invoke :'bundle:install'

    # These are instructions to start the app after it's been prepared.
    restart do
      queue 'touch tmp/restart.txt'
    end

    # This optional block defines how a broken release should be cleaned up.
    clean do
      queue 'log "failed deployment"'
    end
  end
end
Rico Sta. Cruz
Owner

re: the :launch syntax:

that's my invention and I hate it myself! we've been toying with the idea of changing it to simply:

task :deploy do
  deploy do
    invoke :'git:clone'
    invoke :'other:things:here'
  end
end

task :restart do
  queue "sudo service myapp restart"
end

... that is, simply assuming that the :restart task is the way to restart it. This way, you also get a bonus of getting to implement mina restart in a nice, conveniently DRY manner.

Comments and suggestions welcome.

Jamie Hill

Yes, much prefer that. I guess the same could be true for the "clean" block i.e. this could also become it's own task?

I'm trying to think of a way to remove the "deploy" block also to save on the additional nesting as essentially all it does it run the "deploy.sh.erb" stuff after yielding the block. Maybe the stuff in "deploy.sh.erb" could be made into another standard task (I'm thinking "update" like Vlad does), it could then use the queue method etc. to run all those bits. Just a thought.

Once everything is a standard task, the "deploy" task could be as simple as:

task :deploy => [:'git:clone', :'bundle:install', :'rails:db_migrate', :'other:stuff', :update, :restart]

I would actually like to see simpler task names as whichever scm you are using, there will be a clone/checkout stage, some kind of database migration is usually needed whichever language/framework you are using (could be blank task by default) and the "bundle:install" task could be the default for the "bundle" namespace... we would end up with something like:

task :deploy => [:clone, :bundle, :migrate, :update, :restart]

Much cleaner... most or if not all of this can be achieved without breaking the existing functionality, what do you think? I'm happy to have a crack at this if you are in agreement.

I will be writing a blog post on Mina soon over at http://thelucid.com as I'm loving it compared to Vlad or Capistrano so might hold off for a few days if there are likely to be implementation changes.

Rico Sta. Cruz
Owner
task :deploy => [:'git:clone', :'bundle:install', :'rails:db_migrate', :'other:stuff', :update, :restart]

This Cap/Vlad-like syntax is not going to happen, sorry. Let me explain, though... it's part of what makes Mina special.

Right now, you can chain tasks in that way. For instance, you may do the following, which makes mina slow_deploy work the same as doing mina local:test deploy remote:test.

task :slow_deploy => [:'local:test', :deploy, :'remote:test']

However, deploying is something different. Most Mina tasks are merely used to queue lines of Bash code in. This concept is incredibly simple:

task :tail do
  queue "echo Checking error logs"
  queue "tail -f /var/www/error.log"
end

# invoking "mina tail" simply runs the following bash script remotely.
# You can verify this with "mina --simulate":
#
#     echo Checking error logs
#     tail -f /var/www/error.log
#

In a deployment, you have to wrap your invokes and queues inside a deploy do ... end block. This certain deploy script below illustrates the point:

task :deploy do
  deploy do
    queue "wget http://foo.com/my_latest_code.tgz"
    queue "tar xvf my_latest_code.tgz"
  end
end

Running this via --simulate tells you that it concatenates the code very differently:

#!/usr/bin/env sh
cd /var/www/myproject.com
echo "-----> Creating build path..."
mkdir -p tmp/build-283943
echo "-----> Doing deploys..."
cd tmp/build-283943 &&
(
  wget http://foo.com/my_latest_code.tgz
) && (
  tar xvf my_latest_code.tgz
) && (
  echo "----> Deploy succeeded!"
) || (
  echo "! Deploy failed, rolling back"
  rm -rf tmp/build-283943
  exit 256
)

...of course, the actual script is much longer, but I've shorted it to illustrate the point.

What happened here? The deploy do...end block captured your queued items and put them together differently by placing it into a deploy script boilerplate.

You will not be able to do this simply by task :deploy => [:one, :two, :three].

Rico Sta. Cruz
Owner

Also, I would say no on the shortening of task names. It provides no value and makes the abstraction deeper than it actually should be. Can you just swap SCM addons (from git to svn, for instance) and expect everything to work? Can you make another "app framework" addon that implements its own migrate + bundle (and so on) and swap them out at will? Probably not.

Renaming them to generic names (eg, migrate meaning to simply invoke any migrations it should do, versus rails:db_migrate which specifically invokes database migrations for rails projects) only gives us another layer of abstraction that's not necessary. Today, one glance at a deploy block lets you somewhat figure out what a deploy script actually does, whereas if they were generic names, you would have to look up the definitions for each name to figure out what each would do.

Jamie Hill

Fair enough.

Did you go with assuming a restart task instead of the launch block in the end? If so what about the clean block, couldn't this assume a clean task also?

clodeindustrie

Hi there,

Has any work been started regarding the rollback feature?

Raphael Randschau

:+1: for this feature! But it's quite easy to just DIY, right?

Nihad Abbasov

@rstacruz is there any ETA for this feature?

Gabrijel Škoro
Owner

+1

Vinh Quốc Nguyễn

Bump this up. It's over 2 years and seems nobody put it a good care.
I think we should make this a simple

mina rollback

what it does it simply remove the last releast, re-point symlink to the previous releas.

And move on.

mbahar

you can use this to roll back;

but be carefull; if you rollback more than the number of deployed releases; you will get NIL

desc "Roll backs the lates release"
task :rollback => :environment do

queue! %[echo "-----> Rolling back to previous release for instance: #{domain}"]

# remove latest release folder (active release)
queue %[echo "-----> Deleting active release : "]
queue %[ls "#{deploy_to}/releases" -Art | sort | tail -n 1]
queue! %[ls "#{deploy_to}/releases" -Art | sort | tail -n 1 | xargs -I active sudo rm -rf "#{deploy_to}/releases/active"]

# delete existing sym link and create a new symlink pointing to the previous release
queue %[echo "-----> Creating new symlink from the previous release: "]
queue %[ls "#{deploy_to}/releases" -Art | sort | tail -n 1]
queue! %[sudo rm "#{deploy_to}/current"]
queue! %[ls -Art "#{deploy_to}/releases" | sort | tail -n 1 | xargs -I active sudo ln -s "#{deploy_to}/releases/active" "#{deploy_to}/current"]

end

Tyler Mandry

Here's an improved version of the above script. It switches the release atomically and doesn't use sudo.

desc "Rolls back the latest release"
task :rollback => :environment do
  queue! %[echo "-----> Rolling back to previous release for instance: #{domain}"]

  # Delete existing sym link and create a new symlink pointing to the previous release
  queue %[echo -n "-----> Creating new symlink from the previous release: "]
  queue %[ls "#{deploy_to}/releases" -Art | sort | tail -n 2 | head -n 1]
  queue! %[ls -Art "#{deploy_to}/releases" | sort | tail -n 2 | head -n 1 | xargs -I active ln -nfs "#{deploy_to}/releases/active" "#{deploy_to}/current"]

  # Remove latest release folder (active release)
  queue %[echo -n "-----> Deleting active release: "]
  queue %[ls "#{deploy_to}/releases" -Art | sort | tail -n 1]
  queue! %[ls "#{deploy_to}/releases" -Art | sort | tail -n 1 | xargs -I active rm -rf "#{deploy_to}/releases/active"]
end
Daniel R.

+1 would be a great addition for using mina/rails. Ive been using mina for 1.5 years now for sinatra apps. the first time now with rails. capistrano is a pain

railsme

what about migrations?

Jérémy FRERE

+1 for integrating it in mina. Anyway, thanks for the task @tmandry :)

Joshua Muheim

+1

Dieulivol

+1, Thanks @tmandry !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.