|
|
@ -104,22 +104,69 @@ notes:
|
|
|
|
|
|
|
|
|
|
|
|
EXAMPLES = '''
|
|
|
|
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:
|
|
|
|
# Typical usage:
|
|
|
|
- name: Initialize the deploy root and gather facts
|
|
|
|
- name: Initialize the deploy root and gather facts
|
|
|
|
deploy_helper: path=/path/to/root
|
|
|
|
deploy_helper: path=/path/to/root
|
|
|
|
- name: Clone the project to the new release folder
|
|
|
|
- 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
|
|
|
|
- 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
|
|
|
|
- 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
|
|
|
|
- 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
|
|
|
|
deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize
|
|
|
|
|
|
|
|
|
|
|
|
# Retrieving facts before running a deploy
|
|
|
|
# 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
|
|
|
|
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
|
|
|
|
- name: Initialize the deploy root
|
|
|
|
deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=present
|
|
|
|
deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=present
|
|
|
|
|
|
|
|
|
|
|
@ -129,7 +176,7 @@ EXAMPLES = '''
|
|
|
|
shared_path=/var/www/shared
|
|
|
|
shared_path=/var/www/shared
|
|
|
|
current_path=/var/www/active
|
|
|
|
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=v1.1.1 state=present
|
|
|
|
- deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize
|
|
|
|
- deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize
|
|
|
|
|
|
|
|
|
|
|
@ -142,12 +189,22 @@ EXAMPLES = '''
|
|
|
|
# Postponing the cleanup of older builds:
|
|
|
|
# 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 release={{ deploy_helper.new_release }} state=finalize clean=False
|
|
|
|
- deploy_helper: path=/path/to/root state=clean
|
|
|
|
- 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:
|
|
|
|
# Keeping more old releases:
|
|
|
|
- deploy_helper: path=/path/to/root release={{ deploy_helper.new_release }} state=finalize keep_releases=10
|
|
|
|
- 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
|
|
|
|
- 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):
|
|
|
|
class DeployHelper(object):
|
|
|
|