-
Type:
Task
-
Resolution: Fixed
-
Priority:
Unknown
-
Affects Version/s: None
-
Component/s: ABX
-
None
-
None
-
Python Drivers
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Goal
Remove TestPyPI from the release process for all four libraries in this monorepo, replacing the TestPyPI round-trip with local validation. Mirrors PYTHON-5971 / winkerberos#161 and PYTHON-5970 (PyMongo).
Context
Per PYTHON-5971, the PyPI admins are deprecating TestPyPI and have already de-prioritized it (see the Python Discuss thread). PyMongo and winkerberos have already moved off it, substituting validate-pyproject and twine check --strict.
Two additional reasons specific to this repo:
- TestPyPI is a hard blocker for the first langchain-mongodb-deepagents-vfs release. Trusted publishing needs a pending publisher registered on every index used, and the maintainer's TestPyPI account name/email does not match their PyPI one — recoverable only by emailing PyPI support.
- _test_release.yml passes skip-existing: true, which its own comment describes as "only for CI use and extremely dangerous otherwise".
Current state (verified on main at 006027e)
_release.yml has four jobs: build -> test-pypi-publish -> pre-release-checks -> publish -> mark-release.
The coupling is deeper here than in winkerberos, which only had a publish step to delete. pre-release-checks installs the package from TestPyPI in order to validate the built artifact the way a consumer would receive it:
uv run pip install --extra-index-url https://test.pypi.org/simple/ "$PKG_NAME==$VERSION" || \ ( sleep 5 && uv run pip install --extra-index-url https://test.pypi.org/simple/ "$PKG_NAME==$VERSION" )
TestPyPI was only the delivery mechanism for that check, so it can be replaced by installing the wheel directly from the dist artifact the build job already uploads. Note pre-release-checks does not currently download that artifact, so a download-artifact step must be added.
Blocker found while implementing: twine must be pinned
Copying the house recipe verbatim does not work here. twine check --strict fails on our artifacts:
$ uvx twine check --strict dist/*
ERROR InvalidDistribution: Invalid distribution metadata: '2.5' is not a valid metadata version
This is not stale tooling — uvx resolves twine 6.2.0, and twine <7 cannot parse Metadata-Version: 2.5, which current hatchling emits. Pinning fixes it:
$ uvx --from 'twine>=7' twine check --strict dist/*
Checking dist/langchain_mongodb-0.12.0-py3-none-any.whl: PASSED
Checking dist/langchain_mongodb-0.12.0.tar.gz: PASSED
PyPI itself accepts Metadata 2.5 — hatchling 1.32.0 and langsmith 0.11.1 are both published with it — so twine was simply behind. This also retroactively explains the test_distribution.py failure removed in #427.
Changes
| File | Change |
|---|---|
| .github/workflows/_test_release.yml | deleted (89 lines) |
| .github/workflows/_release.yml | test-pypi-publish job removed; 3 needs: entries dropped; validate-pyproject + twine check --strict added to build; pre-release-checks reworked to install from the dist artifact |
| TRUSTED_PUBLISHING.md | second publisher registration removed; only PyPI is needed now |
| RELEASE.md | no change — it never referenced TestPyPI |
Trade-off
Lost: a genuine round-trip through a warehouse instance, which implicitly proved PyPI would accept the artifact's metadata before the real upload. That failure now surfaces in publish instead. twine check --strict in the build job is the intended mitigation and covers the same class of problem locally.
Gained: dependencies in pre-release-checks now resolve from real PyPI rather than a TestPyPI/PyPI hybrid, making it a more faithful consumer simulation than before; one fewer OIDC publisher per new package; skip-existing gone; shorter pipeline.
Acceptance criteria
- No reference to TestPyPI anywhere in .github/.
- _release.yml job graph remains correctly ordered: build -> pre-release-checks -> publish -> mark-release.
- validate-pyproject passes for all four libs.
- twine check --strict passes for all four libs with twine>=7.
- A release can be run end to end without any TestPyPI account.
Verification basis
validate-pyproject confirmed passing for all four libs. twine check --strict with twine>=7 confirmed passing for langchain-mongodb and langchain-mongodb-deepagents-vfs builds. Workflow YAML validated with the repo's own check-yaml and Validate GitHub Workflows pre-commit hooks, and the resulting job dependency graph parsed and inspected.