Published June 23, 2026 — Hugging Face described how it shifted the huggingface_hub release process from a 4–6 week cadence to weekly releases driven by a single GitHub Actions workflow. The team built the pipeline from open tools and open-weight models, and kept a human reviewer at the decision point where judgement matters.
Why they changed
huggingface_hub is the core Python client in the Hugging Face ecosystem; many libraries (for example transformers, datasets, diffusers, sentence-transformers) depend on it to talk to the Hub. Weeks without a release left fixes and features stuck on main. Preparing release notes, aggregating tens of PRs and drafting announcements was not technically hard but required focused time — historically several hours up to half a day for a minor release.
Two kinds of work
The process splits into mechanical steps that can be automated (version bumps, commits, tags, pushes, creating downstream test branches, opening post-release PRs) and judgment work (writing release notes, picking highlights, phrasing a human-facing announcement). The automated steps are well-suited for CI; the writing is where a language model can produce a solid first draft quickly. Because models can be confidently wrong, the flow keeps a human reviewing the draft.
Design principles: open parts and reusability
From the start the team required that every moving part be something any maintainer can run: no closed model behind an unreplaceable API, no proprietary release platform. The stack includes:
- GitHub Actions to orchestrate the release.
- OpenCode as the agent runtime that drives the model.
- An open-weights model (currently GLM-5.2 from Z.ai) to draft release notes and the Slack announcement.
- HF Inference Providers to serve the model.
- PyPI Trusted Publishing for package publication with OIDC and PEP 740 / Sigstore attestations.
The second principle is simple: the model drafts, a human decides. The model is fast at turning terse PR titles into readable notes, but deterministic validation and a human reviewer prevent shipping incomplete or invented content.
A tour of the pipeline
The whole workflow lives in one file (.github/workflows/release.yml), triggered manually via the Actions UI, with a single input (release_type: minor-prerelease, minor-release, patch-release). Jobs run roughly in this order:
- Prepare: compute next version, create or reuse release branch, bump version, commit, tag, push.
- Publish to PyPI: build and upload huggingface_hub and, in parallel, the hf CLI PyPI package.
- Release notes: diff the commit range since the last tag, pull PR metadata from the GitHub API, and have the model draft a structured changelog; save as a draft GitHub release.
- Downstream test branches: for RCs, open branches in transformers, datasets, diffusers, sentence-transformers with the RC pinned so their CI quickly signals regressions.
- Slack announcement: produce an internal announcement in the team voice from the notes.
- Archive notes: upload both the raw AI draft and the human-edited version to a Hugging Face Bucket.
- Post-release bump: after a stable release, open a PR on main bumping to the next dev0.
- Comment on shipped PRs: leave a "this shipped in vX.Y.Z" comment on every PR in the release.
- Sync CLI docs: open a PR to the skills repo with regenerated hf CLI docs.
- Report to Slack: every step posts its status as a thread reply and a final job updates the root message with ✅ or ❌.
The remaining manual steps are reviewing and publishing the draft release notes and reviewing/posting the internal Slack message — the human-in-the-loop checkpoints.
Trust but verify: the human-in-the-loop core
A major risk with AI-generated notes is omission or invention of PRs. To avoid shipping wrong changelogs, the workflow first deterministically extracts all PR numbers that should be in the release (for example by parsing squash-merge commit messages) and saves them as the source of truth (a manifest). The model drafts notes from that manifest, then the system extracts PR references from the model output and compares them to the manifest. If there are missing or extra PRs, the flow does not publish; instead it hands the discrepancy back to the agent and asks it to fix exactly those PRs. This loop repeats until the notes match the manifest exactly. The pattern wraps a non-deterministic model in deterministic guardrails.
Grounding the model so it doesn't make things up
Completeness is one side; accuracy is the other. A model summarizing a PR from its title alone can invent code examples. To prevent that, the workflow fetches documentation diffs for each PR (the unified diff of any docs/*.md file touched by the PR) and includes those diffs in the model context. That way, when the model writes "here's the new CLI command," it can quote the example the PR author actually added. Prompts live as small Markdown "skills" checked into the repo (SKILL.md plus templates) and instruct the agent how to pick highlights, structure sections, and when to add doc links.
The human checkpoint
After the RC is published, the draft GitHub release contains the AI's first pass. A reviewer reads and edits it for tone, emphasis, and balance, then triggers the minor-release run to promote the RC to final. The editing step typically reduces what used to be a half-day of writing to a roughly 15-minute review. The pipeline archives both the raw AI draft (at RC time) and the human-edited version (at release time) to a Hugging Face Bucket, creating a dataset of model outputs versus desired edits that can inform future improvements to the agent's skills.
Open and secure plumbing
Reworking the release process also allowed tightening supply-chain security:
- No long-lived PyPI token: publishing uses Trusted Publishing with OIDC short-lived tokens minted by GitHub for this workflow and generates PEP 740 / Sigstore provenance for artifacts.
- Agent runtime is pinned and checksum-verified; the team does not run unverified remote installers.
- The workflow uses pypa/gh-action-pypi-publish@v1.14.0 with attestations=true so there is no password or API token in the job.
What did it cost?
A full release (notes plus Slack announcement across 20–40 PRs and a few rounds of prompting) costs about $0.25 on Inference Providers when using open weights billed pay-as-you-go.
What changed in practice
The release cadence moved from every 4–6 weeks to weekly. Secondary effects included better first drafts of notes (review time is now polishing instead of writing), earlier surfacing of integration breakages via downstream test branches, and shorter contributor loops thanks to the automatic "shipped in vX.Y.Z" comments.
Make it yours
The workflow is shaped around huggingface_hub but is intentionally generic: the trigger and version-bump logic, the trust-but-verify loop (deterministic manifest, model draft, validate, re-prompt), OIDC Trusted Publishing, pinned runtimes, and skill-based prompts are reusable. Project-specific parts — downstream repo list, skill tone, Slack and bucket destinations — should be adapted. To adopt it: fork the workflow and scripts, set the package and model IDs and OpenCode version, configure Trusted Publishing on PyPI, and remove downstream-testing if you don't have downstreams. The trust-but-verify loop is the most reusable piece and is what makes generated artifacts safe to ship.
What's next
Planned extensions include auto-triaging downstream failures by analyzing failing CI logs and reusing the pattern across other Python libraries in the ecosystem.
Takeaway
The parts of a release that used to need a half-day of focused human work (writing notes, drafting announcements, coordinating downstream checks) are exactly the parts a model can draft. Mechanic tasks belong in a YAML file. The effective pattern is: let the model draft, use deterministic code to verify, and have a human make the final call. Built from open tools and open weights, the system is low-cost and reproducible; the full workflow file is public and the team invites maintainers to fork it and adapt it.



