Skip to content

feat(TRI-1118): add --release-version + PEP 440/817 wheel scheme#503

Draft
mc-nv wants to merge 6 commits into
r26.06from
mchornyi/tri-1118-ci-artifactory-publish-wheels-to-the-artifactory
Draft

feat(TRI-1118): add --release-version + PEP 440/817 wheel scheme#503
mc-nv wants to merge 6 commits into
r26.06from
mchornyi/tri-1118-ci-artifactory-publish-wheels-to-the-artifactory

Conversation

@mc-nv

@mc-nv mc-nv commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What does the PR do?

Adds a --release-version CLI flag with a TRITON_RELEASE_VERSION env-var fallback to python/build_wheel.py. Precedence: CLI flag > env var > in-tree TRITON_VERSION file. CI can pin a release tag without editing the source-tree TRITON_VERSION.

The base version is classified by regex:

  • X.Y.Z (release-semantic) → PEP 440 normalized output (no local segment, no PEP 427 build tag, no variant label). PyPI-clean.
  • anything else (.devN, aN, rcN, .postN, …) → PEP 817 variant: keeps the PEP 427 build tag and appends a PEP 817 variant label nv<container>.cu<major><minor> to the wheel filename after the platform tag. Backward-compatible — pre-PEP 817 installers ignore variants and fall back to a non-variant wheel.

ANSI-colored info lines surface the chosen path in CI logs.

Checklist

  • PR title reflects the change and is of format <commit_type>: <Title>
  • Changes are described in the pull request.
  • Related issues are referenced.
  • Populated github labels field
  • Added test plan and verified test passes.
  • Verified that the PR passes existing CI.
  • Verified copyright is correct on all changed files.
  • Added succinct git squash message before merging.
  • All template sections are filled out.
  • Optional: screenshots for behavior/output changes with before/after.

Commit Type:

  • feat

Related PRs:

triton-inference-server/server#8845

Where should the reviewer start?

  • python/build_wheel.py — the _compose_variant_label helper plus the inline release/variant decision in __main__.

Test plan:

  • Helper unit-test (no Docker): exercise _compose_variant_label and the version classifier with the matrix in TRI-1118 (release vs dev/pre-release vs garbage).

  • Filename rename simulation: synthesize a fake *.whl, run the rename loop, confirm shape …-{platform}-nv<container>.cu<XYZ>.whl.

  • Container build with --release-version 2.70.0 → wheel filename is tritonserver-2.70.0-...whl (PyPI-clean).

  • Container build with --release-version 2.70.0.dev0 → wheel filename includes -nv<container>.cu<XYZ> variant label.

  • L0_* tests pass with no new failures.

  • CI Pipeline ID:

Caveats:

  • PEP 817 is currently Draft. The filename-level rename is forward-compatible but does not yet add variant.json metadata inside the wheel. When mainstream PEP 817 tooling lands, these wheels may need a follow-up to add the metadata.

Background

Part of TRI-1118 (CI artifactory publishing). The PEP 440 local-version segment (+nv26.05.cu132) is rejected by PyPI uploads, blocking artifactory publishing. This change moves the disambiguation into a separate filename slot via PEP 817.

Related Issues:

  • Resolves: TRI-1118

Adds a --release-version CLI flag with a TRITON_RELEASE_VERSION env-var
fallback to build_wheel.py. Precedence: CLI flag > env var >
in-tree TRITON_VERSION file. CI can now pin a release tag without
editing the source-tree TRITON_VERSION.

Classifies the base version by regex:
  - X.Y.Z (release-semantic) -> PEP 440 normalized output: no PEP 440
    local segment, no PEP 427 build tag, no variant label. PyPI-clean.
  - anything else (.devN, aN, rcN, etc.) -> PEP 817 variant: keeps the
    PEP 427 build tag (CI_PIPELINE_ID) and appends a PEP 817 variant
    label (nv<container>.cu<major><minor>) to the wheel filename after
    the platform tag. Backward-compatible -- pre-PEP 817 installers
    ignore variants and fall back to a non-variant wheel.

ANSI-colored info lines surface the chosen path in CI logs.

Refs TRI-1118.
mc-nv added 5 commits June 16, 2026 23:18
…EP 427 build tag

Pre-this-commit, dev wheels carried the CI pipeline id as a PEP 427
build tag between version and python-tag:
    tritonserver-2.70.0.dev0-12345-cp310-cp310-...-nv26.05.cu132.whl

PEP 427 build tags are rejected by public PyPI and duplicate the
identity that already belongs in the version string.

Switch to PEP 440 .dev<N> counter semantics. When the resolved base
version matches X.Y.Z.devN and CI_PIPELINE_ID is a positive integer,
replace the dev counter with the pipeline id:
    2.70.0.dev0 + CI_PIPELINE_ID=12345 -> 2.70.0.dev12345

Resulting filename:
    tritonserver-2.70.0.dev12345-cp310-cp310-...-nv26.05.cu132.whl

This is PyPI-uploadable, PEP 440-sortable across reruns
(dev12346 > dev12345), and removes the need for any PEP 427 build-tag
injection in `python -m build`.

The PEP 817 variant label path is untouched: dev versions still
classify as non-release and get the nv/cu label appended. Release
wheels (X.Y.Z) remain PyPI-clean. Local dev builds without
CI_PIPELINE_ID keep their in-tree .dev0.

Refs TRI-1118.
Two related fixes for the wheel-build / install pipeline:

1) auditwheel manylinux wheel was never installed.
   _repair_wheel_with_auditwheel() was passing --wheel-dir=<dest_dir>,
   which writes the manylinux wheel one directory above where the
   CMake `install(DIRECTORY ${WHEEL_OUT_DIR})` line reads from
   (<dest>/wheel/dist/). Result: the manylinux wheel was produced but
   never copied to /opt/tritonserver/python/ in the base image -- the
   publish job uploaded only the pre-repair linux_<arch> wheel.

   Switch --wheel-dir to dist_dir so auditwheel writes alongside the
   pre-repair wheel; on success, remove the original linux_<arch>
   wheel so dist_dir carries a single canonical manylinux artifact.

2) Dev-counter rewrite didn't match the in-tree TRITON_VERSION.
   The previous regex required canonical PEP 440 X.Y.Z.devN; in-tree
   `TRITON_VERSION` files use the legacy `X.Y.Zdev` shape (no period,
   no counter). Relax to ^(\d+\.\d+\.\d+)\.?dev\d*$ so both forms
   match and CI_PIPELINE_ID gets substituted as the dev counter.

Refs TRI-1118.
…o .so

Previous logic hardcoded `manylinux_2_28_<arch>` for any wheel auditwheel
reported as "no ELF". Result: pure-Python wheels (e.g. downstream builds
that disabled bindings) carried a false manylinux compatibility promise.

New routing inspects the wheel zip for native `.so` members up front:

  Has `.so`  -> auditwheel repair. auditwheel chooses the lowest
                `manylinux_<X>_<Y>_<arch>` policy that covers the .so's
                glibc symbol requirements, per PEP 513 / PEP 599 / PEP 600.
                Original `linux_<arch>` wheel is removed on success.
  No `.so`   -> `python -m wheel tags --python-tag py3 --abi-tag none
                --platform-tag any --remove` -> emit a canonical
                `py3-none-any` pure-Python wheel per PEP 425. The
                manylinux tag is OMITTED -- claiming manylinux on a wheel
                with no glibc-bound code would be a false promise.

PEP 656 musllinux is not produced here (build containers are glibc-based;
auditwheel-musl would be needed on musl distros). PEP 440 version
normalization still happens upstream of this function in the dev-counter
rewrite.

Add `_wheel_has_so()` helper using zipfile + basename inspection
(matches `*.so` and `*.so.<ver>`), the same classification heuristic
auditwheel and pip use.

Refs TRI-1118.
Symptom (job 342953964 / pipeline 55073480):
  tritonserver-2.70.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
  tritonserver-2.70.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl

Cause: CMake's add_custom_command for the wheel target runs twice
(build phase + install phase). The first run produces a manylinux wheel
in `wheel/dist/` and removes the linux_<arch> input. The second run's
`python -m build` re-creates the linux_<arch> wheel; dist/ now contains
both. _repair_wheel_with_auditwheel iterates over `os.listdir(dist_dir)`
and invokes auditwheel on each, including the already-manylinux leftover.
auditwheel applied to an already-tagged wheel emits a compressed PEP 425
tag set (e.g. manylinux_2_27_x86_64.manylinux_2_28_x86_64) -- valid but
noisy.

Two-belt fix:
  1. Clean wheel/dist/ before `python -m build` runs so leftovers from
     a previous CMake pass can't accumulate.
  2. In _repair_wheel_with_auditwheel, skip wheels whose filename
     already carries a manylinux or musllinux tag (defensive guard for
     any other source of stale wheels).

Together these make the script idempotent across repeated CMake
invocations and ensure each wheel carries exactly one platform tag.

Refs TRI-1118.
…sion

If auditwheel emits (or has emitted) a wheel whose PEP 425 platform-tag
component is a compressed set of manylinux entries -- e.g.
manylinux_2_27_x86_64.manylinux_2_28_x86_64 -- collapse to the highest
version (manylinux_2_28_x86_64). The lower-version entry is redundant
(higher version is the strictest applicable glibc baseline, aligned
with the build container's manylinux policy).

Implementation: scan dist/ after _repair_wheel_with_auditwheel completes;
parse each wheel filename; if the platform-tag component contains
multiple manylinux_X_Y_<arch> entries, sort by (X, Y) and rewrite the
tag via `python -m wheel tags --platform-tag <highest> --remove`.

Single-tag wheels and pure-Python (py3-none-any) wheels are no-ops.
Non-manylinux entries in a compressed set (rare) are preserved.

Refs TRI-1118.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant