Skip to content

Instantly share code, notes, and snippets.

@codingwithchris
Last active May 5, 2019 16:14
Show Gist options
  • Save codingwithchris/c1d20da766a3183673d6e1f9706bb2c7 to your computer and use it in GitHub Desktop.
Save codingwithchris/c1d20da766a3183673d6e1f9706bb2c7 to your computer and use it in GitHub Desktop.
An atomic deployment shell script for WordPress
# This script was inspired in part by this Delicious Brains article: https://deliciousbrains.com/wordpress-workflow-atomic-deployments/
# ----------------
# Configs
# ----------------
# ------
# Colors
# ------
WHITE='\033[1;37m'
GRAY='\033[0;37m'
DGRAY='\033[1;30m'
GREEN='\033[0;32m'
ORANGE='\033[0;33m'
NC='\033[0m' # No Color
# ----------------
# Deployment
# ----------------
# If we pass in an argument, use it for the Deployment ID (most likely a git commit hash)
DEPLOYMENT_ID=$1
# IF for some reason we couldn't get the commit hash (DEPLOYMENT_ID is empty), use a timestamp instead
if [[ ! ${DEPLOYMENT_ID} ]]; then
DEPLOYMENT_ID=`date +%s`
printf "${ORANGE}No commit hash passed, defaulting 'DEPLOYMENT_ID' to timsestamp${NC}\n\n"
fi
# The number of total releases (including the current release) to keep on cleanup
RELEASES_TO_KEEP=5
# Where we will house our releases
RELEASES_FOLDER=__releases
# A folder to house the release being deployed right now
THIS_RELEASE_FOLDER=${RELEASES_FOLDER}/${DEPLOYMENT_ID}
# The folder that references the current release "in play"
CURRENT_RELEASE_FOLDER=__current
# The folder that holds our deployment files so we can take action on them
DEPLOY_CACHE=__deploy-cache
# ---------------------------
# Kick Off Atomic Deployment
# ---------------------------
# Kick off our deployment process!
printf "${GREEN}Atomic deployment started at `date`...${NC}\n"
printf "${DGRAY}running......${NC}\n\n"
# Display our Deployment ID
printf "${WHITE}Deployment ID: ${DEPLOYMENT_ID}${NC}\n\n"
# Copy all files from our deploy cache to our latest release folder
printf "Creating New Release from Deploy Cache: ${GRAY}public/${THIS_RELEASE_FOLDER}${NC}\n"
mkdir -p public/${THIS_RELEASE_FOLDER}
printf "${DGRAY}copying files...${NC}\n"
cp -r ${DEPLOY_CACHE}/. public/${THIS_RELEASE_FOLDER};
printf "${DGRAY}complete...${NC}\n\n"
# To make our lives easier... we are going to just cd into public and work from there from here on out
printf "${GRAY}Moving into 'public' directory for remainder of deployment...${NC}\n"
cd public
printf "${DGRAY}Here we go...${NC}\n\n"
# Link the `current` folder to the new (latest) release
printf "Make New Release Current: ${GRAY}${CURRENT_RELEASE_FOLDER}${NC} » ${GRAY}${THIS_RELEASE_FOLDER}${NC}\n"
rm -f ${CURRENT_RELEASE_FOLDER}
ln -s $(pwd)/${THIS_RELEASE_FOLDER} $(pwd)/${CURRENT_RELEASE_FOLDER}
printf "${DGRAY}complete...${NC}\n\n"
printf "${GREEN}Current release is ready to rock...${NC}\n\n"
# -------------------------------------------------
# Move/Link files and folders to final destinations
# -------------------------------------------------
# Link `wp` core from the 'current' release to the core install folder at `public/wp`
printf "Linking: WordPress ${GRAY}'core'${NC} to current release\n"
rm -rf wp
ln -s $(pwd)/${CURRENT_RELEASE_FOLDER}/wp $(pwd)/wp
printf "${DGRAY}complete...${NC}\n\n"
# Link the 'mu-plugins' folder from the 'current' release to the wp-content folder
printf "Linking: WordPress ${GRAY}'mu-plugins'${NC} to current release\n"
rm -rf wp-content/mu-plugins
ln -s $(pwd)/${CURRENT_RELEASE_FOLDER}/wp-content/mu-plugins $(pwd)/wp-content/mu-plugins
printf "${DGRAY}complete...${NC}\n\n"
# Link the 'themes' folder from the 'current' release to the wp-content folder
printf "Linking: WordPress ${GRAY}'themes'${NC} to current release\n"
rm -rf wp-content/themes
ln -s $(pwd)/${CURRENT_RELEASE_FOLDER}/wp-content/themes $(pwd)/wp-content/themes
printf "${DGRAY}complete...${NC}\n\n"
# Move various files to final destination in the root of the `public` folder
printf "Copying: ${GRAY}'wp-config.php'${NC} and ${GRAY}'index.php'${NC} to ${GRAY}'public'${NC} root\n"
cp ${THIS_RELEASE_FOLDER}/index.php ./
cp ${THIS_RELEASE_FOLDER}/wp-config.php ./
printf "${DGRAY}complete...${NC}\n\n"
printf "Removing: ${GRAY}'wp-config.php'${NC} from ${GRAY}${THIS_RELEASE_FOLDER}${NC} (will symlink in next step)\n"
rm -rf ${THIS_RELEASE_FOLDER}/wp-config.php
printf "${DGRAY}complete...${NC}\n\n"
# Symlink the current release wp-config file to our real wp-config file.
printf "Linking: ${GRAY}'wp-config.php'${NC} to ${GRAY}${THIS_RELEASE_FOLDER}/wp-config.php${NC} so it can resolve itself from 'public'\n"
ln -s $(pwd)/wp-config.php $(pwd)/${THIS_RELEASE_FOLDER}/wp-config.php
printf "${DGRAY}complete...${NC}\n\n"
# -----------------------------------
# Success! At this point we are live.
# -----------------------------------
printf "${GREEN}Files successfully deployed and linked! Latest release is LIVE!! Starting cleanup...${NC}\n\n"
# ----------------
# Cleanup
# ----------------
printf "${ORANGE}Cleaning: old releases (keeping max of ${RELEASES_TO_KEEP} total)${NC}\n"
cd ${RELEASES_FOLDER} && ls -t | tail -n +$(expr ${RELEASES_TO_KEEP} + 1) | xargs rm -rf
cd ../
printf "${DGRAY}complete...${NC}\n\n"
# ----------------
# Post Deployment
# ----------------
printf "${GREEN}Huzzah! The atomic deployment has completed sucessfully!${NC}\n\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment