docs(install): add nightly install + docker tag guidance, and auto-bump version on release tag (#30308)
This commit is contained in:
@@ -0,0 +1,88 @@
|
|||||||
|
name: Bot Bump Docs Version
|
||||||
|
#
|
||||||
|
# Bumps the "install from source" release-branch version pinned in the docs
|
||||||
|
# (the `git clone -b v<version> ...sglang.git` line in
|
||||||
|
# docs_new/docs/get-started/install.mdx "Method 2: From source" and
|
||||||
|
# docs_new/docs/hardware-platforms/amd_gpu.mdx) whenever a release tag is
|
||||||
|
# pushed, and opens a PR with the change.
|
||||||
|
#
|
||||||
|
# Triggers mirror release-docker.yml: a pushed `v*` tag (the release), or a
|
||||||
|
# manual run with an explicit version.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v[0-9]+.*"
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Version to set (without v prefix, e.g., 0.5.13)"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
resolve-version:
|
||||||
|
if: github.repository == 'sgl-project/sglang'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- name: Get version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
VERSION="${{ github.event.inputs.version }}"
|
||||||
|
else
|
||||||
|
VERSION="${GITHUB_REF_NAME#v}"
|
||||||
|
fi
|
||||||
|
if [ -z "$VERSION" ] || ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
|
||||||
|
echo "::error::Invalid version: $VERSION (expected: X.Y.Z)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
bump-docs-version:
|
||||||
|
needs: resolve-version
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Branch off main so the PR targets the docs on the default branch,
|
||||||
|
# not the (detached) tag commit that triggered this run.
|
||||||
|
ref: main
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
pip install tomli
|
||||||
|
|
||||||
|
- name: Configure Git and branch
|
||||||
|
run: |
|
||||||
|
git config user.name "sglang-bot"
|
||||||
|
git config user.email "sglang-bot@users.noreply.github.com"
|
||||||
|
# github.run_id is unique per run repo-wide; run_attempt disambiguates re-runs.
|
||||||
|
BRANCH_NAME="bot/bump-docs-version-${{ needs.resolve-version.outputs.version }}-${{ github.run_id }}-${{ github.run_attempt }}"
|
||||||
|
git checkout -b "$BRANCH_NAME"
|
||||||
|
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Run docs version bump script
|
||||||
|
run: |
|
||||||
|
python scripts/release/bump_docs_install_version.py "${{ needs.resolve-version.outputs.version }}"
|
||||||
|
|
||||||
|
- name: Commit and create PR
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GH_PAT_FOR_PULL_REQUEST }}
|
||||||
|
run: |
|
||||||
|
if git diff --quiet; then
|
||||||
|
echo "Docs already pin this version; no PR needed."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
bash scripts/release/commit_and_pr.sh "docs install" "${{ needs.resolve-version.outputs.version }}" "$BRANCH_NAME"
|
||||||
@@ -35,6 +35,23 @@ uv pip install --force-reinstall sglang-kernel --index-url https://docs.sglang.a
|
|||||||
uv pip install --force-reinstall sgl-deep-gemm --index-url https://docs.sglang.ai/whl/cu129/ --no-deps
|
uv pip install --force-reinstall sgl-deep-gemm --index-url https://docs.sglang.ai/whl/cu129/ --no-deps
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Nightly builds
|
||||||
|
|
||||||
|
To pick up the latest features and fixes before the next stable release, install a nightly build. Nightly wheels are built from the latest `main` and published to the SGLang wheel index. Add that index with `--extra-index-url`, and combine `--prerelease=allow` with `--index-strategy unsafe-best-match` so uv considers the nightly (pre-release) version alongside PyPI:
|
||||||
|
|
||||||
|
```bash Command
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install uv
|
||||||
|
uv pip install --prerelease=allow --index-strategy unsafe-best-match --extra-index-url https://docs.sglang.ai/whl/cu130/ sglang
|
||||||
|
```
|
||||||
|
|
||||||
|
To install a nightly build under Cuda 12, swap the index to `cu129`:
|
||||||
|
```bash Command
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install uv
|
||||||
|
uv pip install --prerelease=allow --index-strategy unsafe-best-match --extra-index-url https://docs.sglang.ai/whl/cu129/ sglang
|
||||||
|
```
|
||||||
|
|
||||||
### Quick fixes to common problems
|
### Quick fixes to common problems
|
||||||
- If you encounter `OSError: CUDA_HOME environment variable is not set`. Please set it to your CUDA install root with either of the following solutions:
|
- If you encounter `OSError: CUDA_HOME environment variable is not set`. Please set it to your CUDA install root with either of the following solutions:
|
||||||
1. Use `export CUDA_HOME=/usr/local/cuda-<your-cuda-version>` to set the `CUDA_HOME` environment variable.
|
1. Use `export CUDA_HOME=/usr/local/cuda-<your-cuda-version>` to set the `CUDA_HOME` environment variable.
|
||||||
@@ -61,6 +78,10 @@ pip install -e "python"
|
|||||||
The docker images are available on Docker Hub at [lmsysorg/sglang](https://hub.docker.com/r/lmsysorg/sglang/tags), built from [Dockerfile](https://github.com/sgl-project/sglang/tree/main/docker).
|
The docker images are available on Docker Hub at [lmsysorg/sglang](https://hub.docker.com/r/lmsysorg/sglang/tags), built from [Dockerfile](https://github.com/sgl-project/sglang/tree/main/docker).
|
||||||
Replace `<secret>` below with your huggingface hub [token](https://huggingface.co/docs/hub/en/security-tokens).
|
Replace `<secret>` below with your huggingface hub [token](https://huggingface.co/docs/hub/en/security-tokens).
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
`latest` and `dev` are **mutable** tags: `latest` always points at the newest stable release, while `dev` is rebuilt daily from the latest `main` and includes build/development tools. Because they are overwritten over time, pin an immutable version tag for reproducible deployments — e.g. `lmsysorg/sglang:v0.5.12`. Browse all released versions on [Docker Hub](https://hub.docker.com/r/lmsysorg/sglang/tags).
|
||||||
|
</Note>
|
||||||
|
|
||||||
```bash Command
|
```bash Command
|
||||||
docker run --gpus all \
|
docker run --gpus all \
|
||||||
--shm-size 32g \
|
--shm-size 32g \
|
||||||
|
|||||||
@@ -24,6 +24,18 @@ python scripts/release/bump_sglang_version.py 0.5.3rc0
|
|||||||
- `python/pyproject_npu.toml`
|
- `python/pyproject_npu.toml`
|
||||||
- `python/sglang/version.py`
|
- `python/sglang/version.py`
|
||||||
|
|
||||||
|
### `bump_docs_install_version.py`
|
||||||
|
Bumps the release version pinned in the Mintlify install docs — both the `git clone -b v<version> ...sglang.git` "install from source" line and the version-pinned `lmsysorg/sglang:v<version>` Docker example. Mutable tags (`latest`, `dev`) are intentionally left untouched. Driven automatically on release-tag push by [`.github/workflows/bot-bump-docs-version.yml`](../../.github/workflows/bot-bump-docs-version.yml), which opens a PR with the change.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
python scripts/release/bump_docs_install_version.py 0.5.13
|
||||||
|
```
|
||||||
|
|
||||||
|
**Files updated:**
|
||||||
|
- `docs_new/docs/get-started/install.mdx` (Method 2: From source; Method 3: pinned Docker image)
|
||||||
|
- `docs_new/docs/hardware-platforms/amd_gpu.mdx` (Install from Source)
|
||||||
|
|
||||||
### `bump_kernel_version.py`
|
### `bump_kernel_version.py`
|
||||||
Updates the `sglang-kernel` release version across all relevant files following the pattern from [PR #10732](https://github.com/sgl-project/sglang/pull/10732).
|
Updates the `sglang-kernel` release version across all relevant files following the pattern from [PR #10732](https://github.com/sgl-project/sglang/pull/10732).
|
||||||
|
|
||||||
|
|||||||
Executable
+149
@@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from utils import (
|
||||||
|
compare_versions,
|
||||||
|
get_repo_root,
|
||||||
|
normalize_version,
|
||||||
|
validate_version,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Docs pages that pin a release branch in their "install from source" snippet,
|
||||||
|
# e.g. `git clone -b v0.5.12 https://github.com/sgl-project/sglang.git`.
|
||||||
|
FILES_TO_UPDATE = [
|
||||||
|
Path("docs_new/docs/get-started/install.mdx"),
|
||||||
|
Path("docs_new/docs/hardware-platforms/amd_gpu.mdx"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Matches `git clone -b v<version> https://github.com/sgl-project/sglang.git`,
|
||||||
|
# capturing the version (without the leading `v`) in group 2.
|
||||||
|
CLONE_RE = re.compile(
|
||||||
|
r"(git clone -b )v([0-9][0-9A-Za-z.\-]*)"
|
||||||
|
r"( https://github\.com/sgl-project/sglang\.git)"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Matches a version-pinned docker image such as `lmsysorg/sglang:v0.5.12`
|
||||||
|
# (leaving any suffix like `-cu130`/`-runtime` untouched), capturing the
|
||||||
|
# version in group 2. Mutable tags (`latest`, `dev`, ...) are not matched.
|
||||||
|
DOCKER_RE = re.compile(r"(lmsysorg/sglang:)v(\d+\.\d+\.\d+(?:rc\d+|\.post\d+)?)\b")
|
||||||
|
|
||||||
|
# All version references the bump keeps in sync, each with the version in group 2.
|
||||||
|
VERSION_PATTERNS = [CLONE_RE, DOCKER_RE]
|
||||||
|
|
||||||
|
|
||||||
|
def read_current_version(file_path: Path) -> str:
|
||||||
|
"""Read the pinned source-install version from a docs page."""
|
||||||
|
match = CLONE_RE.search(file_path.read_text())
|
||||||
|
if not match:
|
||||||
|
raise ValueError(
|
||||||
|
f"Could not find a 'git clone -b v<version> ...sglang.git' line in {file_path}"
|
||||||
|
)
|
||||||
|
return match.group(2)
|
||||||
|
|
||||||
|
|
||||||
|
def stale_versions(file_path: Path, new_version: str) -> list:
|
||||||
|
"""Return any pinned versions in the file that differ from new_version."""
|
||||||
|
content = file_path.read_text()
|
||||||
|
return [
|
||||||
|
m.group(2)
|
||||||
|
for pattern in VERSION_PATTERNS
|
||||||
|
for m in pattern.finditer(content)
|
||||||
|
if m.group(2) != new_version
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def replace_version(file_path: Path, new_version: str) -> bool:
|
||||||
|
if not file_path.exists():
|
||||||
|
print(f"Warning: {file_path} does not exist, skipping")
|
||||||
|
return False
|
||||||
|
|
||||||
|
content = file_path.read_text()
|
||||||
|
new_content = CLONE_RE.sub(rf"\g<1>v{new_version}\g<3>", content)
|
||||||
|
new_content = DOCKER_RE.sub(rf"\g<1>v{new_version}", new_content)
|
||||||
|
|
||||||
|
if content == new_content:
|
||||||
|
print(f"No changes needed in {file_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
file_path.write_text(new_content)
|
||||||
|
print(f"✓ Updated {file_path}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Bump the 'install from source' release-branch version in the docs"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"new_version",
|
||||||
|
help="New version (e.g., 0.5.13, 0.5.13rc0, or 0.5.13.post1)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
new_version = normalize_version(args.new_version)
|
||||||
|
|
||||||
|
if not validate_version(new_version):
|
||||||
|
print(f"Error: Invalid version format: {new_version}")
|
||||||
|
print("Expected format: X.Y.Z, X.Y.ZrcN, or X.Y.Z.postN")
|
||||||
|
print("Examples: 0.5.13, 0.5.13rc0, 0.5.13.post1")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
repo_root = get_repo_root()
|
||||||
|
|
||||||
|
# Determine the current version from the primary install page for logging.
|
||||||
|
primary = repo_root / FILES_TO_UPDATE[0]
|
||||||
|
old_version = read_current_version(primary)
|
||||||
|
print(f"Current docs install version: {old_version}")
|
||||||
|
print(f"New docs install version: {new_version}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
comparison = compare_versions(new_version, old_version)
|
||||||
|
if comparison == 0:
|
||||||
|
print("Docs are already at this version; nothing to do.")
|
||||||
|
return
|
||||||
|
elif comparison < 0:
|
||||||
|
print(
|
||||||
|
f"Warning: new version ({new_version}) is older than the docs version "
|
||||||
|
f"({old_version}); proceeding anyway."
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_count = 0
|
||||||
|
for file_rel in FILES_TO_UPDATE:
|
||||||
|
file_abs = repo_root / file_rel
|
||||||
|
if replace_version(file_abs, new_version):
|
||||||
|
updated_count += 1
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(f"Successfully updated {updated_count} file(s)")
|
||||||
|
print(f"Docs install version bumped from {old_version} to {new_version}")
|
||||||
|
|
||||||
|
print("\nValidating version updates...")
|
||||||
|
failed_files = []
|
||||||
|
for file_rel in FILES_TO_UPDATE:
|
||||||
|
file_abs = repo_root / file_rel
|
||||||
|
if not file_abs.exists():
|
||||||
|
print(f"Warning: File {file_rel} does not exist, skipping validation.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
stale = stale_versions(file_abs, new_version)
|
||||||
|
if stale:
|
||||||
|
failed_files.append(file_rel)
|
||||||
|
print(f"✗ {file_rel} still pins v{', v'.join(sorted(set(stale)))}")
|
||||||
|
else:
|
||||||
|
print(f"✓ {file_rel} validated")
|
||||||
|
|
||||||
|
if failed_files:
|
||||||
|
print(f"\nError: {len(failed_files)} file(s) were not updated correctly:")
|
||||||
|
for file_rel in failed_files:
|
||||||
|
print(f" - {file_rel}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("\nAll files validated successfully!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user