Last active
May 21, 2019 09:29
-
-
Save pfrenssen/a672bf18b26e1ccbb74e to your computer and use it in GitHub Desktop.
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
#!/bin/bash -e | |
# | |
# Syncs a local Drupal dev site with the production server: | |
# - pulls latest code from the git repo on the server | |
# - downloads database from production and restores it locally | |
# - syncs the sites/default/files folder | |
# | |
# Required software packages: git, mysql, openssh, rsync, sudo | |
# Drush has to be installed on the server. | |
# | |
# This script will happily overwrite all your local changes and will throw away | |
# your database. Make sure everything important is committed or backed up. | |
# | |
# A list of the configuration variables. | |
CONFIG_VARIABLES=( "PROJECT" "SSH_USER" "SSH_SERVER" "REMOTE_TMP" "REMOTE_WEBROOT" "GIT_REPO" "LOCAL_BACKUP" "LOCAL_WEBROOT" "LOCAL_USER" "LOCAL_APACHE_USER" "LOCAL_MYSQL_USER" "LOCAL_MYSQL_PASS" "LOCAL_DRUSH" "REMOTE_DRUSH" ) | |
# Load config file if it exists. | |
if [ -f sync.config ]; then | |
. sync.config | |
fi | |
# Get user input for missing parameters. | |
until [[ "$PROJECT" =~ ^[_0-9a-z]+$ ]] ; do | |
echo "Enter a name for the project. Lowercase characters and underscores only." | |
read -p "Project name: " PROJECT | |
done | |
while [ -z "$SSH_USER" ] ; do | |
read -e -p "Remote user name: " -i "$PROJECT" SSH_USER | |
done | |
while [ -z "$SSH_SERVER" ] ; do | |
read -e -p "Remote domain name: " -i "srv1.pocomas.be" SSH_SERVER | |
done | |
while [ -z "$REMOTE_TMP" ] ; do | |
read -e -p "Remote temporary folder: " -i "/home/${SSH_USER}/backups" REMOTE_TMP | |
if ! ssh $SSH_USER@$SSH_SERVER test -d "$REMOTE_TMP" ; then | |
echo 'Error, folder does not exist. Please try again.' | |
REMOTE_TMP= | |
fi | |
done | |
while [ -z "$REMOTE_WEBROOT" ] ; do | |
read -e -p "Remote Drupal root folder: " -i "/home/${SSH_USER}/public_html" REMOTE_WEBROOT | |
if ! ssh $SSH_USER@$SSH_SERVER test -d "$REMOTE_WEBROOT" ; then | |
echo 'Error, folder does not exist. Please try again.' | |
REMOTE_WEBROOT= | |
fi | |
done | |
while [ -z "$GIT_REPO" ] ; do | |
read -e -p "URI of the master bare git repo: " -i "$SSH_USER@$SSH_SERVER:/home/${SSH_USER}/git" GIT_REPO | |
if ! git ls-remote $GIT_REPO &> /dev/null ; then | |
echo 'Error, no git repository found at this location. Please try again.' | |
GIT_REPO= | |
fi | |
done | |
while [ -z "$LOCAL_BACKUP" ] ; do | |
read -e -p "Local database backup folder: " -i "`pwd`/database" LOCAL_BACKUP | |
done | |
while [ -z "$LOCAL_WEBROOT" ] ; do | |
read -e -p "Local Drupal root folder: " -i "`pwd`/drupal" LOCAL_WEBROOT | |
done | |
while [ -z "$LOCAL_USER" ] ; do | |
read -e -p "Local user name: " -i "`whoami`" LOCAL_USER | |
done | |
while [ -z "$LOCAL_APACHE_USER" ] ; do | |
read -e -p "Local Apache user name: " -i "`whoami`" LOCAL_APACHE_USER | |
done | |
while [ -z "$LOCAL_MYSQL_USER" ] ; do | |
read -e -p "Local MySQL user name: " -i "root" LOCAL_MYSQL_USER | |
read -e -p "Local MySQL password: " LOCAL_MYSQL_PASS | |
done | |
while [ -z "$LOCAL_DRUSH" ] ; do | |
read -e -p "Local Drush installation: " -i "$LOCAL_WEBROOT/vendor/bin/drush" LOCAL_DRUSH | |
done | |
while [ -z "$REMOTE_DRUSH" ] ; do | |
read -e -p "Remote Drush installation: " -i "$REMOTE_WEBROOT/vendor/bin/drush" REMOTE_DRUSH | |
done | |
if [ ! -f sync.config ]; then | |
read -e -p "Do you want to save these settings (y/n)? " -i "y" SAVE_CONFIG | |
if [ "$SAVE_CONFIG" == "y" ] ; then | |
for CONFIG_VARIABLE in ${CONFIG_VARIABLES[@]} ; do | |
echo "$CONFIG_VARIABLE=\"${!CONFIG_VARIABLE}\"" >> sync.config | |
done | |
fi | |
fi | |
# First check if the code is already present. If not, download a fresh copy from | |
# the server and prepare everything for the installation of Drupal. | |
if [ ! -d "$LOCAL_WEBROOT" ]; then | |
# Clone the remote repo into $LOCAL_WEBROOT. | |
git clone $GIT_REPO $LOCAL_WEBROOT | |
fi | |
# Install Composer dependencies. | |
if [ -f $LOCAL_WEBROOT/composer.json ]; then | |
composer install --working-dir=$LOCAL_WEBROOT | |
fi | |
# Make sure the sites/default folder is writable. | |
sudo chmod u+w $LOCAL_WEBROOT/sites/default | |
# Create the sites/default/files/-folder and set permissions. | |
mkdir -p $LOCAL_WEBROOT/sites/default/files | |
sudo chown $LOCAL_USER:$LOCAL_APACHE_USER $LOCAL_WEBROOT/sites/default/files | |
sudo chmod 775 $LOCAL_WEBROOT/sites/default/files | |
# If the site is not yet installed, do so. | |
if [ ! -f "${LOCAL_WEBROOT}/sites/default/settings.php" ]; then | |
# @todo: ask the user for a database name and credentials before creating the | |
# database. | |
# Create a new database. | |
mysql -e "DROP DATABASE IF EXISTS \`$PROJECT\`;" | |
mysql -e "CREATE DATABASE \`$PROJECT\`;" | |
# Install Drupal. | |
$LOCAL_DRUSH site-install minimal install_configure_form.update_status_module='array(FALSE,FALSE)' --root="${LOCAL_WEBROOT}" --db-url=mysql://${LOCAL_MYSQL_USER}:${LOCAL_MYSQL_PASS}@localhost/${PROJECT} --account-name=${PROJECT} --account-pass=${PROJECT} --yes | |
else | |
# Pull latest code from the repository. | |
cd $LOCAL_WEBROOT | |
git checkout master | |
if [ -n "$(git log origin/master..master)" ] ; then | |
echo "Please make sure all local commits have been pushed to origin, or discard them before continuing." | |
exit 1 | |
fi | |
git reset --hard origin/master | |
git pull origin master --no-edit | |
fi | |
# Make a gzipped backup of the production database and save it on the server. | |
SUFFIX=$(date +"%Y%m%d")-$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 6 | head -n 1) | |
ssh -l $SSH_USER $SSH_SERVER "$REMOTE_DRUSH --root=\"$REMOTE_WEBROOT\" sql-dump | gzip -9 > $REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz" | |
# Check to see if database backup folder exists. If not create it. | |
if [ ! -d "$LOCAL_BACKUP" ]; then | |
mkdir -p $LOCAL_BACKUP | |
fi | |
# Transfer database backup. | |
scp $SSH_USER@$SSH_SERVER:$REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz $LOCAL_BACKUP | |
# @todo | |
# Backup local database before restoring. | |
# Restore database backup. | |
gunzip $LOCAL_BACKUP/${PROJECT}-${SUFFIX}.sql.gz --stdout | $LOCAL_DRUSH --root=$LOCAL_WEBROOT sql-cli | |
# Delete backup from server | |
ssh -l $SSH_USER $SSH_SERVER "rm $REMOTE_TMP/${PROJECT}-${SUFFIX}.sql.gz" | |
# Make sure the files folder is writable by the current user. Execute these | |
# commands in batches of 100 to avoid "Argument list too long" errors. | |
while [[ $(find $LOCAL_WEBROOT/sites/default/files/ ! -user $LOCAL_USER -printf '.' | wc -c) != 0 ]]; do | |
find $LOCAL_WEBROOT/sites/default/files/ ! -user $LOCAL_USER -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chown $LOCAL_USER | |
done | |
while [[ $(find $LOCAL_WEBROOT/sites/default/files/ ! -perm -u+w -printf '.' | wc -c) != 0 ]]; do | |
find $LOCAL_WEBROOT/sites/default/files/ ! -perm -u+w -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod u+w | |
done | |
# Synchronize the files folder. | |
rsync -rltDvz --delete --no-perms $SSH_USER@$SSH_SERVER:$REMOTE_WEBROOT/sites/default/files/ $LOCAL_WEBROOT/sites/default/files/ | |
# Set permissions. | |
sudo chown -R $LOCAL_USER:$LOCAL_APACHE_USER $LOCAL_WEBROOT/sites/default/files | |
while [[ $(find $LOCAL_WEBROOT/sites/default/files -type d ! -perm -775 -printf '.' | wc -c) != 0 ]]; do | |
find $LOCAL_WEBROOT/sites/default/files -type d ! -perm -775 -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod 775 | |
done | |
while [[ $(find $LOCAL_WEBROOT/sites/default/files -type f ! -perm -664 -printf '.' | wc -c) != 0 ]]; do | |
find $LOCAL_WEBROOT/sites/default/files -type f ! -perm -664 -print0 | head -zn 100 | xargs -0 --no-run-if-empty sudo chmod 664 | |
done | |
# Clear Drupal cache. | |
$LOCAL_DRUSH --root="${LOCAL_WEBROOT}" cc all |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment