Skip to content

Instantly share code, notes, and snippets.

@pda
Last active December 25, 2015 01:39
Show Gist options
  • Select an option

  • Save pda/6896824 to your computer and use it in GitHub Desktop.

Select an option

Save pda/6896824 to your computer and use it in GitHub Desktop.
Shell script to migrate between Heroku Postgres databases via pgbackups.
#!/usr/bin/env zsh
# Migrate data between Heroku Postgres databases via pgbackups.
# This involves downtime via `heroku maintenance:on`.
#
# To migrate example-app to HEROKU_POSTGRESQL_COLOR:
# heroku-postgres-migrate.sh <example-app> <HEROKU_POSTGRESQL_COLOR>
#
# To exit maintenance mode (in case something dies half-way):
# heroku-postgres-migrate.sh --wake
#
# NOTE: the scaling of non-web processes needs to be edited in this
# script. Attempting to scale down a process type that doesn't exist
# prevents this script from continuing.
# See: start_maintenance and end_maintenance.
#
# Based on the guide at:
# https://devcenter.heroku.com/articles/upgrade-heroku-postgres-with-pgbackups
#
# Author: Paul Annesley
# License: MIT
set -e
function start_maintenance {
log "Entering maintenance mode"
heroku maintenance:on
#log "Scaling worker=0"
#heroku ps:scale worker=0
}
function end_maintenance {
log "Coming out of maintenance mode"
heroku maintenance:off
#log "Scaling worker=1"
#heroku ps:scale worker=1
}
function validate_db {
if [[ ! $1 =~ "^HEROKU_POSTGRESQL_[A-Z]+$" ]]; then
panic "Invalid DB name: $1"
fi
}
function validate_app {
if [[ ! $1 =~ "^[a-z][a-z0-9-]*[a-z0-9]$" ]]; then
panic "Invalid Heroku app name: $1"
fi
}
function migrate_app_to {
local APP=$1
local NEW_DB=$2
log "Migrating to $NEW_DB..."
log "Capturing a database backup"
heroku pgbackups:capture --expire
log "Restoring backup into $NEW_DB"
heroku pgbackups:restore $NEW_DB --confirm $APP
log "Promoting $NEW_DB to DATABASE_URL"
heroku pg:promote $NEW_DB
}
function check_for_pgbackups {
log "Checking for pgbackups add-on"
(heroku addons | grep pgbackups) ||
panic "pgbackups required: heroku addons:add pgbackups:auto-month"
}
function main {
local APP=$1
local NEW_DB=$2
validate_app $APP
validate_db $NEW_DB
check_for_pgbackups
start_maintenance
migrate_app_to $APP $NEW_DB
end_maintenance
}
function log {
echo -e "\n>> $@"
}
function panic {
echo "!! $@" >&2
exit 1
}
if [[ $1 = "--wake" ]]; then
end_maintenance
exit 0
fi
main $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment