Skip to content

Instantly share code, notes, and snippets.

@kofronpi
Forked from jonah-williams/circle.yml
Created May 25, 2016 22:56
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save kofronpi/f62d3c3cf4a6b5f40f6eef9124fe21e4 to your computer and use it in GitHub Desktop.
Automating deployments to Heroku from CircleCI
test:
override:
- bundle exec rspec spec
deployment:
acceptance:
branch: master
commands:
- ./script/heroku_deploy.sh <ACCEPTANCE_HEROKU_APP>:
timeout: 300
staging:
branch: staging
commands:
- ./script/heroku_deploy.sh <STAGING_HEROKU_APP>:
timeout: 300
production:
branch: production
commands:
- ./script/heroku_deploy.sh <PRODUCTION_HEROKU_APP>:
timeout: 300
#!/bin/sh -e
APP_NAME=$1
git remote add heroku git@heroku.com:$APP_NAME.git
git fetch heroku
MIGRATION_CHANGES=$(git diff HEAD heroku/master --name-only -- db | wc -l)
echo "$MIGRATION_CHANGES db changes."
PREV_WORKERS=$(heroku ps --app $APP_NAME | grep "^worker." | wc -l | tr -d ' ')
# 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
# deploy code changes (and implicitly restart the app and any running workers)
git push heroku $CIRCLE_SHA1:refs/heads/master
# run database migrations if needed and restart background workers once finished
if test $MIGRATION_CHANGES -gt 0; then
heroku run rake db:migrate db:seed --app $APP_NAME
heroku scale worker=$PREV_WORKERS --app $APP_NAME
heroku restart --app $APP_NAME
fi
heroku run rake cache:flush --app $APP_NAME
heroku maintenance:off --app $APP_NAME
#!/bin/sh -e
APP_NAME=$1
heroku maintenance:on --app $APP_NAME
git push heroku $CIRCLE_SHA1:refs/heads/master
heroku run rake db:migrate db:seed --app $APP_NAME
heroku restart --app $APP_NAME
heroku maintenance:off --app $APP_NAME
#!/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 ' ')
# configure pipeline deploy https://devcenter.heroku.com/articles/labs-pipelines
heroku plugins:install git://github.com/heroku/heroku-pipeline.git
if test $(heroku apps | grep $PIPELINE_APP_NAME -c) -gt 0; then
echo "Using existing pipeline $PIPELINE_APP_NAME"
git remote add pipeline $HEROKU_PIPELINE_REMOTE
DIFF_REMOTE=pipeline
else
heroku apps:create $PIPELINE_APP_NAME --remote pipeline
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 heroku $HEROKU_APP_REMOTE
DIFF_REMOTE=heroku
fi
# configure app and check for db changes
git fetch $DIFF_REMOTE
MIGRATION_CHANGES=$(git diff $CIRCLE_SHA1 $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 $CIRCLE_SHA1:refs/heads/master
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
)
MIGRATION_EXIT=$? # store the exit code
# 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
# If the migration failed, now we can exit with that exit code
if test $MIGRATION_EXIT -ne 0; then
exit $MIGRATION_EXIT
fi
heroku run rake cache:flush --app $APP_NAME
heroku maintenance:off --app $APP_NAME
DEPLOY_END=`date +%s`
ELAPSED=$(( $DEPLOY_END - $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
exit 0
#!/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 ' ')
# configure pipeline deploy https://devcenter.heroku.com/articles/labs-pipelines
if test $(heroku apps | grep $PIPELINE_APP_NAME -c) -gt 0; then
echo "Using existing pipeline $PIPELINE_APP_NAME"
git remote add pipeline $HEROKU_PIPELINE_REMOTE
else
heroku apps:create $PIPELINE_APP_NAME --remote pipeline
heroku labs:enable pipelines --app $PIPELINE_APP_NAME
fi
heroku plugins:install git://github.com/heroku/heroku-pipeline.git
heroku pipeline:add $APP_NAME --app $PIPELINE_APP_NAME
heroku pipeline --app $PIPELINE_APP_NAME
# configure app and check for db changes
git remote add heroku $HEROKU_APP_REMOTE
git fetch heroku
MIGRATION_CHANGES=$(git diff $CIRCLE_SHA1 heroku/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 $CIRCLE_SHA1:refs/heads/master
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
# 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 db:seed --app $APP_NAME
heroku restart --app $APP_NAME
heroku scale worker=$PREV_WORKERS --app $APP_NAME
fi
heroku run rake cache:flush --app $APP_NAME
heroku maintenance:off --app $APP_NAME
DEPLOY_END=`date +%s`
ELAPSED=$(( $DEPLOY_END - $DEPLOY_START ))
# HACK!
# Pipelines do not update the git repository on downstream apps.
#
# In order to be able to diff for db changes against the app overwrite the pipeline
# deploy with a git push of the same commit.
#
# Since this we already ran any required migrations this can always be a
# zero-downtime deploy we don't need to enable maintenance mode and are no longer
# sensetive to long asset precompilation times or other delays.
#
# We could remove this if we want to maintain a persistent pipeline app and always
# diff against that app to determine if db changes exist. Alternately we might
# be able to parse `heroku pipeline:diff` output for commit hashes and check for
# db changes in each commit.
git push heroku $CIRCLE_SHA1:refs/heads/master -f
# remove the pipeline app
heroku apps:destroy --app $PIPELINE_APP_NAME --confirm $PIPELINE_APP_NAME
echo "Deploy completed!"
if test $MIGRATION_CHANGES -gt 0; then
echo " $ELAPSED seconds in maintenance mode."
else
echo " $ELAPSED seconds, without maintenance mode."
fi
#!/bin/sh -e
APP_NAME=$1
git remote add heroku git@heroku.com:$APP_NAME.git
git fetch heroku
MIGRATION_CHANGES=$(git diff HEAD heroku/master --name-only -- db | wc -l)
echo "$MIGRATION_CHANGES db changes since last deploy."
rake assets:precompile
git config user.name "CircleCi"
git config user.email "ci@example.com"
git add public/assets
git commit -m "Precompile assets"
PREV_WORKERS=$(heroku ps --app $APP_NAME | grep "^worker." | wc -l | tr -d ' ')
# 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
# deploy code changes (and implicitly restart the app and any running workers)
git push heroku HEAD:refs/heads/master -f
# run database migrations if needed and restart background workers once finished
if test $MIGRATION_CHANGES -gt 0; then
heroku run rake db:migrate db:seed --app $APP_NAME
heroku restart --app $APP_NAME
heroku scale worker=$PREV_WORKERS --app $APP_NAME
fi
heroku run rake cache:flush --app $APP_NAME
heroku maintenance:off --app $APP_NAME
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment