Simple bash deployment script for Django

This is an update for my post about automated django deployments

Edit 09-2020: I've expanded the script to fetch remote data and load it into the local Django dev instance. Make sure you never run this script anywhere except than a development environment.

Raw
#!/bin/bash

# Fixed settings
commit=$(git rev-parse HEAD)
date=$(date +%Y%m%d_%H%M%S)
name="${date}_${commit}"
git="~/${name}/git"
src="${git}/src"
# settings="${src}/src/conf/settings/"
venv="~/${name}/virtualenv"
manage="${venv}/bin/python ${git}/src/manage.py"
manage_latest="~/latest/virtualenv/bin/python latest/git/src/manage.py"
archive="${name}.tar.gz"
previous="previous"
latest="latest"

# Dynamic settings
python=/usr/bin/python3.7
pidfile="${previous}/git/src/user.pid"
remote_suggestion="user@example.com"
compilemessages=1

# Arg "parsing"
cmd=$1
remote=${2:-${remote_suggestion}}

if [[ ! "${remote}" ]]; then
  echo "No remote given, aborting, try ${remote_suggestion}"
  exit 1
fi
if [[ ! "${cmd}" ]]; then
  echo No command given, aborting, try deploy remoteclean getdata getdatafull
  exit 1
fi

_getdata () {
  exclude="$*"
  set -e
  echo "Dumping prod data"
  echo "exclude ${exclude}"
  ssh "${remote}" "${manage_latest} dumpdata --format json --indent 2 --natural-foreign --natural-primary ${exclude} -o data.json"
  echo "Fetching prod data"
  if [ ! -d data ]; then
    mkdir data/
  fi
  rsync -avz --progress "${remote}:data.json" data/
  cat data/data.json > src/data.json
  rsync -avz "${remote}:media" docker
}

loaddata () {
  # Thorough database reset before loading data
  flush="._sqlflush.sql"
  ./manage.py sqlflush --no-color > "$flush"
  ./manage.py dbshell < "$flush"
  ./manage.py migrate
  ./manage.py loaddata src/data.json
  ./manage.py update_index
  rm -f "$flush"
  grep '^  "model":' src/data.json  | sort | uniq --count | sort --numeric
}

getdata () {
  # Exclude models we don't usually want
  _getdata -e admin.logentry -e sessions.session
}

getdatafull () {
  # Exclude models we never want
  _getdata -e sessions.session
}

if [[ "${cmd}" == "deploy" ]]; then
  set -e
  echo "Transfer archive..."
  git archive --format tar.gz -o "${archive}" "${commit}"
  scp "${archive}" "${remote}:"
  rm -f "${archive}"

  echo "Install files"
  ssh "${remote}" mkdir -p "${git}"
  ssh "${remote}" tar xzf "${archive}" -C "${git}"

  echo "Updating tor exit node list..."
  ssh "${remote}" "cp ${git}/download_tor.sh ."
  ssh "${remote}" "cp ${git}/download_maxmind.sh ."
  ssh "${remote}" "bash download_tor.sh ${src}/conf/settings/"

  echo "Install virtualenv"
  ssh "${remote}" virtualenv --quiet "${venv}" -p ${python}
  ssh "${remote}" "${venv}/bin/pip" install --quiet --upgrade pip setuptools
  ssh "${remote}" "${venv}/bin/pip" install --quiet -r "${git}/requirements.txt"

  echo "Set up django..."
  ssh "${remote}" "${manage} check"
  ssh "${remote}" "${manage} check --deploy"
  ssh "${remote}" "${manage} migrate --noinput"
  if [[ ${compilemessages} -gt 0 ]]; then
    ssh "${remote}" "cd ${git} && ${manage} compilemessages"
  fi
  ssh "${remote}" "${manage} collectstatic --noinput"

  echo "Switching to new install..."
  ssh "${remote}" rm -fv "${previous}"
  set +e  # first deploy
  ssh "${remote}" mv -v "${latest}" "${previous}"
  set -e
  ssh "${remote}" ln -s "${name}" "${latest}"
  echo "Killing old worker, pidfile ${pidfile}"
  ssh "${remote}" "test -f ${pidfile} && kill -15 \$(cat ${pidfile}) || echo pidfile not found"


  echo "Cleaning up..."
  ssh "${remote}" rm -f "${archive}"
  rm -f "${archive}"
  set +e
elif [[ "${cmd}" == "getdata" ]]; then
  getdata
elif [[ "${cmd}" == "getdatafull" ]]; then
  getdatafull
elif [[ "${cmd}" == "loaddata" ]]; then
  loaddata
elif [[ "${cmd}" == "go" ]]; then
  getdata
  loaddata
elif [[ "${cmd}" == "gofull" ]]; then
  getdatafull
  loaddata
fi

if [[ "${cmd}" == "deploy" || "${cmd}" == "remoteclean" ]]; then
  echo "Deleting obsolete deploys"
  ssh "${remote}" '/usr/bin/find . -maxdepth 1 -type d -name "2*" | ' \
    'grep -v "$(basename "$(readlink latest)")" | ' \
    'grep -v "$(basename "$(readlink previous)")" | ' \
    '/usr/bin/xargs /bin/rm -rf'
  ssh "${remote}" rm -fv 2*tar.gz
fi

0 comments

Reply

Cancel reply
Markdown. Syntax highlighting with <code lang="php"><?php echo "Hello, world!"; ?></code> etc.
DjangoPythonBitcoinTuxDebianHTML5 badgeSaltStackUpset confused bugMoneyHackerUpset confused bugX.OrggitFirefoxWindowMakerBashIs it worth the time?i3 window managerWagtailContainerIrssiNginxSilenceUse a maskWorldInternet securityPianoFontGnuPGThunderbirdJenkinshome-assistant-logo