Skip to content

Add TestPyPI publish workflow (Phase 5a dry-run) - #1212

Closed
Shi-Dong wants to merge 4 commits into
shi/phase4-extras-require-inventoryfrom
shi/phase5a-testpypi-dry-run
Closed

Add TestPyPI publish workflow (Phase 5a dry-run)#1212
Shi-Dong wants to merge 4 commits into
shi/phase4-extras-require-inventoryfrom
shi/phase5a-testpypi-dry-run

Conversation

@Shi-Dong

Copy link
Copy Markdown
Contributor

Summary

  • Add .github/workflows/publish-testpypi.yml: manual-only workflow that builds a wheel from third_party/sglang/python or third_party/Megatron-LM, rewrites the pyproject.toml to use a Radixark-namespaced placeholder name + a PEP 440 dev-release version, and uploads to TestPyPI.
  • Includes a dry_run input so the build step can be validated before TestPyPI credentials are configured.
  • Includes a post-upload smoke install (pip install --index-url https://pypi.org/simple/ --extra-index-url https://test.pypi.org/simple/ radixark-sglang-test==<dev-version>) so a green run is end-to-end evidence the publish pipeline works.

Why

Phase 5a of the pip install miles roadmap: validate the wheel-build + index-publish pipeline against TestPyPI before committing to a production index host (private index vs. PyPI proper). TestPyPI is the right tool for this because:

  • It's an actual external index, not a mock — twine upload, pip install, the whole flow gets exercised.
  • It's ephemeral (TestPyPI can purge packages at any time) and doesn't resolve regular PyPI deps — so it's a sandbox, not a stable distribution channel.

Once this PR is green, the same workflow can be retargeted to whatever production index we pick (private CodeArtifact / GitHub Packages / real PyPI) by changing the --repository flag and the secret name. Phase 5b is "pick the real index"; this PR is "prove the publish workflow is sound."

Setup required to run with dry_run=false

Once you're ready to actually upload to TestPyPI:

  1. Register an account at https://test.pypi.org/ (separate from PyPI).
  2. Create an API token at https://test.pypi.org/manage/account/token/ with "Entire account" scope. (You can narrow the scope to specific packages after the first successful upload.)
  3. Add the token as a GitHub Actions secret named TEST_PYPI_API_TOKEN at https://github.com/radixark/miles/settings/secrets/actions.

These instructions are also in the workflow file's header comment.

Test plan

  • Trigger via gh workflow run publish-testpypi.yml --ref shi/phase5a-testpypi-dry-run -f package=sglang -f dry_run=true — should build wheel + sdist successfully without needing a token. (I'll fire this immediately after the PR opens.)
  • Once the TEST_PYPI_API_TOKEN secret is configured, re-trigger with dry_run=false. Wheel should upload to TestPyPI and the smoke install should pull it back into a fresh venv.
  • Repeat with package=megatron-lm to validate Megatron-LM follows the same path.

What this PR explicitly does NOT do

  • Doesn't commit to a long-term index host. TestPyPI is a sandbox.
  • Doesn't change the Docker image's install path (sglang + Megatron-LM still come from COPY-from-submodule).
  • Doesn't populate miles' extras_require slots (Phase 6 — gated on picking the real index).

Stacked on

radixark/miles PR #1196 (Phase 4: empty extras_require slots).

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@Shi-Dong
Shi-Dong marked this pull request as ready for review May 28, 2026 06:50
@Shi-Dong
Shi-Dong requested a review from yushengsu-thu as a code owner May 28, 2026 06:50
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from f9c1820 to a458463 Compare May 30, 2026 08:17
@Shi-Dong
Shi-Dong force-pushed the shi/phase5a-testpypi-dry-run branch from 918d208 to e0d7275 Compare May 30, 2026 08:17
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from a458463 to ef8c861 Compare June 1, 2026 16:12
@Shi-Dong
Shi-Dong force-pushed the shi/phase5a-testpypi-dry-run branch 2 times, most recently from 497d427 to a1a7f8c Compare June 2, 2026 04:40
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from ef8c861 to 51fee7e Compare June 2, 2026 04:40
@Shi-Dong
Shi-Dong force-pushed the shi/phase5a-testpypi-dry-run branch from a1a7f8c to efa3b43 Compare June 2, 2026 09:07
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from 51fee7e to 518d340 Compare June 2, 2026 09:07
@Shi-Dong
Shi-Dong force-pushed the shi/phase5a-testpypi-dry-run branch from efa3b43 to b61e5ab Compare June 3, 2026 15:02
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from 518d340 to 6ee0b3f Compare June 3, 2026 15:02
Shi-Dong added 4 commits June 4, 2026 06:09
… 5a)

Phase 5a of the `pip install miles` roadmap: validate the wheel-build
plus index-publish pipeline against TestPyPI before committing to a
production index host (private vs. PyPI proper).

The new workflow `.github/workflows/publish-testpypi.yml` is manual-only
(workflow_dispatch). On invocation it:

  1. Checks out miles + submodules.
  2. Rewrites the submodule's pyproject.toml to use a Radixark-namespaced
     placeholder name (radixark-sglang-test / radixark-megatron-test) and
     a PEP 440 dev-release version (0.0.0.devYYYYMMDDHHMMSS).
  3. Builds a wheel + sdist via `python -m build`.
  4. (Unless dry_run=true) Uploads to https://test.pypi.org/ using a
     TEST_PYPI_API_TOKEN secret, then `pip install`s it into a fresh
     venv as a smoke check.

The dry_run input lets you validate the build step before you have a
TestPyPI account / token configured. Once the secret is set, leave it
unchecked and the workflow does the full upload + smoke install.

What this PR explicitly does NOT do:

  - It does NOT commit to a long-term index host. TestPyPI is ephemeral
    (packages can be purged at any time, dependency resolution doesn't
    happen there) — this is purely a CI dry-run.
  - It does NOT touch the existing Docker / training paths. The image
    still installs sglang + Megatron-LM via COPY-from-submodule.
  - It does NOT populate miles' extras_require slots with the new
    wheel names. That's Phase 6, after we pick the real index.
workflow_dispatch requires the workflow file on the default branch, so add a temporary push trigger on the feature branch that auto-fires a dry-run when the workflow file changes. Wire inputs through env vars so the same workflow body works on both push (defaults: package=sglang, dry_run=true) and workflow_dispatch.
Previous smoke install used --extra-index-url https://test.pypi.org/simple/ alongside --index-url https://pypi.org/simple/, so pip resolved transitive deps from BOTH indexes. TestPyPI is a public sandbox with name-squat packages (e.g. an unrelated FASTAPI-1.0 squatting on fastapi case-insensitively), and pip happily downloaded the squatter, which then failed to build its sdist. The wheel upload itself succeeded; only the dep-resolution smoke tripped on TestPyPI hazards.

Switch to --index-url https://test.pypi.org/simple/ --no-deps. Our smoke check only needs to prove the wheel we just published is fetchable and installable — transitive dep resolution from a sandbox is neither safe nor necessary.
twine upload reports success the moment the upload finishes, but TestPyPI is eventually consistent. The simple-index can take 30-120s to surface a new release, during which pip install --no-deps fails with No matching distribution found. Add a polling step that waits for the new version to appear (up to 5 min) before attempting the install.
@Shi-Dong
Shi-Dong force-pushed the shi/phase4-extras-require-inventory branch from 6ee0b3f to db6b4d4 Compare June 4, 2026 13:10
@Shi-Dong
Shi-Dong force-pushed the shi/phase5a-testpypi-dry-run branch from b61e5ab to 0317549 Compare June 4, 2026 13:10
@Shi-Dong

Copy link
Copy Markdown
Contributor Author

Closing as obsolete. This PR is superseded by a thin packaging slice cut fresh off current `main`:

  • radixark/miles#PRA — re-add `third_party/sglang` + `third_party/Megatron-LM` submodules
  • radixark/miles#PRB — `setup.py` bundling + `publish-pypi.yml` + `miles-rl` 0.0.3

Why this one is no longer needed: see the per-PR note below. The branch is left in place; nothing is lost.

@Shi-Dong Shi-Dong closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant