If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeYea... things go wrong. But, but, but! Ansistrano is cool because if something fails, the symlink will never change and the site will continue using the old code. If you're following our "Safe Migrations" philosophy, then deploying is even safer: if your migrations run, but the deploy never finishes, your non-destructive migrations won't hurt the current code.
But sometimes... a deploy will finish... only for you to have the sudden, horrible realization, that something is now massively wrong with the site. Like, there are zombies all over it or something.
At this moment, fate presents you with 3 options:
Other than running out of the building screaming, rolling back is the fastest way to escape the problem. And fortunately, Ansistrano has a second role all about... rolling back: ansistrano.rollback.
To install it, open the requirements.yml
file and add an entry. For the version... let's see. The latest version right now is 2.0.1
. Let's use that:
... lines 1 - 6 | |
- src: ansistrano.rollback | |
version: 2.0.1 |
Tip
Due to the changes in Ansible Galaxy, Ansistrano is installed now via ansistrano.rollback
instead of the old carlosbuenosvinos.ansistrano-rollback
.
To install the role, on your local terminal, run:
ansible-galaxy install -r ansible/requirements.yml
The rollback process will be its own, simple playbook. Create it: rollback.yml
. I'll open deploy.yml
so we can steal things... starting with the host. Then, of course, we need to include the new role: ansistrano.rollback
:
- hosts: aws | |
roles: | |
- ansistrano.rollback |
Rolling back is way simpler than deploying, but it works in the same way: there are a few stages and we override variables to control things. The only variable we need to override is ansistrano_deploy_to
. In deploy.yml
, we imported a vars_files
called vars.yml
, and used it to help set this.
Let's do basically the same thing here. Copy part of the vars_files
section, paste it, and just import vars.yml
: we don't need the vault:
- hosts: aws | |
vars_files: | |
- ./vars/vars.yml | |
... lines 6 - 13 |
Back in deploy.yml
, also steal ansistrano_deploy_to
and add that to rollback.yml
:
- hosts: aws | |
vars_files: | |
- ./vars/vars.yml | |
vars: | |
# Ansistrano vars | |
ansistrano_deploy_to: "{{ project_deploy_dir }}" # Base path to deploy to. | |
... lines 10 - 13 |
And... yea... that's basically it! So... let's try it! On the server, I'm already in /var/www/project
. My current
symlink is set, and releases
has 3 directories inside.
Back on your local terminal... rollback!
ansible-playbook ansible/rollback.yml -i ansible/hosts.ini
That's it. It should only take a few seconds. It does delete the old release directory, but this - like most things - can be controlled with a variable.
Done! Back on the server... yes! The symlink changed. And one of our releases is gone!
So rolling back is pretty easy. The most common issue involves migrations. Again, if you follow our "safe migrations" philosophy, you have nothing to worry about. But, if you're a bit more reckless - hey, no judgment - then you may need to manually run the down direction on some of your migrations after a rollback.
Tip
The variable is now called ansistrano_rollback_before_symlink_tasks_file
instead
of ansistrano_before_symlink_tasks_file
.
Let's add a little "opportunity" for us to do that. Let me show you: copy the ansistrano_before_symlink_tasks_file
variable. In rollback.yml
, paste this and set it to a new rollback/before-symlink.yml
:
- hosts: aws | |
... lines 3 - 6 | |
vars: | |
... lines 8 - 10 | |
# Hooks: custom tasks if you need them | |
ansistrano_before_symlink_tasks_file: '{{ playbook_dir }}/rollback/before-symlink.yml' | |
... lines 13 - 16 |
Now, create a new rollback/
directory with that file inside. Here, we'll add just one task: "Pause to run migrations manually down". Use the pause
module to freeze the playbook and put up a message:
- name: Pause to run migrations manually down | |
pause: | |
prompt: "Please, run 'bin/console doctrine:migrations:execute YYYYMMDDHHMMSS --down' manually in '{{ ansistrano_release_path.stdout }}' if needed and press enter to continue" |
This is our opportunity to manually execute any down migrations we want.
Hey, I know: it's not automated and it's not awesome. But, things have gone wrong, so it's time for us to take over.
Let's rollback one more time:
ansible-playbook ansible/rollback.yml -i ansible/hosts.ini
Here's the pause: it shows us the directory we should go into. Hit enter and it keeps going. Oh, and cool! It failed on one of the servers! That was unplanned... but awesome! That's the new server, and apparently we've only deployed there two times. So, there was no old version to rollback to. Ansistrano smartly prevented the rollback... instead of rolling back to nothing.
Ok guys... we're done! Woh! This tutorial was a crazy ride - I loved it! And I hope you did too. You can now deploy a killer Symfony site - or any site with Ansistrano. If this was all interesting but felt like a lot of work, don't forget about the platform-as-a-service options like Heroku or Platform.sh. You don't have quite as much flexibility, and they're sometimes a bit more expensive, but a lot of what we learned is handled for you and you can get started really quickly.
Whatever you choose, go forth and build something awesome! Ok guys, I'll seeya next time!
Hey guys:
First of all, happy new year. I hope you have spent a nice holidays.
I was wondering if you are going to update the Ansistrano tutorial using Symfony 5. This has been one of the most useful courses for me and I think I am probably missing something in the configuration to explote all the potential in Symfony 5, maybe with the cache.
Are you planning to do this? Or at least put some little useful notes in the scripts?
Cesar
Hey Cesar!
Happy new year to you too! We did have nice holidays - I always enjoy a bit of quiet around the new year :).
We don't currently have any plans to update this course to Symfony 5, or, it's at least not a priority. But yes, we *do* typically like to add useful notes to tutorials to help extend their usefulness. This might be an opportunity for that!
> I am probably missing something in the configuration to explote all the potential in Symfony 5, maybe with the cache.
What makes you think that you are missing some Symfony 5 potential? Are you seeing errors? Poor performance? Something else?
Let me know :).
Cheers!
Hey Ryan
Thanks for answering!
Sometimes I have errors in the deployment in the part of composer dependencies or in warming up the cache. I didn't identify why but the funny thing is when I run the deploy playbook again, it works perfectly. I don't have the type of errors now but next time I will probably tell you with more details.
My question was more a general wonder. For example, some tweaks to the code like you did in chapter 16. I am not an expert, I just follow your tutorials and things work. That's why I like Symfony.
Cheers.
Cesar
Hey Cesar!
> Sometimes I have errors in the deployment in the part of composer dependencies or in warming up the cache. I didn't identify why but the funny thing is when I run the deploy playbook again, it works perfectly
Got it :). Let us know if/when you see those error again - it's always possible it's something we could address with a note on the tutorial.
> My question was more a general wonder. For example, some tweaks to the code like you did in chapter 16.
Yea... obviously it's hard to think of *all* the possible things that might be different on a Symfony 5.2 app for this tutorial, but not a *lot* of things come to mind... at least not major things. The cache topic you linked to is actually one of the spots that "has" changed the most of the past few years. But actually, that chapter (I believe) is still accurate: if you warm up your cache AND have apcu or Opcache, then nothing "should" be written to your filesystem. That is still true - it had only just recently "become" true when we made this tutorial.
Anyways, that's not a complete answer, but I hope it helps :). Obviously there will be other differences like parameters.yml vs .env files, though it shouldn't make a huge difference. On that topic, I probably would now use Symfony's secrets system instead of Ansible's vault... just because it would make your life a bit easier.
Cheers!
// composer.json
{
"require": {
"php": ">=5.5.9",
"doctrine/doctrine-bundle": "^1.6", // 1.6.8
"doctrine/orm": "^2.5", // v2.7.2
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"sensio/distribution-bundle": "^5.0.19", // v5.0.20
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.26
"symfony/monolog-bundle": "^3.1.0", // v3.1.0
"symfony/polyfill-apcu": "^1.0", // v1.4.0
"symfony/swiftmailer-bundle": "^2.3.10", // v2.6.3
"symfony/symfony": "3.3.*", // v3.3.5
"twig/twig": "^1.0||^2.0", // v1.34.4
"doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.1
"predis/predis": "^1.1", // v1.1.1
"composer/package-versions-deprecated": "^1.11" // 1.11.99
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.1.6
"symfony/phpunit-bridge": "^3.0", // v3.3.5
"doctrine/data-fixtures": "^1.1", // 1.3.3
"hautelook/alice-bundle": "^1.3" // v1.4.1
}
}
# ansible/requirements.yml
-
src: DavidWittman.redis
version: 1.2.4
-
src: ansistrano.deploy
version: 2.7.0
-
src: ansistrano.rollback
version: 2.0.1
Hi,
I just stumbled upon an updated var name for rollback:
ansistrano_rollback_before_symlink_tasks_file instead of the one mentioned in the script ( ansistrano_before_symlink_tasks_file).
Thanks for all.
Cheers
J