community.general.deploy_helper – Manages some of the steps common in deploying projects.¶
Note
This plugin is part of the community.general collection (version 2.5.1).
To install it use: ansible-galaxy collection install community.general
.
To use it in a playbook, specify: community.general.deploy_helper
.
Synopsis¶
The Deploy Helper manages some of the steps common in deploying software. It creates a folder structure, manages a symlink for the current release and cleans up old releases.
Running it with the
state=query
orstate=present
will return thedeploy_helper
fact.project_path
, whatever you set in the path parameter,current_path
, the path to the symlink that points to the active release,releases_path
, the path to the folder to keep releases in,shared_path
, the path to the folder to keep shared resources in,unfinished_filename
, the file to check for to recognize unfinished builds,previous_release
, the release the ‘current’ symlink is pointing to,previous_release_path
, the full path to the ‘current’ symlink target,new_release
, either the ‘release’ parameter or a generated timestamp,new_release_path
, the path to the new release folder (not created by the module).
Parameters¶
Notes¶
Note
Facts are only returned for
state=query
andstate=present
. If you use both, you should pass any overridden parameters to both calls, otherwise the second call will overwrite the facts of the first one.When using
state=clean
, the releases are ordered by creation date. You should be able to switch to a new naming strategy without problems.Because of the default behaviour of generating the new_release fact, this module will not be idempotent unless you pass your own release name with
release
. Due to the nature of deploying software, this should not be much of a problem.
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
community.general.deploy_helper:
path: /path/to/root
- name: Clone the project to the new release folder
ansible.builtin.git:
repo: ansible.builtin.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
ansible.builtin.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_helper.new_release_path }}'
- name: Create some folders in the shared folder
ansible.builtin.file:
path: '{{ deploy_helper.shared_path }}/{{ item }}'
state: directory
with_items:
- sessions
- uploads
- name: Add symlinks from the new release to the shared folder
ansible.builtin.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
community.general.deploy_helper:
path: /path/to/root
release: '{{ deploy_helper.new_release }}'
state: finalize
# Retrieving facts before running a deploy
- name: Run 'state=query' to gather facts without changing anything
community.general.deploy_helper:
path: /path/to/root
state: query
# Remember to set the 'release' parameter when you actually call 'state=present' later
- name: Initialize the deploy root
community.general.deploy_helper:
path: /path/to/root
release: '{{ deploy_helper.new_release }}'
state: present
# all paths can be absolute or relative (to the 'path' parameter)
- community.general.deploy_helper:
path: /path/to/root
releases_path: /var/www/project/releases
shared_path: /var/www/shared
current_path: /var/www/active
# Using your own naming strategy for releases (a version tag in this case):
- community.general.deploy_helper:
path: /path/to/root
release: v1.1.1
state: present
- community.general.deploy_helper:
path: /path/to/root
release: '{{ deploy_helper.new_release }}'
state: finalize
# Using a different unfinished_filename:
- community.general.deploy_helper:
path: /path/to/root
unfinished_filename: README.md
release: '{{ deploy_helper.new_release }}'
state: finalize
# Postponing the cleanup of older builds:
- community.general.deploy_helper:
path: /path/to/root
release: '{{ deploy_helper.new_release }}'
state: finalize
clean: False
- community.general.deploy_helper:
path: /path/to/root
state: clean
# Or running the cleanup ahead of the new deploy
- community.general.deploy_helper:
path: /path/to/root
state: clean
- community.general.deploy_helper:
path: /path/to/root
state: present
# Keeping more old releases:
- community.general.deploy_helper:
path: /path/to/root
release: '{{ deploy_helper.new_release }}'
state: finalize
keep_releases: 10
# Or, if you use 'clean=false' on finalize:
- community.general.deploy_helper:
path: /path/to/root
state: clean
keep_releases: 10
# Removing the entire project root folder
- community.general.deploy_helper:
path: /path/to/root
state: absent
# Debugging the facts returned by the module
- community.general.deploy_helper:
path: /path/to/root
- ansible.builtin.debug:
var: deploy_helper
Authors¶
Ramon de la Fuente (@ramondelafuente)