Add the one-time PyPI name-reservation workflow#25
Draft
mmanciop wants to merge 6 commits into
Draft
Conversation
Rename the four vendored packages at the distribution-name level only: import paths and entry-point names stay upstream-shaped so that switching to the official opentelemetry-* packages, once upstream publishes them, is a dependency swap rather than a migration. The distro now pins the renamed exporters exactly like every other dependency, and all versions move to release form (1.44.0; the distro is 0.1.0) ahead of the first publication on the Dash0 package index.
scripts/build_simple_index.py regenerates the static package index from all published, non-draft GitHub releases: assets are downloaded and re-hashed, verified against the committed manifest (the immutability guard - a filename can never change bytes once indexed), restricted to the five expected projects and this repository's release-asset origin, and rendered as PEP 503/592 HTML with #sha256= fragments so consumers can install with --require-hashes. The HTML is emitted directly with the standard library: dumb-pypi, the planned generator, joins one base URL with each filename and cannot express per-file release-asset URLs, which embed the release tag. Stdlib-only also means no third-party code runs in the job that controls what consumers' lockfiles hash-pin. Recovery levers, both git-audited: scripts/index-excluded.toml skips a poisoned filename past the guard; scripts/index-yanked.toml marks a version yanked without deleting anything.
Replace PyPI/TestPyPI publishing with the self-hosted channel. Pushing a vX.Y.Z tag builds only artifacts whose filenames are not yet in the committed manifest (rebuilds are not byte-stable across toolchain upgrades), attests provenance, uploads them to a draft release, and publishes it as the final step so immutable releases always lock a complete asset set. The index job then regenerates and deploys the PEP 503 site, committing manifest additions to main with a dedicated deploy key. workflow_dispatch offers rebuild-index, dry-run (index artifact, no deploy, no manifest commit), and rebuild-assets recovery modes. Hardening: per-job least-privilege permissions, env indirection for event fields, SHA-pinned third-party actions, pinned uv and hatchling (build constraints), no dependency cache, queued concurrency.
RELEASING.rst is rewritten around the new pipeline: the formerly open publishing decisions recorded as resolved, the release checklist, the recovery runbooks (dry run, index rebuild, dropped concurrency runs, yank, immutability-guard trips), the one-time admin setup including the mandatory trusted-publisher removal after name reservation, and the consumer contract (hash-pinned installs, only-binary, Renovate registryUrls, attestation verification). READMEs and CONTRIBUTING now explain the dash0-opentelemetry-* publication names and index-based installation.
Address the confirmed findings from the pre-ship code review: - Read the manifest from origin/main in the build job, not from the tag checkout: a tag cut before the previous release's manifest commit landed would rebuild already-published filenames with different bytes and freeze index generation on the immutability guard. - Drop the index-time rejection of stable-versioned assets on GitHub pre-releases: rehearsal rc releases legitimately carry the vendored packages' stable versions, and any post-publish index failure on immutable assets is a pipeline deadlock by construction. Pre-release semantics live in the PEP 440 version string. - Sort releases oldest-first before deduplication: the GitHub API returns newest-first, so the 'original release URL wins' intent was inverted in production (and the test encoded the inversion). - Fail index generation when a yank entry matches no indexed file instead of silently serving the version the maintainer believes was withdrawn. - Add scripts/check_version_bumped.py to CI: a package change merged without a version bump would be silently skipped at release time (its filename is already in the manifest) while the run goes green. - Fail with explicit guidance when a release was published outside the pipeline (immutable and asset-less; the version must be burned), and document that releases are never created from the GitHub UI. - Validate wheel/sdist metadata with twine before anything becomes immutable, restoring the check the PyPI upload used to provide. - Fail fast on a missing release-tag input for mode=rebuild-assets. - Derive the package set from the workspace (root uv.sources in the index generator, packages/*/pyproject.toml in the release workflow, --all-packages in CI) so a sixth package cannot be silently dropped by a stale hardcoded list; match asset names literally (grep -F).
Defensively registers the five dash0-opentelemetry-* names on public PyPI with honest 0.0.0.devN stubs, closing the dependency-confusion hole that --extra-index-url consumption would otherwise leave open. The trusted publishers must be bound to this workflow and the protected pypi environment only, and removed after a successful run.
Member
Author
|
Merging this needs to wait for the PyPI org being approved |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #24. Adds the one-time
Reserve PyPI namesworkflow that defensively registers the fivedash0-opentelemetry-*distribution names on public PyPI.Why
The real packages are served from the Dash0 package index (#24), and consumers install with
--extra-index-url. pip resolves the highest version across all configured indexes, so unregistered names on public PyPI could be squatted with a higher version and win that resolution (dependency confusion). PyPI name ownership is exclusive from the first upload, so owning the names closes the hole for good.What the workflow does
workflow_dispatchonly; generates five stub projects inline (version0.0.0.devN— below every real version, dev-only so default resolution never selects it,Nincrementable because PyPI permanently forbids filename reuse) with a README pointing at the real index and repo, builds them with uv, and publishes via trusted publishing withskip-existing: true(partial-failure re-runs are safe).pypienvironment;permissions: {}at workflow level,id-token: writeonly on the publish job.