What's New
Deep integration between Soup and the HuggingFace Hub — auto-push checkpoints, Collections, self-hosted endpoints, HF Datasets write, HF Spaces auto-deploy, and a richer auto-generated model card.
- Auto-push checkpoints —
soup train --push-as user/my-modeluploads everysave_stepscheckpoint as acheckpoint-<N>branch on HuggingFace Hub. Pair with--hf-resumeto pull the latest and keep going after a crash. - HuggingFace Collections —
soup push --collection user/my-collection-abc123adds the pushed repo to an existing Collection. Idempotent: re-push is a no-op when the repo is already there. - Self-hosted Hub — set
HF_ENDPOINT=https://hf.internal.example.comand every HF operation in Soup routes there. Localhost HTTP permitted; private / link-local / cloud-metadata IPs rejected. - Publish HF datasets —
soup data push --input data.jsonl --hf-dataset user/my-datauploads a local JSONL file as an HF dataset repo (inverse ofsoup data download, shipped v0.24.0). - Deploy HF Space —
soup deploy hf-space --model user/my-model --space user/my-space --template gradio-chatcreates a Gradio (orstreamlit-chat) Space wrapping the fine-tuned model in one command. - Model card v2 — the auto-generated README now surfaces the training config (task / base / lr / optimizer) and an optional eval scorecard. Markdown-active characters in task names are neutralised for safe rendering on HF Hub.
Install / Upgrade
```bash
pip install --upgrade soup-cli
or from a fresh env:
pip install soup-cli==0.29.0
```
No new required dependencies. `huggingface-hub` is already a core dep.
Security
- SSRF-hardened `HF_ENDPOINT` — scheme allowlist (http/https only), `0.0.0.0` explicitly rejected, plain-HTTP restricted to loopback (`localhost` / `127.0.0.1` / `::1`). RFC1918 / link-local / cloud-metadata endpoints (`10.x`, `172.16.x`, `192.168.x`, `169.254.169.254`) rejected via `ipaddress.ip_address`.
- Repo ID validation applied to `soup push --repo`, `soup train --push-as`, `soup data push --hf-dataset`, `soup deploy hf-space --model/--space`: alphanumeric + `._-` only, per-component ≤96 chars, total ≤200, null-byte / whitespace / `..` / leading-`/` rejected.
- `soup push --model` cwd containment — prevents a crafted `soup.yaml output:` from silently uploading system files.
- Auto-push allow-list — `HFPushCallback` restricts uploaded files to `.safetensors` / `.bin` / `.pt` / `.json` / `tokenizer*` / `trainer_state.json` / `training_args.bin` / `README.md`, keeping `.env` and source files out of auto-pushed branches if `output_dir` ever overlaps the project root.
- `prepare_hf_resume` enforces cwd containment and passes `local_dir_use_symlinks=False` to `snapshot_download`, defeating symlink-based filesystem escape on older `huggingface_hub` versions.
- Commit message sanitisation — multi-line commit messages are stripped to the first line and capped at 200 chars in both `soup push` and `soup data push`.
- Model card v2 — task names, non-numeric scores, and the `data_lineage` kwarg are neutralised / HTML-escaped before being embedded in the README rendered on HF Hub.
- HF Space template rendering validates `model_repo` via `validate_repo_id` before substitution — a crafted repo id cannot inject Python code into the deployed Space.
- Single-source token resolution via `utils/hf.resolve_token` (env > cached login), explicit non-printable tokens rejected. `push --token` flag now emits a deprecation warning.
Full per-feature security notes live in SECURITY.md.
Known Limitations
- No end-to-end `--push-as` integration test — the wiring from `build_push_callback` → `trainer.add_callback` is exercised via unit tests only, because a real HF Trainer requires `torch` + `transformers` + a live Hub connection. Tracked in #49.
- Auto-resume pulls the latest `checkpoint-` branch regardless of recency — `--hf-resume` does not compare HF remote last-modified against the current local clock, so a stale branch from months ago will be used if no newer one exists. Use `--resume ` explicitly when you need surgical control. Tracked in #50.
- `soup deploy hf-space` ships two templates (`gradio-chat`, `streamlit-chat`). Custom templates via `--template-dir` are tracked for v0.29.1 in #51.
See the full security log and the changelog on GitHub.