Created
August 13, 2019 10:42
-
-
Save aitor/4cd24f547dccef8d01ee10d7b5cf0495 to your computer and use it in GitHub Desktop.
Refresh demo/staging data in Heroku (cf. http://covidence.engineering/automatically-refresh-staging-db/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -ex | |
# Pass in Heroku API token | |
token=$1 | |
# We run this script in a stateless Docker image, so to make the script a bit | |
# cleaner, we just write out the credentials to a file that the Heroku Toolbelt | |
# knows to read. | |
if ! grep -lq api.heroku.com ~/.netrc 2>/dev/null; then | |
echo "machine api.heroku.com" > ~/.netrc | |
echo " login [email protected]" >> ~/.netrc | |
echo " password $token" >> ~/.netrc | |
chmod 0600 ~/.netrc | |
fi | |
# Helper function for calling Heroku API | |
function hapi { | |
curl \ | |
--fail \ | |
--silent \ | |
--netrc \ | |
--header 'Accept: application/vnd.heroku+json; version=3' \ | |
https://api.heroku.com$* | |
} | |
# Routine to wait for DB to be caught up, then promote it and de-provision the | |
# old instance. | |
function promote { | |
app=$1 | |
heroku pg:wait --wait-interval 10 -a $app | |
heroku pg:unfollow -a $app --confirm $app $app::NEW_DATABASE || true | |
heroku addons:attach -a $app $app::DATABASE --as OLD_DATABASE | |
heroku pg:promote -a $app NEW_DATABASE | |
heroku addons:detach -a $app NEW_DATABASE | |
heroku addons:destroy -a $app --confirm $app OLD_DATABASE | |
heroku run:detached -a $app rails runner 'Ops::Staging::Search.massacre!' | |
} | |
# Routine to create a new DB with a deterministic name so that we can more | |
# easily promote it later. | |
# | |
# There is also some logic here to recover from a build which got interrupted | |
# mid-way so that we don't accumulate orphaned DBs that we have to pay for. | |
function create { | |
app=$1 | |
plan=$2 | |
shift 2 | |
existing=$(hapi /addons/$app::DATABASE | jq -Mr .name) | |
new=$(hapi /addons/$app::NEW_DATABASE | jq -Mr .name || true) | |
if [ -z "$new" ]; then | |
heroku addons:create \ | |
-a $app heroku-postgresql:$plan \ | |
--as NEW_DATABASE \ | |
$* | |
else | |
if [ "$new" == "$existing" ]; then | |
heroku addons:detach -a $app NEW_DATABASE | |
create $app $plan | |
else | |
true # already got a new one in waiting | |
fi | |
fi | |
} | |
# Takes a snapshot and copies it. This takes longer, breaks the destination | |
# DB until it has completed, so is only used for demo to demo-staging, which | |
# use Hobby DBs which cannot be followed/forked. | |
# | |
# One benefit of this which might be worth applying to staging/dev is that the | |
# destination data sizes (tables+indexes) are much smaller, which suits the | |
# smaller instance sizes used there. | |
function copy { | |
src=$1 | |
dst=$2 | |
heroku pg:copy $src::DATABASE NEW_DATABASE \ | |
--wait-interval 10 \ | |
--app $dst \ | |
--confirm $dst | |
} | |
# Create new DBs and trigger loading of data | |
create covidence-dev premium-0 --fork covidence-production::DATABASE --fast | |
create covidence-staging premium-2 --fork covidence-production::DATABASE --fast | |
create covidence-demo-staging hobby-basic | |
copy covidence-demo covidence-demo-staging | |
# Promote DBs (these steps block until each DB to be ready for promotion) | |
promote covidence-dev | |
promote covidence-staging | |
promote covidence-demo-staging |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment