diff --git a/web_infrastructure/deploy_helper.py b/web_infrastructure/deploy_helper.py index 21c238d255b..ce36478020d 100644 --- a/web_infrastructure/deploy_helper.py +++ b/web_infrastructure/deploy_helper.py @@ -104,22 +104,69 @@ notes: EXAMPLES = ''' +# General explanation, starting with an example folder structure for a project: + +root: + releases: + - 20140415234508 + - 20140415235146 + - 20140416082818 + + shared: + - sessions + - uploads + + current: -> releases/20140416082818 + + +The 'releases' folder holds all the available releases. A release is a complete build of the application being +deployed. This can be a clone of a repository for example, or a sync of a local folder on your filesystem. +Having timestamped folders is one way of having distinct releases, but you could choose your own strategy like +git tags or commit hashes. + +During a deploy, a new folder should be created in the releases folder and any build steps required should be +performed. Once the new build is ready, the deploy procedure is 'finalized' by replacing the 'current' symlink +with a link to this build. + +The 'shared' folder holds any resource that is shared between releases. Examples of this are web-server +session files, or files uploaded by users of your application. It's quite common to have symlinks from a release +folder pointing to a shared/subfolder, and creating these links would be automated as part of the build steps. + +The 'current' symlink points to one of the releases. Probably the latest one, unless a deploy is in progress. +The web-server's root for the project will go through this symlink, so the 'downtime' when switching to a new +release is reduced to the time it takes to switch the link. + +To distinguish between successful builds and unfinished ones, a file can be placed in the folder of the release +that is currently in progress. The existence of this file will mark it as unfinished, and allow an automated +procedure to remove it during cleanup. + + # Typical usage: - name: Initialize the deploy root and gather facts deploy_helper: path=/path/to/root - name: Clone the project to the new release folder - git: repo=git://foosball.example.org/path/to/repo.git dest={{ deploy.new_release_path }} version=v1.1.1" + git: repo=git://foosball.example.org/path/to/repo.git dest={{ deploy_helper.new_release_path }} version=v1.1.1 - name: Add an unfinished file, to allow cleanup on successful finalize - file: path={{ deploy.new_release_path }}/{{ deploy.unfinished_filename }} state=touch + file: path={{ deploy_helper.new_release_path }}/{{ deploy_helper.unfinished_filename }} state=touch - name: Perform some build steps, like running your dependency manager for example - composer: command=install working_dir={{ deploy.new_release_path }} + composer: command=install working_dir={{ deploy_helper.new_release_path }} +- name: Create some folders in the shared folder + file: path='{{ deploy_helper.shared_path }}/{{ item }}' state=directory + with_items: ['sessions', 'uploads'] +- name: Add symlinks from the new release to the shared folder + file: path='{{ deploy_helper.new_release_path }}/{{ item.path }}' + src='{{ deploy_helper.shared_path }}/{{ item.src }}' + state=link + with_items: + - { path: "app/sessions", src: "sessions" } + - { path: "web/uploads", src: "uploads" } - name: Finalize the deploy, removing the unfinished file and switching the symlink deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize # Retrieving facts before running a deploy -- name: Run query to gather facts without changing anything +- name: Run 'state=query' to gather facts without changing anything deploy_helper: path=/path/to/root state=query - # Remember to set the 'release' parameter when you actually call state=present +# Remember to set the 'release' parameter when you actually call 'state=present' later - name: Initialize the deploy root deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=present @@ -129,7 +176,7 @@ EXAMPLES = ''' shared_path=/var/www/shared current_path=/var/www/active -# Using your own naming strategy: +# Using your own naming strategy for releases (a version tag in this case): - deploy_helper: path=/path/to/root release=v1.1.1 state=present - deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize @@ -142,12 +189,22 @@ EXAMPLES = ''' # Postponing the cleanup of older builds: - deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize clean=False - deploy_helper: path=/path/to/root state=clean +# Or running the cleanup ahead of the new deploy +- deploy_helper: path=/path/to/root state=clean +- deploy_helper: path=/path/to/root state=present # Keeping more old releases: - deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize keep_releases=10 -# Or: +# Or, if you use 'clean=false' on finalize: - deploy_helper: path=/path/to/root state=clean keep_releases=10 +# Removing the entire project root folder +- deploy_helper: path=/path/to/root state=absent + +# Debugging the facts returned by the module +- deploy_helper: path=/path/to/root +- debug: var=deploy_helper + ''' class DeployHelper(object):