I initially went for edeliver, but if I remember correctly I had an issue or two and I didn’t quite feel comfortable with it, so I’ve since moved to using a bash script I wrote (below in case it’s of any use - I hope I’m not embarrassing myself too much!) that runs Distillery which I run from my workstation and which is enough for my simple needs at the moment. So far I’m only using one server per app.
I’m one of those people @bitwalker mentions who isn’t comfortable with containers. I do plan to look at Bootleg at some point.
build_and_deploy_release.sh:
#!/usr/bin/env bash
# Usage: ./build_and_deploy_release.sh app version environment
# Usage example: ./build_and_deploy_release.sh my_app 0.0.1 prod
# Set to exit on error
set -ue -o pipefail
# Ensure the present working directory is that of the script
cd "${0%/*}"
# Source required functions
. $HOME/sh_scripts/functions/ask.sh
# Check for correct number of command line arguments
if [[ $# -ne 3 ]] ; then
echo "Usage: $0 app version environment"
fi
app="$1"
version="$2"
environment="$3"
releases_dir="_build/prod/rel/${app}/releases"
archive="${app}.tar.gz"
case $app:$environment in
app_name:prod)
server="example.com"
sudo_ssh_profile="user@${server}"
app_ssh_profile="app-name@${server}"
;;
app_name:staging)
server="staging.example.com"
sudo_ssh_profile="user@${server}"
app_ssh_profile="app-name@${server}"
;;
*)
echo "No server found for ${app} at ${environment}"; exit 1 ;;
esac
if ask "Build release of ${app} ${version} for ${environment}?" ; then
MIX_ENV=prod mix release --profile=${app}:${environment}
else
exit 1
fi
if ask "Copy release archive to ${app_ssh_profile} and extract?" ; then
# Copy the release archive to the server
scp -q "${releases_dir}/${version}/${archive}" "${app_ssh_profile}:~/app/"
# Extract and delete the release archive on the server
ssh -qt "${app_ssh_profile}" "tar -C ~/app -xzf ~/app/${archive} && rm ~/app/${archive}"
else
exit 1
fi
if ask "Restart ${app} app at ${app_ssh_profile}?" ; then
echo "Restarting app; provide password for sudo for ${sudo_ssh_profile}"
ssh -qt "${sudo_ssh_profile}" "sudo systemctl restart ${app}_app.service"
else
exit 1
fi
echo "Deployment completed"
ask.sh:
################################################################################
# Ask yes/no questions, with or without a default answer.
# http://djm.me/ask
# Globals:
# None
# Arguments:
# 1: question
# 2: default answer: Y or N (optional)
# Returns:
# None
# Example usage:
# if ask "Do you want to do such-and-such?"; then
# echo "Answer is yes"
# else
# echo "Answer is no"
# fi
################################################################################
ask() {
local prompt default REPLY
while true; do
if [ "${2:-}" = "Y" ]; then
prompt="Y/n"
default=Y
elif [ "${2:-}" = "N" ]; then
prompt="y/N"
default=N
else
prompt="y/n"
default=
fi
# Ask the question (not using "read -p" as it uses stderr not stdout)
echo -n "$1 [$prompt] "
# Read the answer (use /dev/tty in case stdin is redirected from somewhere else)
read REPLY </dev/tty
# Default?
if [ -z "$REPLY" ]; then
REPLY=$default
fi
# Check if the reply is valid
case "$REPLY" in
Y*|y*) return 0 ;;
N*|n*) return 1 ;;
esac
done
}