Skip to content

Instantly share code, notes, and snippets.

@shaniber
Created March 26, 2014 14:49
Show Gist options
  • Save shaniber/9785061 to your computer and use it in GitHub Desktop.
Save shaniber/9785061 to your computer and use it in GitHub Desktop.
#!/bin/bash
# A simple script to make live backups of an organization's GitHub repositories.
# Where to store the backup files
GHBU_BACKUP_DIR=${GHBU_BACKUP_DIR-"==/FULL/PATH/TO/BACKUPDIR=="}
# The GitHub organization whose repos will be backed up
GHBU_ORG=${GHBU_ORG-"==ORGANIZATION=="}
# GitHub API token.
GBHU_TOKEN=${GBHU_TOKEN-"==AUTHTOKEN=="}
# the GitHub hostname.
GHBU_GITHOST=${GHBU_GITHOST-"github.com"}
# base URI for the GitHub API.
GHBU_API=${GHBU_API-"https://api.github.com"}
# Options for the API call.
GHBU_API_OPTS="access_token=${GBHU_TOKEN}&"
# base command to use to clone GitHub repos
GHBU_GIT_CLONE_CMD="git clone --quiet --mirror git@${GHBU_GITHOST}:"
# base command to use to clone GitHub repos
GHBU_GIT_FETCH_CMD="git --bare fetch"
# when `true`, old backups will be deleted
GHBU_PRUNE_OLD=${GHBU_PRUNE_OLD-true}
# the min age (in days) of backup files to delete
GHBU_PRUNE_AFTER_N_DAYS=${GHBU_PRUNE_AFTER_N_DAYS-3}
# when `true`, only show error messages
GHBU_SILENT=${GHBU_SILENT-false}
TSTAMP=`date "+%Y%m%d-%H%M"`
# The function `check` will exit the script if the given command fails.
function check {
"$@"
status=$?
if [ $status -ne 0 ]; then
echo "ERROR: Encountered error (${status}) while running the following:" >&2
echo " $@" >&2
echo " (at line ${BASH_LINENO[0]} of file $0.)" >&2
echo " Aborting." >&2
exit $status
fi
}
# The function `tgz` will create a gzipped tar archive of the specified file ($1) and then remove the original
function tgz {
check tar zcf $1.tar.gz $1 && check rm -rf $1
}
$GHBU_SILENT || (echo "" && echo "=== INITIALIZING ===" && echo "")
$GHBU_SILENT || echo "Using backup directory $GHBU_BACKUP_DIR"
check mkdir -p $GHBU_BACKUP_DIR
$GHBU_SILENT || echo -n "Fetching list of repositories for ${GHBU_ORG}..."
REPOURL="${GHBU_API}/orgs/${GHBU_ORG}/repos?${GHBU_API_OPTS}per_page=2"
REPOLIST=""
while [ $REPOURL ]; do
REPOREQCONTENT=`curl --silent -i $GHBU_CURLOPTS $REPOURL -q`
REPOURL=`check echo "${REPOREQCONTENT}" | grep "\"next\"" | check awk -F'<' '{print $2}' | check sed -e 's/>;.*//g'`
REPOLIST=$REPOLIST`check echo "${REPOREQCONTENT}" | grep "\"name\"" | check awk -F': "' '{print $2}' | check sed -e 's/",//g'`$'\n'
done
$GHBU_SILENT || echo " found `echo $REPOLIST | wc -w | awk '$1=$1'` repositories."
$GHBU_SILENT || (echo "" && echo "=== BACKING UP ===" && echo "")
for REPO in $REPOLIST; do
# if the repository exists, update it from GitHub.
if [ -d ${GHBU_BACKUP_DIR}/${REPO}.git ] ; then
$GHBU_SILENT || echo "Syncing existing repo ${GHBU_ORG}/${REPO}"
check cd ${GHBU_BACKUP_DIR}/${REPO}.git && check ${GHBU_GIT_FETCH_CMD}
# if the repository is new, clone it.
else
$GHBU_SILENT || echo "Backing up ${GHBU_ORG}/${REPO}"
check ${GHBU_GIT_CLONE_CMD}${GHBU_ORG}/${REPO}.git ${GHBU_BACKUP_DIR}/${REPO}.git
fi
# if the wiki exists, update it from GitHub.
if [ -d ${GHBU_BACKUP_DIR}/${REPO}.wiki.git ] ; then
$GHBU_SILENT || echo "Syncing existing wiki for ${GHBU_ORG}/${REPO}"
check cd ${GHBU_BACKUP_DIR}/${REPO}.wiki.git && check ${GHBU_GIT_FETCH_CMD}
# if the wiki is new, attempt to clone it (and ignore it if it doesn't exist).
else
$GHBU_SILENT || echo "Backing up ${GHBU_ORG}/${REPO}.wiki (if any)"
${GHBU_GIT_CLONE_CMD}${GHBU_ORG}/${REPO}.wiki.git ${GHBU_BACKUP_DIR}/${REPO}.wiki.git 2>/dev/null
fi
# Have to read the API docs to see how to do this via the API using a token.
# $GHBU_SILENT || echo "Backing up ${GHBU_ORG}/${REPO} issues"
# check curl --silent -u $GHBU_UNAME:$GHBU_PASSWD ${GHBU_API}/repos/${GHBU_ORG}/${REPO}/issues -q > ${GHBU_BACKUP_DIR}/${GHBU_ORG}-${REPO}.issues-${TSTAMP} && tgz ${GHBU_BACKUP_DIR}/${GHBU_ORG}-${REPO}.issues-${TSTAMP}
done
if $GHBU_PRUNE_OLD; then
$GHBU_SILENT || (echo "" && echo "=== PRUNING ===" && echo "")
$GHBU_SILENT || echo "Pruning issues backup files ${GHBU_PRUNE_AFTER_N_DAYS} days old or older."
$GHBU_SILENT || echo "Found `find $GHBU_BACKUP_DIR -name '*.tar.gz' -mtime +$GHBU_PRUNE_AFTER_N_DAYS | wc -l` files to prune."
find $GHBU_BACKUP_DIR -name '*.tar.gz' -mtime +$GHBU_PRUNE_AFTER_N_DAYS -exec rm -fv {} > /dev/null \;
fi
$GHBU_SILENT || (echo "" && echo "=== DONE ===" && echo "")
$GHBU_SILENT || (echo "GitHub backup completed." && echo "")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment