I used to use Fabric to deploy my personal apps, but I often ran into issues with it, so several months ago I switched over to simple shell scripts that use ssh. Much more resilient, and far easier to maintain (at least for me).
Here’s a sample of what one of these deploy scripts looks like for a Django app:
#!/bin/sh
git push
ssh myusername@myhost /bin/zsh << EOF
cd /path/to/app/code/
echo "- Pulling the code"
git checkout main && git pull
echo "- Restarting the app"
supervisorctl restart myappname
echo "- Running migrations"
/path/to/venv/bin/python manage.py migrate
echo "- Collecting static"
/path/to/venv/bin/python manage.py collectstatic --noinput
EOF
I’ve thought about using a CD pipeline instead, but I’m not convinced that introducing an extra dependency — no matter how slick — is actually worth it for something small and personal like this. (CI/CD sure is nice at work, however.)