Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling failures with Fabric

I'm trying to handle failure on fabric, but the example I saw on the docs was too localized for my taste. I need to execute rollback actions if any of a number of actions fail. I tried, then, to use contexts to handle it, like this:

@_contextmanager
def failwrapper():
    with settings(warn_only=True):
        result = yield
    if result.failed:
        rollback()
        abort("********* Failed to execute deploy! *********")

And then

@task
def deploy():
    with failwrapper():
        updateCode()
        migrateDb()
        restartServer()

Unfortunately, when one of these tasks fail, I do not get anything on result.

Is there any way of accomplishing this? Or is there another way of handling such situations?

like image 416
Daniel C. Sobral Avatar asked May 31 '12 03:05

Daniel C. Sobral


2 Answers

According to my tests, you can accomplish that with this:

from contextlib import contextmanager

@contextmanager
def failwrapper():
    try:
        yield
    except SystemExit:
        rollback()
        abort("********* Failed to execute deploy! *********")

As you can see I got rid of the warn_only setting as I suppose you don't need it if the rollback can be executed and you're aborting the execution anyway with abort().

Fabric raises SystemExit exception when encountering errors and warn_only setting is not used. We can just catch the exception and do the rollback.

like image 77
Henri Siponen Avatar answered Oct 06 '22 22:10

Henri Siponen


Following on from Henri's answer, this also handles keyboard interrupts (Ctrl-C) and other exceptions:

@_contextmanager
def failwrapper():
    try:
        yield
    except:
        rollback()
        raise
like image 33
Kristopher Johnson Avatar answered Oct 06 '22 23:10

Kristopher Johnson