# deploy_helper – Manages some of the steps common in deploying projects

- Synopsis

- Parameters

- Notes

- Examples

- Status

## 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` or `state=present` will return the `deploy_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

Parameter | Choices/Defaults | Comments
--- | --- | ---

clean
boolean

Choices:
- no
- yes ←

Whether to run the clean procedure in case of `state=finalize`.

current_path - | Default: "current" | the name of the symlink that is created when the deploy is finalized. Used in `finalize` and `clean`. Returned in the `deploy_helper.current_path` fact.
keep_releases - | Default: 5 | the number of old releases to keep when cleaning. Used in `finalize` and `clean`. Any unfinished builds will be deleted first, so only correct releases will count. The current version will not count.
path - / required |  | the root path of the project. Alias dest. Returned in the `deploy_helper.project_path` fact. aliases: dest
release - |  | the release version that is being deployed. Defaults to a timestamp format %Y%m%d%H%M%S (i.e. '20141119223359'). This parameter is optional during `state=present`, but needs to be set explicitly for `state=finalize`. You can use the generated fact `release={{ deploy_helper.new_release }}`.
releases_path - | Default: "releases" | the name of the folder that will hold the releases. This can be relative to `path` or absolute. Returned in the `deploy_helper.releases_path` fact.
shared_path - | Default: "shared" | the name of the folder that will hold the shared resources. This can be relative to `path` or absolute. If this is set to an empty string, no shared folder will be created. Returned in the `deploy_helper.shared_path` fact.

state
-

Choices:
- present ←
- finalize
- absent
- clean
- query

the state of the project. `query` will only gather facts, `present` will create the project root folder, and in it the releases and shared folders, `finalize` will remove the unfinished_filename file, create a symlink to the newly deployed release and optionally clean old releases, `clean` will remove failed & old releases, `absent` will remove the project folder (synonymous to the file module with `state=absent`)

unfinished_filename - | Default: "DEPLOY_UNFINISHED" | the name of the file that indicates a deploy has not finished. All folders in the releases_path that contain this file will be deleted on `state=finalize` with clean=True, or `state=clean`. This file is automatically deleted from the new_release_path during `state=finalize`.

## Notes

Note

- Facts are only returned for `state=query` and `state=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
      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_helper.new_release_path }}'
        version: v1.1.1
    - name: Add an unfinished file, to allow cleanup on successful finalize
      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
      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 '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' later
    - name: Initialize the deploy root
      deploy_helper:
        path: /path/to/root
        release: '{{ deploy_helper.new_release }}'
        state: present

    # all paths can be absolute or relative (to the 'path' parameter)
    - 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):
    - 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

    # Using a different unfinished_filename:
    - deploy_helper:
        path: /path/to/root
        unfinished_filename: README.md
        release: '{{ deploy_helper.new_release }}'
        state: finalize

    # 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, 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

## Status

- This module is not guaranteed to have a backwards compatible interface. [preview]

- This module is maintained by the Ansible Community. [community]

### Authors

- Ramon de la Fuente (@ramondelafuente)

Hint

If you notice any issues in this documentation, you can edit this document to improve it.