Skip to content

Instantly share code, notes, and snippets.

@HitScan
Created February 22, 2023 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HitScan/2655f0486ca84ecf658131e2999f2845 to your computer and use it in GitHub Desktop.
Save HitScan/2655f0486ca84ecf658131e2999f2845 to your computer and use it in GitHub Desktop.
Build an idempotent Evergreen db upgrade script between any 2 branches. Allows custom pre- and post- steps in case fixes are required to apply a stock script.
#!/bin/bash
# Find the list of Eg upgrade scripts and build a psql-compatible upgrade script
usage() {
echo "Usage: $0 branch/spec/from branch/spec/to version [pg_host] [pg_db] [pg_user]"
echo "The version parameter is used as eg_version in upgrade scripts."
exit 1
}
if [ $# -lt 3 ]; then
echo "Need a From branch, To branch, and Version!" >&2
usage
fi
if [ ! git status >/dev/null 2>&1 ] || [ "$(git ls-tree HEAD -- "$upg" 2>/dev/null | wc -l )" -eq 0 ]; then
echo "This script expects to be run in an Evergreen ILS git repository." >&2
usage
fi
# If we're here we know that we're in a git repository and it at least looks a lot like an Evergreen repo.
br_from="$1"
br_to="$2"
eg_version="$3"
pg_host="${4:-localhost}"
pg_db="${5:-evergreen}"
pg_user="${6:-evergreen}"
upg=":/Open-ILS/src/sql/Pg/upgrade/"
workdir="$(mktemp -d)"
if [ $? -ne 0 ]; then
echo "Unable to create temporary work directory!" >&2
exit 1
fi
upg_from="$workdir/from"
upg_to="$workdir/to"
git ls-tree --name-only "$br_from" -- "$upg" 2>/dev/null | cut -d/ -f 6 >"$upg_from"
git ls-tree --name-only "$br_to" -- "$upg" 2>/dev/null | cut -d/ -f 6 >"$upg_to"
files="$(diff "$upg_from" "$upg_to" | grep '>' | cut -c 3-)"
# Outputs a script on stdout. It's up to you to > it somewhere.
cat <<SCRIPTSWRITINSCRIPTS
#!/bin/bash
# Database Connection info. You're going to want a .pgpass or locally trusted connection for this.
export PGHOST=$pg_host
export PGDATABASE=$pg_db
export PGUSER=$pg_user
# How'd we do?
trap 'r=\$?; if [ \$r -eq 0 ]; then echo -e "\\\\nFinished.\\\\n"; else echo -e \\\\007; echo -e "OH SNAP\\\\n"; fi ' EXIT
# Stop on any errors
set -e
# And tell psql to do the same
psql_flags="-q -X -v eg_version='$eg_version' -v ON_ERROR_STOP=1 -P pager=off"
test_q="SELECT COUNT(version) FROM config.upgrade_log WHERE version=:'version';"
SCRIPTSWRITINSCRIPTS
# This obviously depends on our keeping a 1234.blahblah.sql naming scheme. At over 1300 scripts I like my chances.
for f in $files
do
vers="$(echo $f | cut -d. -f 1)"
cat <<ONCEMOREROUNDTHESUN
# Run upgrade $vers?
done="\$(echo "\$test_q" | psql -A -t \$psql_flags -v "version=$vers")"
if [ \$done -eq 0 ]; then
if [ -f "${vers}-pre.sql" ]; then
echo "Applying pre-upgrade adjustment for $vers"
psql \$psql_flags -f "${vers}-pre.sql"
fi
echo "Applying upgrade $vers"
psql \$psql_flags -f "$f"
if [ -f "${vers}-post.sql" ]; then
echo "Applying post-upgrade adjustment for $vers"
psql \$psql_flags -f "${vers}-post.sql"
fi
fi
ONCEMOREROUNDTHESUN
done
rm "$upg_from" "$upg_to" 2>/dev/null
rmdir "$workdir" 2>/dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment