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.
#!/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