This guide is for people who want to run SFTPWarden from source, contribute a change, build documentation, or validate the project before publishing a release.
For the shorter GitHub contribution guide, see CONTRIBUTING.md.
SFTPWarden uses dev as the integration branch and main as the protected
production/release branch.
Contributors should not work directly on dev or open normal pull requests to
main. Instead:
- Fork the repository.
- Create your own branch from
dev. - Develop and validate your change in that branch.
- Open a Pull Request from your branch to
dev.
git clone https://github.com/<your-user>/sftpwarden.git
cd sftpwarden
git remote add upstream https://github.com/kithuto/sftpwarden.git
git fetch upstream
git checkout -b dev upstream/dev
git checkout -b fix/my-changeAfter development, push your branch and open:
fix/my-change -> dev
The maintainer promotes accepted changes from dev to main when preparing
production updates or public releases.
git clone https://github.com/kithuto/sftpwarden.git
cd sftpwarden
git checkout dev
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev,docs,mysql,postgres,mongodb]"
sftpwarden --versionThe mysql extra also enables MariaDB because both providers use PyMySQL. The
mariadb extra is an alias for the same dependency.
Use Python 3.11, 3.12, 3.13, or 3.14. Install the Python versions locally before
running the full tox matrix.
Create a branch from dev before changing files:
git checkout dev
git pull origin dev
git checkout -b fix/my-changeRun the CLI from the editable install:
sftpwarden doctor
sftpwarden validate --config examples/yaml/sftpwarden.yamlBuild the runtime image when changing Docker/runtime behavior:
docker build -t sftpwarden:local -f docker/runtime/Dockerfile .
docker run --rm --entrypoint sh sftpwarden:local -c 'command -v sshd && command -v sftpwarden'For Kubernetes, Helm, or runtime changes that affect the container in a cluster,
run a real Kubernetes or Helm smoke test when feasible. At minimum, render the
manifests or values, run helm lint, and confirm the runtime image builds.
Build the watcher image when changing watcher behavior:
docker build -t sftpwarden-watcher:local -f docker/watcher/Dockerfile .
docker run --rm --entrypoint sh sftpwarden-watcher:local -c 'command -v sftpwarden'Run the full validation:
toxThe default tox run covers:
- lint and formatting;
- tests on Python 3.11, 3.12, 3.13, and 3.14;
- coverage once, instead of repeating it for every Python version;
- Sphinx documentation build;
- package build and wheel content check;
- dependency audit.
Run one part:
tox -e lint
tox -e py311
tox -e py312
tox -e py313
tox -e py314
tox -e coverage
tox -e docs
tox -e package
tox -e audit
tox -e cleanRun pytest directly while iterating:
python -m pytest
python -m pytest tests/test_cli.pyThe Sphinx source lives in docs/. docs/index.md owns the main navigation,
and static assets live under docs/_static/.
Build the Sphinx site locally:
python -m pip install -e ".[docs]"
sphinx-build -b html docs docs/_build/htmlThe CI-friendly validation command is:
tox -e docsKeep the README focused on adoption. Put deeper explanations in the specific docs pages:
The public documentation site is published by .github/workflows/docs.yml.
Pushes to main that touch README.md, CONTRIBUTING.md, SECURITY.md,
CODE_OF_CONDUCT.md, or docs/** build the HTML site on Python 3.14 with:
sphinx-build -b html docs docs/_build/htmlThe workflow uploads docs/_build/html as a GitHub Pages artifact and deploys it
with actions/deploy-pages. Documentation-only pull requests should still run
tox -e docs before review so broken links, invalid MyST, and Sphinx warnings
are caught before the workflow publishes from main.
Keep public behavior stable unless the change is intentional and documented:
- CLI command names and option names should remain compatible.
sftpwarden.yaml, provider files, SQL schemas, and context registry formats should remain compatible.- Runtime state should remain readable across upgrades.
- JSON output should stay parseable.
For user/provider changes, add tests that cover both service behavior and CLI behavior when the CLI output matters.
For remote/deploy/watcher changes, include dry-run coverage so generated SSH, rsync/scp, Docker, and scheduler commands stay reviewable.
Tox cleans Python caches, coverage output, docs output, and package artifacts
after the environments that generate them. Run tox -e clean to clean the same
local artifacts plus Docker smoke-test images.
Before opening a PR:
- target
dev, notmain; - for docs-only changes, run
tox -e docs; - for code changes, run
tox; - for Docker/runtime changes, build the affected Docker image locally;
- update README/docs when adoption or operations behavior changes;
- update examples when configuration changes;
- redact secrets from logs and screenshots;
- describe the user-facing behavior, validation performed, and any known limits.
Before a public release:
tox
python -m build
docker build -t sftpwarden:local -f docker/runtime/Dockerfile .
docker build -t sftpwarden-watcher:local -f docker/watcher/Dockerfile .
sftpwarden validate --config examples/yaml/sftpwarden.yaml
sftpwarden validate --config examples/csv/sftpwarden.yaml
sftpwarden validate --config examples/sqlite/sftpwarden.yaml
SFTPWARDEN_MYSQL_DSN=mysql://user:pass@localhost/sftp \
sftpwarden validate --config examples/mysql/sftpwarden.yaml
SFTPWARDEN_MARIADB_DSN=mariadb://user:pass@localhost/sftp \
sftpwarden validate --config examples/mariadb/sftpwarden.yaml
SFTPWARDEN_POSTGRES_DSN=postgresql://user:pass@localhost/sftp \
sftpwarden validate --config examples/postgres/sftpwarden.yaml
SFTPWARDEN_MONGODB_DSN=mongodb://localhost:27017/sftp \
sftpwarden validate --config examples/mongodb/sftpwarden.yaml
helm lint charts/sftpwarden
helm template sftpwarden charts/sftpwarden --namespace sftpwardenAlso check the repository-level security workflow before publishing: dependency audit, container scan, SBOM generation, and OpenSSF Scorecard.