name: Release SGLang Kernels on: push: branches: - main paths: - sgl-kernel/python/sgl_kernel/version.py workflow_dispatch: inputs: target: type: choice description: 'Build target' required: false default: 'all' options: - 'all' - 'cu129' - 'cu130' - 'rocm700' - 'rocm720' - 'musa43' tag_name: description: "Version number, must be in the form of vX.Y.Z (e.g. v0.4.0)" type: string required: false pr_number: description: "PR number to build from (e.g. 12345)" type: string required: false concurrency: group: release-sglang-kernels-${{ github.ref }} cancel-in-progress: true jobs: # cu130 is the PyPI-released variant; cu129 wheels are published only to the # sgl-project/whl index (consumed via `pip install ...+cu129` for the legacy # cuda 12.9 path), not to PyPI. build-cu129-matrix: if: | github.repository == 'sgl-project/sglang' && (github.event_name == 'push' || github.event.inputs.target == 'all' || github.event.inputs.target == 'cu129') strategy: matrix: python-version: ["3.10"] cuda-version: ["12.9"] arch: [x86_64, aarch64] include: - arch: x86_64 runner: x64-kernel-build-node - arch: aarch64 runner: arm-kernel-build-node runs-on: ${{ matrix.runner }} steps: # Self-hosted build nodes retain the workspace across jobs. Prior builds # leave root-owned artifacts under sgl-kernel/build/ that actions/checkout # cannot remove, causing EACCES on rmdir. Wipe them via a throwaway root # container before checkout recreates the workspace. - name: Clean workspace (remove root-owned files from prior runs) run: | docker run --rm -v "${{ github.workspace }}:/workspace" alpine:3 \ sh -c 'rm -rf /workspace/..?* /workspace/.[!.]* /workspace/*' || true - uses: actions/checkout@v4 with: submodules: "recursive" ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build wheels run: | cd sgl-kernel chmod +x ./build.sh ./build.sh "${{ matrix.python-version }}" "${{ matrix.cuda-version }}" ${{ matrix.arch == 'aarch64' && 'aarch64' || '' }} env: BUILD_JOBS: 64 NVCC_THREADS: 8 - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: wheel-python${{ matrix.python-version }}-cuda${{ matrix.cuda-version }}${{ matrix.arch == 'aarch64' && '-aarch64' || '' }} path: sgl-kernel/dist/* release-cu129: needs: build-cu129-matrix runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Download artifacts uses: actions/download-artifact@v4 with: path: sgl-kernel/dist/ merge-multiple: true pattern: wheel-* - name: Set tag name id: set_tag_name run: | if [ -z "${{ inputs.tag_name }}" ]; then TAG_NAME="v$(cat sgl-kernel/python/sgl_kernel/version.py | cut -d'"' -f2)" echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT else echo "tag_name=${{ inputs.tag_name }}" >> $GITHUB_OUTPUT fi - name: Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.set_tag_name.outputs.tag_name }} repository: sgl-project/whl token: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} files: | sgl-kernel/dist/* - name: Clone wheel index run: git clone https://oauth2:${WHL_TOKEN}@github.com/sgl-project/whl.git sgl-whl env: WHL_TOKEN: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} - name: Update wheel index run: python3 scripts/update_kernel_whl_index.py --cuda 129 - name: Push wheel index run: | cd sgl-whl git config --local user.name "sglang-bot" git config --local user.email "sglangbot@gmail.com" git add -A git commit -m "update whl index" git push build-cu130-matrix: if: | github.repository == 'sgl-project/sglang' && (github.event_name == 'push' || github.event.inputs.target == 'all' || github.event.inputs.target == 'cu130') strategy: matrix: python-version: ["3.10"] cuda-version: ["13.0"] arch: [x86_64, aarch64] include: - arch: x86_64 runner: x64-kernel-build-node - arch: aarch64 runner: arm-kernel-build-node runs-on: ${{ matrix.runner }} steps: # Self-hosted build nodes retain the workspace across jobs. Prior builds # leave root-owned artifacts under sgl-kernel/build/ that actions/checkout # cannot remove, causing EACCES on rmdir. Wipe them via a throwaway root # container before checkout recreates the workspace. - name: Clean workspace (remove root-owned files from prior runs) run: | docker run --rm -v "${{ github.workspace }}:/workspace" alpine:3 \ sh -c 'rm -rf /workspace/..?* /workspace/.[!.]* /workspace/*' || true - uses: actions/checkout@v4 with: submodules: "recursive" ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build wheels run: | cd sgl-kernel chmod +x ./build.sh ./build.sh "${{ matrix.python-version }}" "${{ matrix.cuda-version }}" ${{ matrix.arch == 'aarch64' && 'aarch64' || '' }} env: BUILD_JOBS: 64 NVCC_THREADS: 8 - name: Strip +cu130 local version for PyPI upload working-directory: sgl-kernel run: | set -eux pip install wheel mkdir -p dist-pypi for w in dist/*.whl; do tmp=$(mktemp -d) python3 -m wheel unpack "$w" --dest "$tmp" unpacked=$(find "$tmp" -mindepth 1 -maxdepth 1 -type d | head -1) info=$(find "$unpacked" -maxdepth 1 -type d -name "*.dist-info" | head -1) meta="$info/METADATA" orig=$(grep '^Version:' "$meta" | head -1 | sed 's/^Version:[[:space:]]*//') new=$(echo "$orig" | sed 's/+cu[0-9]\+$//') if [ "$orig" != "$new" ]; then sed -i "s/^Version:.*/Version: ${new}/" "$meta" old_base=$(basename "$info") new_base="${old_base/${orig}/${new}}" mv "$info" "$(dirname "$info")/${new_base}" fi python3 -m wheel pack "$unpacked" --dest-dir dist-pypi rm -rf "$tmp" done ls -lh dist-pypi/ - name: Upload to PyPI working-directory: sgl-kernel run: | pip install twine python3 -m twine upload --skip-existing dist-pypi/* -u __token__ -p ${{ secrets.PYPI_TOKEN_SGLANG_KERNEL }} - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: wheel-python${{ matrix.python-version }}-cuda${{ matrix.cuda-version }}${{ matrix.arch == 'aarch64' && '-aarch64' || '' }} path: sgl-kernel/dist/* release-cu130: needs: build-cu130-matrix runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Download artifacts uses: actions/download-artifact@v4 with: path: sgl-kernel/dist/ merge-multiple: true pattern: wheel-* - name: Set tag name id: set_tag_name run: | if [ -z "${{ inputs.tag_name }}" ]; then TAG_NAME="v$(cat sgl-kernel/python/sgl_kernel/version.py | cut -d'"' -f2)" echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT else echo "tag_name=${{ inputs.tag_name }}" >> $GITHUB_OUTPUT fi - name: Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.set_tag_name.outputs.tag_name }} repository: sgl-project/whl token: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} files: | sgl-kernel/dist/* - name: Clone wheel index run: git clone https://oauth2:${WHL_TOKEN}@github.com/sgl-project/whl.git sgl-whl env: WHL_TOKEN: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} - name: Update wheel index run: python3 scripts/update_kernel_whl_index.py --cuda 130 - name: Push wheel index run: | cd sgl-whl git config --local user.name "sglang-bot" git config --local user.email "sglangbot@gmail.com" git add -A git commit -m "update whl index" git push build-rocm-matrix: if: | github.repository == 'sgl-project/sglang' && (github.event_name == 'push' || github.event.inputs.target == 'all' || github.event.inputs.target == 'rocm700' || github.event.inputs.target == 'rocm720') runs-on: amd-docker-scale strategy: matrix: python-version: ["3.10"] rocm-version: ["700", "720"] steps: # Self-hosted build nodes retain the workspace across jobs. Prior builds # leave root-owned artifacts under sgl-kernel/build/ that actions/checkout # cannot remove, causing EACCES on rmdir. Wipe them via a throwaway root # container before checkout recreates the workspace. - name: Clean workspace (remove root-owned files from prior runs) run: | docker run --rm -v "${{ github.workspace }}:/workspace" alpine:3 \ sh -c 'rm -rf /workspace/..?* /workspace/.[!.]* /workspace/*' || true - uses: actions/checkout@v4 with: submodules: "recursive" ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Build wheels run: | cp 3rdparty/amd/wheel/sgl-kernel/* sgl-kernel/ cd sgl-kernel chmod +x ./build_rocm.sh ./build_rocm.sh "${{ matrix.rocm-version }}" - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: wheel-python${{ matrix.python-version }}-rocm${{ matrix.rocm-version }} path: sgl-kernel/dist/* release-rocm700: needs: build-rocm-matrix runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Download artifacts uses: actions/download-artifact@v4 with: path: sgl-kernel/dist/ merge-multiple: true pattern: wheel-*-rocm700 - name: Set tag name id: set_tag_name run: | if [ -z "${{ inputs.tag_name }}" ]; then TAG_NAME="v$(cat sgl-kernel/python/sgl_kernel/version.py | cut -d'"' -f2)" echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT else echo "tag_name=${{ inputs.tag_name }}" >> $GITHUB_OUTPUT fi - name: Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.set_tag_name.outputs.tag_name }} repository: sgl-project/whl token: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} files: | sgl-kernel/dist/* - name: Clone wheel index run: git clone https://oauth2:${WHL_TOKEN}@github.com/sgl-project/whl.git sgl-whl env: WHL_TOKEN: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} - name: Update wheel index run: python3 scripts/update_kernel_whl_index.py --rocm 700 - name: Push wheel index run: | cd sgl-whl git config --local user.name "sglang-bot" git config --local user.email "sglangbot@gmail.com" git add -A git commit -m "update whl index" git push release-rocm720: needs: build-rocm-matrix runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }} - name: Download artifacts uses: actions/download-artifact@v4 with: path: sgl-kernel/dist/ merge-multiple: true pattern: wheel-*-rocm720 - name: Set tag name id: set_tag_name run: | if [ -z "${{ inputs.tag_name }}" ]; then TAG_NAME="v$(cat sgl-kernel/python/sgl_kernel/version.py | cut -d'"' -f2)" echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT else echo "tag_name=${{ inputs.tag_name }}" >> $GITHUB_OUTPUT fi - name: Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.set_tag_name.outputs.tag_name }} repository: sgl-project/whl token: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} files: | sgl-kernel/dist/* - name: Clone wheel index run: git clone https://oauth2:${WHL_TOKEN}@github.com/sgl-project/whl.git sgl-whl env: WHL_TOKEN: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} - name: Update wheel index run: python3 scripts/update_kernel_whl_index.py --rocm 720 - name: Push wheel index run: | cd sgl-whl git config --local user.name "sglang-bot" git config --local user.email "sglangbot@gmail.com" git add -A git commit -m "update whl index" git push build-musa43: if: | github.repository == 'sgl-project/sglang' && (github.event_name == 'push' || github.event.inputs.target == 'all' || github.event.inputs.target == 'musa43') runs-on: kernel-build-node-musa strategy: matrix: python-version: ["3.10"] musa-version: ["43"] steps: # Self-hosted build nodes retain the workspace across jobs. Prior builds # leave root-owned artifacts under sgl-kernel/build/ that actions/checkout # cannot remove, causing EACCES on rmdir. Wipe them via a throwaway root # container before checkout recreates the workspace. - name: Clean workspace (remove root-owned files from prior runs) run: | docker run --rm -v "${{ github.workspace }}:/workspace" alpine:3 \ sh -c 'rm -rf /workspace/..?* /workspace/.[!.]* /workspace/*' || true - uses: actions/checkout@v4 with: submodules: "recursive" - name: Clean stale torchada extension locks run: | if ps -eo comm=,args= | grep -E '(^|[[:space:]])(mcc|ninja)([[:space:]]|$)|torchada_cpp_ops' | grep -v grep; then echo "::error::Active torchada extension build detected; refusing to remove lock files" exit 1 fi find "${HOME}/.cache/torch_extensions" \ -path '*/torchada_cpp_ops/lock' \ -type f \ -print \ -delete 2>/dev/null || true - name: Build wheels run: | cd sgl-kernel mv pyproject_musa.toml pyproject.toml python setup_musa.py sdist bdist_wheel - name: Rename MUSA wheels run: | bash scripts/ci/musa/rename_wheels_musa.sh ${{ matrix.musa-version }} sgl-kernel/dist - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: wheel-python${{ matrix.python-version }}-musa${{ matrix.musa-version }} path: sgl-kernel/dist/* release-musa43: needs: build-musa43 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Download artifacts uses: actions/download-artifact@v4 with: path: sgl-kernel/dist/ merge-multiple: true pattern: wheel-* - name: Set tag name id: set_tag_name run: | if [ -z "${{ inputs.tag_name }}" ]; then TAG_NAME="v$(cat sgl-kernel/python/sgl_kernel/version.py | cut -d'"' -f2)" echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT else echo "tag_name=${{ inputs.tag_name }}" >> $GITHUB_OUTPUT fi - name: Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.set_tag_name.outputs.tag_name }} repository: sgl-project/whl token: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} files: | sgl-kernel/dist/* - name: Clone wheel index run: git clone https://oauth2:${WHL_TOKEN}@github.com/sgl-project/whl.git sgl-whl env: WHL_TOKEN: ${{ secrets.GH_PAT_FOR_WHL_RELEASE }} - name: Update wheel index run: python3 scripts/update_kernel_whl_index.py --musa 43 - name: Push wheel index run: | cd sgl-whl git config --local user.name "sglang-bot" git config --local user.email "sglangbot@gmail.com" git add -A git commit -m "update whl index" git push