Skip to content

Instantly share code, notes, and snippets.

@ninapavlich
Last active March 4, 2020 22:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninapavlich/adbf95b2ea2437e82670cd0e8e8d083d to your computer and use it in GitHub Desktop.
Save ninapavlich/adbf95b2ea2437e82670cd0e8e8d083d to your computer and use it in GitHub Desktop.
Bash script that will check a directory for a new commit in a remote repository, and deploy if detects an update
#!/bin/bash
# This script will watch a given directory with a .git checkout and execute a deployment if it detects an update.
# You can set this up with CRON so that deployments happen automatically.
#
# Example CRON usage:
# crontab -e
# */5 * * * * bash /path/to/scripts/deploy.sh
#
# Example manual usage:
# bash /path/to/scripts/deploy.sh force
#
# -----------------------------------
# PARSE ARGUMENTS
# -----------------------------------
GIT_DIR="/srv/project-name/src/"
SLACK_WEBHOOK='https://hooks.slack.com/services/XXXXXXX/XXXXXXX/XXXXXXXXXXXXXX'
REPO_URL_ROOT='https://bitbucket.org/XXXXXXX/XXXXXXXXXXXXXX/commits/'
TEST_URL='https://XXXXXXXXXXXXXX/api/'
TEST_STATUS_CODE=200
FORCE_RAW=$1
FORCE=false
if [ "$FORCE_RAW" = "force" ]; then
FORCE=true
fi
SECONDS=0
# -----------------------------------
# Check Current Git Status
# -----------------------------------
echo "Fetching... (Force Update? $FORCE)"
GIT_FETCH_OUTPUT=$( (git --git-dir=$GIT_DIR.git --work-tree=$GIT_DIR fetch) 2>&1)
echo "$GIT_FETCH_OUTPUT"
GIT_LOCAL_OUTPUT=$( (git --git-dir=$GIT_DIR.git --work-tree=$GIT_DIR rev-parse @{u}) 2>&1)
GIT_REMOTE_OUTPUT=$( (git --git-dir=$GIT_DIR.git --work-tree=$GIT_DIR rev-parse HEAD) 2>&1)
echo "Local is at $GIT_LOCAL_OUTPUT ... Remote is at $GIT_REMOTE_OUTPUT"
if [ $GIT_LOCAL_OUTPUT = $GIT_REMOTE_OUTPUT ] && [ $FORCE = false ]; then
echo "Up-to-date"
else
# -----------------------------------
# Notify that deployment has started
# -----------------------------------
SECONDS=0
/usr/bin/curl \
-X PUT \
-s \
--data-urlencode "payload={ \
\"pretext\": \"New deployment started for $GIT_DIR\", \
\"text\": \"Local is at $GIT_LOCAL_OUTPUT ... Remote is at $GIT_REMOTE_OUTPUT\" \
}" \
$SLACK_WEBHOOK
# -----------------------------------
# Execute deployment
# -----------------------------------
GIT_CHECKOUT_OUTPUT=$( (git --git-dir=$GIT_DIR.git --work-tree=$GIT_DIR checkout master) 2>&1)
GIT_RESET_OUTPUT=$( (git --git-dir=$GIT_DIR.git --work-tree=$GIT_DIR reset --hard origin/master) 2>&1)
echo "$GIT_CHECKOUT_OUTPUT"
echo "$GIT_RESET_OUTPUT"
# - Manage virtual environment
VIRTUALENV_OUTPUT=$( ($GIT_DIR/venv/bin/pip install -r $GIT_DIR/requirements.txt) 2>&1)
echo "$VIRTUALENV_OUTPUT"
# - Update database
MIGRATED_OUTPUT=$( ($GIT_DIR/venv/bin/python $GIT_DIR/manage.py migrate) 2>&1)
echo "$MIGRATED_OUTPUT"
# - Collect static
STATIC_COLLECTED_OUTPUT=$( ($GIT_DIR/venv/bin/python $GIT_DIR/manage.py collectstatic --noinput) 2>&1)
echo "$STATIC_COLLECTED_OUTPUT"
# - Restart UWSGI app
RESTARTED_UWSGI_OUTPUT=$( (systemctl restart emperor.uwsgi) 2>&1)
echo "$RESTARTED_UWSGI_OUTPUT"
# - Restart NGINX
RESTARTED_NGINX_OUTPUT=$( (systemctl restart nginx) 2>&1)
echo "$RESTARTED_NGINX_OUTPUT"
# -----------------------------------
# Verify Success by hitting testing endpoint
# -----------------------------------
TEST_STATUS_CODE_OUTPUT=$(curl -s -o /dev/null -w '%{http_code}' $TEST_URL)
echo "GET $TEST_URL : $TEST_STATUS_CODE_OUTPUT"
if [ $TEST_STATUS_CODE_OUTPUT -eq $TEST_STATUS_CODE ]; then
MESSAGE_COLOR="good"
else
MESSAGE_COLOR="danger"
fi
# -----------------------------------
# Send completion message
# -----------------------------------
duration=$SECONDS
VIEW_COMMIT_URL="$REPO_URL_ROOT$GIT_REMOTE_OUTPUT"
/usr/bin/curl \
-X PUT \
-s \
--data-urlencode "payload={ \
\"attachments\": [ \
{ \
\"fallback\": \"Deployment complete for $GIT_DIR to $GIT_REMOTE_OUTPUT after $duration seconds.\", \
\"color\": \"$MESSAGE_COLOR\",\
\"title\": \"Deployment complete for $GIT_DIR\", \
\"text\": \"Deployment updated to $GIT_REMOTE_OUTPUT after $duration seconds.\", \
\"fields\": [ \
{ \
\"title\": \"Git Update\", \
\"value\": \"${GIT_FETCH_OUTPUT//\"/\\\"}\n\n${GIT_CHECKOUT_OUTPUT//\"/\\\"}\n\n${GIT_RESET_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Managed Virtual Environment\", \
\"value\": \"${VIRTUALENV_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Migrated Databases\", \
\"value\": \"${MIGRATED_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Collected Static Files\", \
\"value\": \"${STATIC_COLLECTED_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Restarted UWSGI\", \
\"value\": \"${RESTARTED_UWSGI_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Restarted NGINX\", \
\"value\": \"${RESTARTED_NGINX_OUTPUT//\"/\\\"}\"
}, \
{ \
\"title\": \"Test Deployment\", \
\"value\": \"$TEST_URL returned $TEST_STATUS_CODE_OUTPUT\"
} \
], \
\"actions\": [\
{\
\"type\": \"button\",\
\"text\": \"View Commit\",\
\"url\": \"$VIEW_COMMIT_URL\"\
},\
{\
\"type\": \"button\",\
\"text\": \"View Site\",\
\"url\": \"$TEST_URL\"\
}\
]\
} \
]\
}" \
$SLACK_WEBHOOK
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment