Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ansible project-deploy (NomadPHP lightning talk)

"A re-usable Ansible role to deploy projects".

Ansible is a provisioning tool rapidly growing in popularity, mainly due to it’s simplicity. But it’s capable of more than just provisioning! In this talk, I’ll walk you through an Ansible role that can be used to deploy your projects. Those familiar with Capistrano wil recognize the method, but I’ll explain it step by step and in the end I’ll show a real-world example from a Symfony2 project: the SweetlakePHP website. (this talk assumes some knowledge of how Ansible works)

  • Login to see the comments

Ansible project-deploy (NomadPHP lightning talk)

  1. 1. ANSIBLE-PROJECT-DEPLOY a re-usable Ansible role to deploy projects
  2. 2. ABOUT US 2 Ramon de la Fuente @f_u_e_n_t_e Jasper N. Brouwer @jaspernbrouwer Future500 B.V.
  3. 3. THE PROBLEM 3
  4. 4. THE PROBLEM • Continuous deployment • Easy maintenance of the deploy procedure. • Small learning curve. • Reuse between projects with little effort. 4
  5. 5. WHAT IS A DEPLOY? 5
  6. 6. WHAT IS A DEPLOY? Directory structure: . !"" releases | !"" 20140415234508 | #"" 20140415235146 !"" shared | !"" sessions | !"" source | #"" uploads #"" current -> releases/20140415235146 6
  7. 7. WHAT IS A DEPLOY? Directory structure: . !"" releases | !"" 20140415234508 | #"" 20140415235146 !"" shared | !"" sessions | !"" source | #"" uploads #"" current -> releases/20140415235146 7
  8. 8. WHAT IS A DEPLOY? 1. Update the codebase + configuration 8
  9. 9. WHAT IS A DEPLOY? 1. Update the codebase + configuration 2. Install dependencies 9
  10. 10. WHAT IS A DEPLOY? 1. Update the codebase + configuration 2. Install dependencies 3. Preserve shared resources 10
  11. 11. WHAT IS A DEPLOY? 1. Update the codebase + configuration 2. Install dependencies 3. Preserve shared resources 4. Build tasks 11
  12. 12. WHAT IS A DEPLOY? 1. Update the codebase + configuration 2. Install dependencies 3. Preserve shared resources 4. Build tasks 5. Finalize 12
  13. 13. THE ROLE 13 https://galaxy.ansible.com/list#/roles/732 project_deploy
  14. 14. ROLE WALKTHROUGH 14
  15. 15. ROLE WALKTHROUGH ! Deploy module variables: ! deploy: project_path current_path releases_path shared_path last_release last_release_path new_release new_release_path unfinished_filename ! ! 15
  16. 16. ROLE WALKTHROUGH ! Deploy module variables: ! deploy: project_path: /path/to/project/ current_path: /path/to/project/current releases_path: /path/to/project/releases shared_path: /path/to/project/shared last_release: 20140415234508 last_release_path: /path/to/project/releases/20140415234508 new_release: 20140415235146 new_release_path: /path/to/project/releases/20140415235146 unfinished_filename: DEPLOY_UNFINISHED Used as: {{ deploy.new_release }} 16
  17. 17. 1. UPDATETHE CODEBASE ! - name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' ! - name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' ! 17
  18. 18. 1. UPDATETHE CODEBASE ! - name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' ! - name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' ! 18
  19. 19. 1. UPDATETHE CODEBASE ! - name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' ! - name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' ! 19
  20. 20. 1. UPDATETHE CODEBASE ! - name: Write unfinished file file: path={{ project_source_path }}/{{ deploy.unfinished_filename }} state=touch ! - name: Copy files to new build dir command: "cp -pr {{ project_source_path }} {{ deploy.new_release_path }}" ! - name: Remove unwanted files/folders from new release file: path={{ deploy.new_release_path }}/{{ item }} state=absent with_items: project_unwanted_items 20
  21. 21. 1. UPDATETHE CONFIG FILES ! - name: Copy project files copy: src={{ item.src }} dest={{ deploy.new_release_path }}/{{ item.dest }} mode={{ item.mode|default('0644') }} with_items: project_files ! - name: Copy project templates template: src={{ item.src }} dest={{ deploy.new_release_path }}/{{ item.dest }} mode={{ item.mode|default('0644') }} with_items: project_templates 21
  22. 22. 2. INSTALL DEPENDENCIES ! - name: Do composer install command: "{{ project_command_for_composer_install }} chdir=…" environment: project_environment when: project_has_composer ! - name: Do npm install command: "{{ project_command_for_npm_install }} chdir=…" environment: project_environment when: project_has_npm ! - name: Do bower install command: "{{ project_command_for_bower_install }} chdir=…" environment: project_environment when: project_has_bower 22
  23. 23. 2. INSTALL DEPENDENCIES ! - name: Do composer install command: "{{ project_command_for_composer_install }} chdir=…" environment: project_environment when: project_has_composer ! - name: Do npm install command: "{{ project_command_for_npm_install }} chdir=…" environment: project_environment when: project_has_npm ! - name: Do bower install command: "{{ project_command_for_bower_install }} chdir=…" environment: project_environment when: project_has_bower 23
  24. 24. 3. SHARED RESOURCES ! - name: Ensure shared sources are present file: "path='{{ deploy.shared_path }}/{{ item.src }}' state={{ item.type }}“ with_items: project_shared_children ! - name: Ensure shared paths are absent file: "path='{{ deploy.new_release_path }}/{{ item.path }}' state=absent" with_items: project_shared_children ! - name: Create shared symlinks file: path='{{ deploy.new_release_path }}/{{ item.path }}' src='{{ deploy.shared_path }}/{{ item.src }}' state=link" with_items: project_shared_children 24
  25. 25. 4. BUILD STEPS ! - name: Run post_build_commands in the new_release_path command: "{{ item }} chdir={{ deploy.new_release_path }}" with_items: project_post_build_commands environment: project_environment 25
  26. 26. 4. BUILD STEPS ! - name: Run post_build_commands in the new_release_path command: "{{ item }} chdir={{ deploy.new_release_path }}" with_items: project_post_build_commands environment: project_environment 26 ! project_post_build_commands: - "app/console cache:clear" - "app/console assets:install" - "app/console assetic:dump"
  27. 27. 5. FINALIZE ! - name: Remove unfinished file file: path={{ deploy.new_release_path }}/{{ deploy.unfinished_filename }} state=absent when: project_finalize ! - name: Finalize the deploy file: src={{ deploy.new_release_path }} dest={{ deploy.current_path }} state=link when: project_finalize 27
  28. 28. 28
  29. 29. IT’S NOT COMPLICATED! • Only 75 lines • Number of tasks: 18 • Variables to configure: 24 29
  30. 30. EXAMPLE PLAYBOOK 30
  31. 31. EXAMPLE PLAYBOOK ! - name: Deploy the application hosts: production remote_user: "{{ production_deploy_user }}" sudo: no ! vars: project_root: "{{ sweetlakephp_root }}" project_git_repo: "{{ sweetlakephp_github_repo }}" project_deploy_strategy: git 31
  32. 32. EXAMPLE PLAYBOOK ! - name: Deploy the application hosts: production remote_user: "{{ production_deploy_user }}" sudo: no ! vars: project_root: "{{ sweetlakephp_root }}" project_git_repo: "{{ sweetlakephp_github_repo }}" project_deploy_strategy: git ! project_environment: SYMFONY_ENV: "prod" 32
  33. 33. EXAMPLE PLAYBOOK ! project_environment: SYMFONY_ENV: "prod" ! project_shared_children: - path: "/app/sessions" src: "sessions" - path: "/web/uploads" src: "uploads" ! project_templates: - name: parameters.yml src: "templates/parameters_prod.yml.j2" dest: "/app/config/parameters_prod.yml" ! 33
  34. 34. EXAMPLE PLAYBOOK ! project_environment: SYMFONY_ENV: "prod" ! project_shared_children: - path: "/app/sessions" src: "sessions" - path: "/web/uploads" src: "uploads" ! project_templates: - name: parameters.yml src: "templates/parameters_prod.yml.j2" dest: "/app/config/parameters_prod.yml" ! 34
  35. 35. EXAMPLE PLAYBOOK ! project_has_composer: yes ! project_post_build_commands: - "php vendor/sensio/…/DistributionBundle/…/bin/build_bootstrap.php” - "app/console cache:clear" - "app/console doctrine:migrations:migrate --no-interaction" - "app/console assets:install" - "app/console assetic:dump" ! roles: - f500.project_deploy ! post_tasks: - name: Remove old releases deploy: "path={{ project_root }} state=clean" 35
  36. 36. EXAMPLE PLAYBOOK ! project_has_composer: yes ! project_post_build_commands: - "php vendor/sensio/…/DistributionBundle/…/bin/build_bootstrap.php” - "app/console cache:clear" - "app/console doctrine:migrations:migrate --no-interaction" - "app/console assets:install" - "app/console assetic:dump" ! roles: - f500.project_deploy ! post_tasks: - name: Remove old releases deploy: "path={{ project_root }} state=clean" 36
  37. 37. THANKYOU! 37 Feedback: https://joind.in/11570 https://github.com/f500/ansible-project_deploy

×