# Reproducibility
The goal: after a deploy, the parts of the server the library owns are a function of your script, not of what was there before. Run the same script twice, or run it against a fresh server, and you get the same result.
What that covers:
- Uploads.
upload_fileandupload_directoryremove the destination first. The remote tree is exactly your local tree minus the ignored patterns. Addmode=and the permissions stop depending on the machine you deploy from too. - Venvs.
create_venvwipes and rebuilds by default. Packages you stopped declaring disappear, pinned versions really apply, and changing the target Python version actually changes the interpreter — none of which happens in a reused venv. - Services. The configuration file of a deployed service is rewritten from the
SupervisorServicemodel every time. What you declare is what supervisord reads.
What it does not cover — real gaps, not oversights:
- System packages and OS state. pacman/apt, users, nginx, databases, firewall, cron. Out of scope; the library doesn't touch them (the one exception is
install_supervisor, because services are its job). - Files the app creates at runtime. Databases, logs, uploads, caches. They live wherever your app puts them and survive every deploy — which is normally what you want. If one lands inside an upload destination, it gets wiped: keep runtime data outside deploy directories.
- Services deployed by previous runs.
deploy_supervisor_servicemanages the service you hand it and nothing else. Services from earlier runs stay untouched, and stay running.
# Limitation: orphan services
There is no prune. If you rename a service — say myapp becomes myapp-web — the new configuration is deployed and started, and the old myapp keeps running with the old code, from a venv you may have just rebuilt underneath it. Same if you drop a service from your script: it isn't removed, it just stops being managed.
A prune that deleted every configuration not declared in your script would, on a host shared with other apps, take down services this library never deployed. So removing a service is manual:
conn.sudo("supervisorctl stop myapp")
conn.sudo("rm /etc/supervisor/conf.d/myapp.conf") # Debian/Ubuntu
# conn.sudo("rm /etc/supervisor.d/myapp.ini") # Arch
conn.sudo("supervisorctl update")