Packages

Build and Deploy Elixir Applications and perform Hot-Code Upgrades and Schema Migrations

Current section

Files

Jump to
edeliver_fork strategies erlang-build-upgrade
Raw

strategies/erlang-build-upgrade

#!/usr/bin/env bash
REQUIRED_CONFIGS+=("APP")
REQUIRED_CONFIGS+=("BUILD_HOST")
REQUIRED_CONFIGS+=("BUILD_USER")
REQUIRED_CONFIGS+=("BUILD_AT")
OPTIONAL_CONFIGS+=("FROM")
OPTIONAL_CONFIGS+=("WITH")
OPTIONAL_CONFIGS+=("TO")
OPTIONAL_CONFIGS+=("REBAR_CONFIG")
TO="${TO:=$(get_latest_commit)}"
help() {
echo -e "
${bldwht}Usage:${txtrst}
edeliver build upgrade [Options]
${txtbld}Options:${txtrst}
--with=<release-version-from-store> ${txtylw}The release version to build the upgrade from${txtrst}.
This release must have been built somewhen by the ${bldwht}build release${txtrst} command
and must exist in the release store.
--from=<git-revision> The revision to build the upgrade from ${txtylw}if that release
is not avaiable any more${txtrst} (in the release store). ${txtylw}Must be in the branch${txtrst}
passed as ${bldwht}--branch=${txtrst} argument or in the master (default).
--to=<git-tag> The revision to build the upgrade for. Default is the HEAD
of the master branch or the branch passed as ${bldwht}--branch=${txtrst} argument.
--branch=<git-branch> The branch to build. ${txtylw}Default is the master branch${txtrst}.
${txtgrn}The branch doesn't need to be pushed to remote${txtrst} before building.
The revision passed as ${bldwht}--from=${txtrst} or ${bldwht}--to=${txtrst} argument must be in
that branch.
--mix-env=<env> Build the upgrade with a custom mix environment.
Default is ${bldwht}prod${txtrst}.
--skip-relup-mod Skip modification of the grenerated relup instructions.
No custom relup instructions are added.
--relup-mod=<module-name> The name of the module to modify the relup
if there are several modules. The module must implement the
Behaviour ${bldwht}Edeliver.Relup.Modification${txtrst}.
--auto-version=[git-]revision|[git-]commit-count[-all[-branches]|-branch]
|[git-]branch[-unless-master]|[build-]date|mix-env ${txtgrn}Appends${txtrst} the git
sha1 revision, the current commit count either across all branches
(default) or for the current branch, the current branch name
(optionally only unless it is the master branch) and/or the
build date as ${txtgrn}metadata to the current upgrade version${txtrst}. To append
that metadata ${txtgrn}automatically for each build${txtrst} set the ${bldwht}AUTO_VERSION${txtrst}
env in the config. Values can also be combined using the ${bldwht}+${txtrst} char,
e.g. ${bldwht}git-revison+git-branch${txtrst} creates version 1.2.3-82a5834-master.
--increment-version=major|minor|patch Increments the major, minor or patch
version ${txtylw}for the current build${txtrst}.
--set-version=<release-version> Sets the release version for ${txtylw}the current build${txtrst}.
${txtbld}Faster Builds:${txtrst} ${txtblu}(Faster builds might fail during build or during runtime)${txtrst}
--skip-git-clean Don't build from a clean state for faster builds. Can be
adjusted by the ${bldwht}GIT_CLEAN_PATHS${txtrst} environment variable. Should be
at least ${bldwht}rel${txtrst} for elixir releases.
--skip-mix-clean Skip the 'mix clean step' for faster builds. Can be used
in addition to ${bldwht}--skip-git-clean${txtrst} Option for incremental builds.
${bldylw}Info:${txtrst}
Builds an upgrade on the build host and copies it to the release store.
It can be used by the edeliver ${bldwht}deploy upgrade${txtrst} command to deploy it on
staging or production hosts.
${txtgrn}The built upgrade can be used for hot code upgrades without a restart${txtrst}
of the node. It is ${txtylw}required${txtrst} that the ${txtylw}release${txtrst} of the running node
${txtylw}is available${txtrst} (${bldwht}--with=${txtrst} Option) ${txtylw}or can be built${txtrst} (${bldwht}--from=${txtrst} Option) to be
able to create the hot code upgrade strategy (relup).
It ${txtylw}might be necessary to adjust the upgrade instructions${txtrst} (relup)
by using the ${bldwht}edit relup${txtrst} command.
"
}
set_build_hosts
run() {
authorize_hosts
authorize_release_store_on_build_host
if [[ -n "$WITH" ]]; then
[[ "$RELEASE_CMD" = "mix" ]] && local _release_type="*" || local _release_type="release"
validate_release_is_in_store "$_release_type" $WITH # we can skip init_app_remotely and pushing to remote if release does not exist
if [[ $? -ne 0 ]]; then
hint_message "You can build appups also with the --from=<git-tag-or-revision> option\nif the release is not in your release store"; exit 2
fi
# push current state
init_app_remotely
git_push
git_reset_remote
git_clean_remote
elif [[ -n "$FROM" ]]; then
# push current state
init_app_remotely
git_push
git_reset_remote
git_clean_remote
# checkout old version
git_checkout_remote $FROM
# build old release
erlang_get_and_update_deps
# ... but don't change version of old release
local _increment_release_version_option="$INCREMENT_RELEASE_VERSION"
local _set_release_version_option="$SET_RELEASE_VERSION"
INCREMENT_RELEASE_VERSION=""
SET_RELEASE_VERSION=""
erlang_clean_compile
erlang_generate_release
[[ "$RELEASE_CMD" = "rebar" ]] && rename_release_add_version
[[ "$RELEASE_CMD" = "mix" ]] && __detect_remote_release_dir && __detect_remote_release_version
# reset the option to auto-increment or setting the version for building the curent release for the upgrade
INCREMENT_RELEASE_VERSION="$_increment_release_version_option"
SET_RELEASE_VERSION="$_set_release_version_option"
OLD_RELEASE_VERSION=${RELEASE_VERSION}
else
error_message "no old version specified"; exit 2
fi
# checkout new version
git_checkout_remote $TO
# build new release
erlang_get_and_update_deps
erlang_clean_compile
# check already now whether the built release will
# have a different release version as the original release
if [[ "$RELEASE_CMD" = "mix" ]]; then
status "Checking version of new release"
if [[ "$AUTO_RELEASE_VERSION" =~ ^(patch|minor|major)$ ]]; then
local _version_command="release.version increase $AUTO_RELEASE_VERSION --verbose | grep -oe ' to .*' | cut -b 5-"
elif [[ "$AUTO_RELEASE_VERSION" == "git" ]]; then
local _version_command="release.version append-git-revision --verbose | grep -oe ' to .*' | cut -b 5-"
elif [[ -n "$AUTO_RELEASE_VERSION" ]]; then
local _version_command="release.version set \"$AUTO_RELEASE_VERSION\" --verbose | grep -oe ' to .*' | cut -b 5-"
else
local _version_command="release.version show"
fi
local _version_that_will_be_built=$(__remote "
[ -f ~/.profile ] && source ~/.profile
cd $BUILD_AT $SILENCE
MIX_ENV=\"$TARGET_MIX_ENV\" $MIX_CMD $_version_command
")
[[ -n "$WITH" ]] && local _old_version="$WITH" || local _old_version="$OLD_RELEASE_VERSION"
[[ "$_version_that_will_be_built" = "$_old_version" ]] \
&& __show_upgrade_version_does_not_differ_error_message \
&& exit 1
fi
if [[ -n "$WITH" ]] && [[ "$RELEASE_CMD" != "rebar" ]]; then
# when generating upgrades with `mix release` (exrm) the old
# release must be uploaded before generating the release.
# `erlang_generate_release` generates the upgrade then automatically
RELEASE_DIR="${RELEASE_DIR:-"${DELIVER_TO}/rel/${APP}"}"
local _release_destination_path="$(dirname $RELEASE_DIR)"
[[ "$RELEASE_FILE" =~ upgrade\.tar\.gz$ ]] && _release_destination_path="${_release_destination_path%%/}/${APP}"
upload_release_archive "$_release_destination_path" "$RELEASE_FILE" "$WITH"
remote_extract_release_archive "$WITH" "$(dirname $RELEASE_DIR)"
if [[ "$RELEASE_FILE" =~ upgrade\.tar\.gz$ ]]; then
status "Removing old releases which were included in upgrade package"
__remote "
[ -f ~/.profile ] && source ~/.profile
set -e
cd \"$(dirname $RELEASE_DIR)/${APP}/releases\" $SILENCE
for release_dir in \$(ls -1); do
[[ \"\$release_dir\" != \"$WITH\" ]] && [[ -n \"\$release_dir\" ]] && [[ -d \"\$release_dir\" ]] && echo \"removing \$release_dir\" $SILENCE && rm -rf \"\$release_dir\" || :
done
"
fi
__detect_remote_release_dir
__detect_remote_release_version
OLD_RELEASE_VERSION=${RELEASE_VERSION}
fi
if [[ "$RELEASE_CMD" = "relx" ]]; then
relx_generate_relup
else
erlang_generate_release
fi
if [[ -n "$WITH" ]] && [[ "$RELEASE_CMD" = "rebar" ]]; then
__detect_remote_release_dir
# backup new release
rename_release_add_version "new"
NEW_RELEASE_VERSION=$RELEASE_VERSION;
OLD_RELEASE_VERSION="$WITH"
# upload and extract old release
upload_release_archive "$(dirname $RELEASE_DIR)" "${APP}_${WITH}.release.tar.gz" "$WITH"
remote_extract_release_archive "$WITH" "$(dirname $RELEASE_DIR)"
# rename old release
rename_release_add_version "old" "$WITH"
# restore new release
rename_release_remove_version $NEW_RELEASE_VERSION
fi
# generate default appups
[[ "$RELEASE_CMD" = "rebar" ]] && rebar_generate_appup $OLD_RELEASE_VERSION
# overwrite default appups with custom appups
[[ "$RELEASE_CMD" = "rebar" ]] && copy_appups_from_release_store_to_build_host $OLD_RELEASE_VERSION
# generate upgrade package and copy it to release store
if [[ "$RELEASE_CMD" = "relx" ]]; then
erlang_archive_release
elif [[ "$RELEASE_CMD" = "mix" ]]; then
remove_built_release_archive "$OLD_RELEASE_VERSION"
RELEASE_VERSION="" # redetect new version
__detect_remote_release_version
else
rebar_generate_upgrade $OLD_RELEASE_VERSION
fi
copy_release_to_release_store "upgrade"
}