Skip to content

Instantly share code, notes, and snippets.

@CGA1123
Created August 2, 2019 15:02
Show Gist options
  • Save CGA1123/41a8901b82a14c9f2a77d8f9663d7d19 to your computer and use it in GitHub Desktop.
Save CGA1123/41a8901b82a14c9f2a77d8f9663d7d19 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -eu
# Finds the heroku slug id from the compile apps latests releases
# via the commit SHA
function heroku_slug () {
heroku releases --app ${1} --json | \
jq -rc --arg commit "${2}" \
'.[]
| select(.description | test("Deploy .*"))
| (.description | gsub("Deploy "; "")) as $commit_hash
| select($commit_hash | test($commit))
| .slug.id'
}
# Copies a slug to an application
function promote_slug () {
local app=${1}
local slug=${2}
local commit=${3}
heroku api POST "/apps/${app}/releases" --body '{"slug": "'"${slug}"'", "description": "Deploy '"${commit}"'"}' | tee release.json
local version=$(jq '.version' release.json)
sleep 5
heroku releases:output ${version} -a ${app}
sleep 5
heroku releases:info ${version} --app $app --json
heroku releases:info ${version} --app $app --json | grep status | grep -q succeeded
}
FIVE_MINUTES=$((60 * 5))
COMPILE_APP=${1}
APP=${2}
CURRENT_COMMIT=${CIRCLE_SHA1}
HEAD_COMMIT=$(git rev-parse origin/master)
COMMIT_BEFORE_HEAD=$(git rev-parse origin/master~1)
CURRENT_TIME=$(date +%s)
COMMIT_TIME=$(git show --format='%ct' origin/master | head -n1)
SECONDS_SINCE_COMMIT=$(expr $CURRENT_TIME - $COMMIT_TIME)
CURRENT_COMMIT_SHORT=${CURRENT_COMMIT:0:8}
echo "-----> Trying to find precompile slug for ${CURRENT_COMMIT} on ${COMPILE_APP}"
SLUG=$(heroku_slug ${COMPILE_APP} ${CURRENT_COMMIT_SHORT})
# If we found a slug id try and promote it to production, fallback to
# old-school deploys if we can't find one
if [ ! -z "${SLUG}" ] ; then
echo "-----> Trying to promote ${SLUG} to ${APP}..."
if [ "${HEAD_COMMIT}" == "${CURRENT_COMMIT}" ] ; then
echo " origin/master is at ${CURRENT_COMMIT}."
echo " Promoting slug..."
promote_slug ${APP} ${SLUG} ${CURRENT_COMMIT_SHORT}
elif [ "${COMMIT_BEFORE_HEAD}" == "${CURRENT_COMMIT}" ] && [ "${SECONDS_SINCE_COMMIT}" -lt "$FIVE_MINUTES" ] ; then
echo " Next commit on master (${HEAD_COMMIT}) merged less than 5 minutes ago - safe to deploy."
echo " Promoting slug..."
promote_slug ${APP} ${SLUG} ${CURRENT_COMMIT_SHORT}
else
echo " Either the next commit on master (${HEAD_COMMIT}) merged more than 5 minutes ago"
echo " or there are multiple commits on master ahead."
echo " This commit will deploy with the next run."
fi
else
echo "-----> Couldn't find precompiled slug - falling back"
echo " Could not find a precompiled slug on ${APP}"
echo " Looked for ${CURRENT_COMMIT}"
echo " Falling back to regular deploys..."
deploy ${APP}
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment