Skip to content

Instantly share code, notes, and snippets.

@bborn
Created November 2, 2014 02:24
Show Gist options
  • Save bborn/938b1c91383535daafef to your computer and use it in GitHub Desktop.
Save bborn/938b1c91383535daafef to your computer and use it in GitHub Desktop.
#!/bin/sh -e
APP_NAME=$1
PIPELINE_APP_NAME=$APP_NAME-slug
HEROKU_APP_REMOTE=git@heroku.com:$APP_NAME.git
HEROKU_PIPELINE_REMOTE=git@heroku.com:$PIPELINE_APP_NAME.git
WORKERS_COUNT=$(heroku ps --app $APP_NAME | grep "^worker." | wc -l | tr -d ' ')
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
LOCAL_DEPLOY_START=`date +%s`
# configure pipeline deploy https://devcenter.heroku.com/articles/labs-pipelines
if test $(heroku plugins | grep pipeline -c) -gt 0; then
echo "Already have pipeline plugin"
else
heroku plugins:install git://github.com/heroku/heroku-pipeline.git
fi
if test $(heroku apps | grep $PIPELINE_APP_NAME -c) -gt 0; then
echo "Using existing pipeline $PIPELINE_APP_NAME"
if test $(git remote -v | grep $PIPELINE_APP_NAME -c) -gt 0; then
echo "Already have git remote"
else
git remote add $PIPELINE_APP_NAME $HEROKU_PIPELINE_REMOTE
git remote add $APP_NAME $HEROKU_APP_REMOTE
fi
DIFF_REMOTE=$APP_NAME
else
heroku apps:create $PIPELINE_APP_NAME --remote $PIPELINE_APP_NAME
heroku labs:enable pipelines --app $PIPELINE_APP_NAME
heroku pipeline:add $APP_NAME --app $PIPELINE_APP_NAME
heroku pipeline --app $PIPELINE_APP_NAME
git remote add $PIPELINE_APP_NAME $HEROKU_PIPELINE_REMOTE
git remote add $APP_NAME $HEROKU_APP_REMOTE
DIFF_REMOTE=$APP_NAME
fi
(
PRECOMPILE_START=`date +%s`
RAILS_ENV=production bundle exec rake assets:precompile
git add public/assets
git commit -m "Precompile assets"
PRECOMPILE_END=`date +%s`
PRECOMPILE_ELAPSED=$(( $PRECOMPILE_END - $PRECOMPILE_START ))
echo "Precompile completed!"
echo " $PRECOMPILE_ELAPSED seconds"
)
# configure app and check for db changes
git fetch $DIFF_REMOTE
MIGRATION_CHANGES=$(git diff $CURRENT_BRANCH $DIFF_REMOTE/master --name-only -- db | wc -l)
echo "$MIGRATION_CHANGES db changes since last deploy."
# use pipeline to prepare a slug to deploy
git push $PIPELINE_APP_NAME $CURRENT_BRANCH:master
echo "Finished deploying to $PIPELINE_APP_NAME"
DEPLOY_START=`date +%s`
# migrations require downtime so enter maintenance mode
if test $MIGRATION_CHANGES -gt 0; then
heroku maintenance:on --app $APP_NAME
# Make sure workers are not running during a migration
heroku scale worker=0 --app $APP_NAME
fi
# Run our migrations in a subprocess so that failed db migrations
# don't immediately abort our deploy script.
(
# promote the compiled slug
heroku pipeline:promote --app $PIPELINE_APP_NAME
# run database migrations if needed and restart background workers once finished
if test $MIGRATION_CHANGES -gt 0; then
heroku run rake db:migrate --app $APP_NAME
heroku run rake db:seed --app $APP_NAME
heroku restart --app $APP_NAME
fi
)
# Always scale our workers back up, regardless of whether the migration failed
if test $MIGRATION_CHANGES -gt 0; then
heroku scale worker=$WORKERS_COUNT --app $APP_NAME
fi
heroku maintenance:off --app $APP_NAME
DEPLOY_END=`date +%s`
ELAPSED=$(( $DEPLOY_END - $DEPLOY_START ))
LOCAL_ELAPSED=$(( $DEPLOY_END - $LOCAL_DEPLOY_START ))
echo "Deploy completed!"
if test $MIGRATION_CHANGES -gt 0; then
echo " $ELAPSED seconds in maintenance mode."
else
echo " $ELAPSED seconds, without maintenance mode."
fi
echo " $LOCAL_ELAPSED seconds total."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment