# Deli

Provides a deploy task for Elixir applications, using a couple of [`edeliver`]( [tasks]( under the hood.

Releases are built using [distillery](, locally, through docker.

Git tags are autogenerated, and `deli` will ask to bump app version, if there are new commits since last version bump. You can switch to a custom versioning strategy if that's not good.

## Configuration

Add `deli` to your deps:

def deps do
    # ...
    {:deli, "~> 0.1.28", runtime: false}

You don't need to add `edeliver` or `distillery`, as they're already included.

No need for edeliver config (for basic scenario). You will need to [setup distillery](

Then add some configuration in your `config/config.exs`:

config :deli,
  hosts: [
    staging: [
    prod: [

See [`lib/deli/config.ex`]( for all configuration options (and their defaults).

## Deploy

$ mix deli

The task above does full cycle deploy:

- Create a local build env
- Build release in this env
- Deploys release to target env hosts
- Restart each app in target hosts, and check their status

It will assume `staging` environment by default.

To target `prod` environment, do:

$ mix deli -t prod

It will ask for confirmation after release is built, before deploy.
If you don't want that extra step, pass `-y` when calling this task.

### Other tasks provided by deli

# Starts all hosts for target prod
$ mix deli.start -t prod

# Stops all hosts for target prod, without confirmation
$ mix deli.stop -t prod -y

# Restarts all hosts for target staging that match ~r/02/
$ mix deli.restart -h 02

# Cleans autogenerated config files
$ mix deli.clean

# Does only docker release phase
$ mix deli.release

# Does only deploy/restart/check (release should be available)
$ mix deli.deploy

# Checks status
$ mix deli.status -t prod

# Checks version
$ mix deli.version

# Opens a IEx remote console from local machine
$ eval $(mix

# Opens a local observer connected to remote node
$ eval $(mix -o)

# When there are more than one host for target,
# eval will just work if you filter it to just return one host
$ eval $(mix -h 01)

# If you don't know yet how to filter, use it without eval,
# and it will do the port forwarding and print out the command to connect,
# but before, it lets you choose the host:
$ mix
Choose a number: 0
iex --name local@ --cookie awesome_cookie --remsh myapp@

### Run mix tasks (locally) in remote nodes

By using [`Deli.Command`](, you can have this:

# runs locally
$ mix --arg_example=1

# runs in all prod hosts
$ mix --arg_example=1 -t prod

# runs in prod hosts matching ~r/03/
$ mix --arg_example=1 -t prod -h 03

### Configuring controller

By default, the release binary (`/opt/APP/bin/APP`) is used to control the app (start, stop, restart, status, ping), but systemd's `systemctl` can be configured as the app controller:

config :deli, controller: Deli.Controller.Systemctl

You can configure any module that implements the [`Deli.Controller` behaviour]( Beware during `v0.x.x` this contract is not stable.

### Edeliver and Distillery

Releases should be configured in your application with [`distillery`](

You don't need to think about edeliver with deli (unless you want to).
Deli generates any config needed for edeliver, and adds them to your gitignore by default.
If you want to maintain a custom version, just remove from .gitignore, and also remove the comment line saying `autogenerated by deli`.
Edeliver mix commands are available to you. But if you use the systemctl controller, avoid using edeliver admin commands (start / stop / ...)

At the moment, this package exists for reusing among similarly configured apps. It might not be flexible enough for your needs yet.

## Potential future work

- Remove edeliver dependency, replacing its steps by local code
- Concurrent restarts / checks / ...
- Retry / rollback strategy
- Upgrades
- Add docker build target to latest debian and ubuntu
- Allow configuring a docker image identifier as docker build target
- Allow configuring docker build elixir / otp / rebar versions (mind the checksums)
- Accept host labels in config, and filter by it in commands
- Associate labels with different build targets (first label wins)
- Configure of a remote build host (docker as default behaviour)
- Configure a custom deploy strategy
- Plugin behaviour to allow custom hooks and integrations (e.g. slack notification)
- Autogenerated files with version and checksums for expiration
- Provide common release service assets (nginx, systemd, logrotate etc)
- Use a remote release store (allows CI to build releases for all build targets upfront)
- Provision/setup new target hosts (with hooks for custom setup)
- Integrate with a terminal-based observer
- mix deli.version handle dev target
- mix deli.version have compare option
- mix to run specifically bin ping command
- mix deli.eval
- Add more docs, tests and typespecs