chore: import upstream snapshot with attribution
Book-CI / test (macos-latest) (push) Has been cancelled
Book-CI / test (ubuntu-latest) (push) Has been cancelled
Book-CI / test (windows-latest) (push) Has been cancelled
Release Fake Tag / publish (push) Has been cancelled
Deploy / deploy (macos-latest) (push) Has been cancelled
Deploy / deploy (ubuntu-latest) (push) Has been cancelled
Deploy / deploy (windows-latest) (push) Has been cancelled
Release to PyPI / Build & publish sglang-kt (push) Has been cancelled
Release to PyPI / Build kt-kernel (Python 3.11) (push) Has been cancelled
Release to PyPI / Build kt-kernel (Python 3.12) (push) Has been cancelled
Release to PyPI / Publish kt-kernel to PyPI (push) Has been cancelled
Book-CI / test (macos-latest) (push) Has been cancelled
Book-CI / test (ubuntu-latest) (push) Has been cancelled
Book-CI / test (windows-latest) (push) Has been cancelled
Release Fake Tag / publish (push) Has been cancelled
Deploy / deploy (macos-latest) (push) Has been cancelled
Deploy / deploy (ubuntu-latest) (push) Has been cancelled
Deploy / deploy (windows-latest) (push) Has been cancelled
Release to PyPI / Build & publish sglang-kt (push) Has been cancelled
Release to PyPI / Build kt-kernel (Python 3.11) (push) Has been cancelled
Release to PyPI / Build kt-kernel (Python 3.12) (push) Has been cancelled
Release to PyPI / Publish kt-kernel to PyPI (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
name: Book-CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# - server_support
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# - server_support
|
||||
jobs:
|
||||
test:
|
||||
name: test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Rust
|
||||
run: |
|
||||
rustup set profile minimal
|
||||
rustup toolchain install stable
|
||||
rustup default stable
|
||||
- name: Setup mdBook
|
||||
uses: peaceiris/actions-mdbook@v2
|
||||
with:
|
||||
mdbook-version: "latest"
|
||||
# - name: Run tests
|
||||
# run: mdbook test
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# - server_support
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# - server_support
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Rust
|
||||
run: |
|
||||
rustup set profile minimal
|
||||
rustup toolchain install stable
|
||||
rustup default stable
|
||||
- name: Setup mdBook
|
||||
uses: peaceiris/actions-mdbook@v2
|
||||
with:
|
||||
mdbook-version: "latest"
|
||||
- run: mdbook build
|
||||
# - name: Copy Assets
|
||||
# run: |
|
||||
# chmod +x ci/copy-assets.sh
|
||||
# ci/copy-assets.sh ${{ matrix.os }}
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
# or || github.ref == 'refs/heads/server_support'
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./book
|
||||
@@ -0,0 +1,142 @@
|
||||
name: DockerHub CI
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
push_to_dockerhub:
|
||||
description: 'Push image to DockerHub? (true/false)'
|
||||
required: true
|
||||
default: 'false'
|
||||
type: boolean
|
||||
cuda_version:
|
||||
description: 'CUDA version (e.g., 12.8.1)'
|
||||
required: false
|
||||
default: '12.8.1'
|
||||
type: string
|
||||
push_simplified_tag:
|
||||
description: 'Also push simplified tag? (true/false)'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
ubuntu_mirror:
|
||||
description: 'Use Tsinghua Ubuntu mirror? (0/1)'
|
||||
required: false
|
||||
default: '0'
|
||||
type: string
|
||||
|
||||
# push:
|
||||
# branches:
|
||||
# - main
|
||||
env:
|
||||
DOCKERHUB_REPO: ${{ secrets.DOCKERHUB_USERNAME }}/ktransformers
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run tests
|
||||
run: |
|
||||
if [ -f docker-compose.test.yml ]; then
|
||||
docker-compose --file docker-compose.test.yml build
|
||||
docker-compose --file docker-compose.test.yml run sut
|
||||
else
|
||||
docker build . --file docker/Dockerfile
|
||||
fi
|
||||
|
||||
build-and-push:
|
||||
needs: test
|
||||
name: Build and Push Multi-Variant Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Move Docker data directory
|
||||
run: |
|
||||
sudo systemctl stop docker
|
||||
sudo mkdir -p /mnt/docker
|
||||
sudo rsync -avz /var/lib/docker/ /mnt/docker
|
||||
sudo rm -rf /var/lib/docker
|
||||
sudo ln -s /mnt/docker /var/lib/docker
|
||||
sudo systemctl start docker
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Determine build parameters
|
||||
id: params
|
||||
run: |
|
||||
# Determine if we should push
|
||||
if [ "${{ github.event_name }}" = "release" ]; then
|
||||
echo "should_push=true" >> $GITHUB_OUTPUT
|
||||
echo "push_simplified=true" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "should_push=${{ inputs.push_to_dockerhub }}" >> $GITHUB_OUTPUT
|
||||
echo "push_simplified=${{ inputs.push_simplified_tag }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_push=false" >> $GITHUB_OUTPUT
|
||||
echo "push_simplified=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Determine CUDA version
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.cuda_version }}" ]; then
|
||||
echo "cuda_version=${{ inputs.cuda_version }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "cuda_version=12.8.1" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Determine Ubuntu mirror setting
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.ubuntu_mirror }}" ]; then
|
||||
echo "ubuntu_mirror=${{ inputs.ubuntu_mirror }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "ubuntu_mirror=0" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build and push Docker image
|
||||
run: |
|
||||
cd docker
|
||||
|
||||
# Build command arguments
|
||||
BUILD_ARGS=(
|
||||
--cuda-version "${{ steps.params.outputs.cuda_version }}"
|
||||
--ubuntu-mirror "${{ steps.params.outputs.ubuntu_mirror }}"
|
||||
--repository "${{ env.DOCKERHUB_REPO }}"
|
||||
)
|
||||
|
||||
# Add simplified tag option if enabled
|
||||
if [ "${{ steps.params.outputs.push_simplified }}" = "true" ]; then
|
||||
BUILD_ARGS+=(--also-push-simplified)
|
||||
fi
|
||||
|
||||
# Add HTTP proxy if available
|
||||
if [ -n "${{ secrets.HTTP_PROXY }}" ]; then
|
||||
BUILD_ARGS+=(--http-proxy "${{ secrets.HTTP_PROXY }}")
|
||||
fi
|
||||
|
||||
# Add HTTPS proxy if available
|
||||
if [ -n "${{ secrets.HTTPS_PROXY }}" ]; then
|
||||
BUILD_ARGS+=(--https-proxy "${{ secrets.HTTPS_PROXY }}")
|
||||
fi
|
||||
|
||||
# Dry run if not pushing
|
||||
if [ "${{ steps.params.outputs.should_push }}" != "true" ]; then
|
||||
BUILD_ARGS+=(--dry-run)
|
||||
fi
|
||||
|
||||
# Execute build script
|
||||
./push-to-dockerhub.sh "${BUILD_ARGS[@]}"
|
||||
|
||||
- name: Display image information
|
||||
if: steps.params.outputs.should_push == 'true'
|
||||
run: |
|
||||
echo "::notice title=Docker Image::Image pushed successfully to ${{ env.DOCKERHUB_REPO }}"
|
||||
echo "Pull command: docker pull ${{ env.DOCKERHUB_REPO }}:v\$(VERSION)-cu\$(CUDA_SHORT)"
|
||||
@@ -0,0 +1,104 @@
|
||||
name: PR KT-Kernel Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
types: [synchronize, labeled]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: pr-kt-kernel-test-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# =============================================== check changes ====================================================
|
||||
check-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
kt_kernel: ${{ steps.filter.outputs.kt_kernel }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fail if the PR does not have the 'run-ci' label
|
||||
if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'run-ci')
|
||||
run: |
|
||||
echo "This pull request does not have the 'run-ci' label. Failing the workflow."
|
||||
exit 1
|
||||
|
||||
- name: Fail if the PR is a draft
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.draft == true
|
||||
run: |
|
||||
echo "This pull request is a draft. Failing the workflow."
|
||||
exit 1
|
||||
|
||||
- name: Detect file changes
|
||||
id: filter
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
kt_kernel:
|
||||
- "kt-kernel/**"
|
||||
- ".github/workflows/kt-kernel-tests.yml"
|
||||
|
||||
# =============================================== KT-Kernel tests ====================================================
|
||||
per-commit-kt-kernel-cpu:
|
||||
needs: [check-changes]
|
||||
if: always() && !failure() && !cancelled() &&
|
||||
(needs.check-changes.outputs.kt_kernel == 'true' || github.event_name == 'workflow_dispatch')
|
||||
runs-on: kt-cpu
|
||||
continue-on-error: false
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
sudo rm -rf $GITHUB_WORKSPACE/* || true
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install KT-Kernel
|
||||
run: |
|
||||
cd kt-kernel
|
||||
bash install.sh build
|
||||
|
||||
- name: Run KT-Kernel CPU tests
|
||||
timeout-minutes: 60
|
||||
run: |
|
||||
cd kt-kernel/test
|
||||
python3 run_suite.py --hw cpu --suite default
|
||||
|
||||
# =============================================== finish ====================================================
|
||||
pr-test-kt-kernel-finish:
|
||||
needs: [check-changes, per-commit-kt-kernel-cpu]
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check all dependent job statuses
|
||||
run: |
|
||||
# Convert the 'needs' context to a JSON string
|
||||
json_needs='${{ toJson(needs) }}'
|
||||
|
||||
# Get a list of all job names from the JSON keys
|
||||
job_names=$(echo "$json_needs" | jq -r 'keys_unsorted[]')
|
||||
|
||||
for job in $job_names; do
|
||||
# For each job, extract its result
|
||||
result=$(echo "$json_needs" | jq -r --arg j "$job" '.[$j].result')
|
||||
|
||||
# Print the job name and its result
|
||||
echo "$job: $result"
|
||||
|
||||
# Check for failure or cancellation and exit if found
|
||||
if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
|
||||
echo "The above jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# If the loop completes, all jobs were successful
|
||||
echo "All jobs completed successfully"
|
||||
exit 0
|
||||
@@ -0,0 +1,41 @@
|
||||
name: Release Fake Tag
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "version.py"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
if: github.repository == 'kvcache-ai/ktransformers'
|
||||
runs-on: ubuntu-latest
|
||||
environment: 'prod'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
version=$(cat version.py | grep '__version__' | cut -d'"' -f2)
|
||||
echo "TAG=v$version" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create and push tag
|
||||
run: |
|
||||
TAG=${{ steps.get_version.outputs.TAG }}
|
||||
git config user.name "ktransformers-bot"
|
||||
git config user.email "ktransformers-bot@users.noreply.github.com"
|
||||
if git ls-remote --tags --exit-code origin "refs/tags/${TAG}" > /dev/null 2>&1; then
|
||||
echo "Tag ${TAG} already exists on origin, skipping."
|
||||
exit 0
|
||||
fi
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}"
|
||||
@@ -0,0 +1,283 @@
|
||||
name: Release to PyPI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "version.py"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_pypi:
|
||||
description: 'Publish to TestPyPI instead of PyPI (for testing)'
|
||||
required: false
|
||||
default: 'false'
|
||||
type: choice
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# ── sglang-kt (must be on PyPI before users can pip install kt-kernel) ──
|
||||
build-and-publish-sglang-kt:
|
||||
name: Build & publish sglang-kt
|
||||
runs-on: [self-hosted, linux, x64]
|
||||
if: github.repository == 'kvcache-ai/ktransformers' && github.ref == 'refs/heads/main'
|
||||
environment: prod
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install build tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build wheel setuptools twine
|
||||
|
||||
- name: Build sglang-kt wheel
|
||||
working-directory: third_party/sglang/python
|
||||
run: |
|
||||
KT_VERSION=$(python3 -c "exec(open('${{ github.workspace }}/version.py').read()); print(__version__)")
|
||||
export SGLANG_KT_VERSION="$KT_VERSION"
|
||||
echo "Building sglang-kt v${KT_VERSION} wheel..."
|
||||
python -m build --wheel -v
|
||||
ls dist/ | grep -q "sglang_kt" || (echo "ERROR: Wheel name does not contain sglang_kt" && exit 1)
|
||||
|
||||
- name: Publish sglang-kt to PyPI
|
||||
if: github.event.inputs.test_pypi != 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload --skip-existing --verbose third_party/sglang/python/dist/*.whl
|
||||
|
||||
- name: Publish sglang-kt to TestPyPI (if requested)
|
||||
if: github.event.inputs.test_pypi == 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload --repository testpypi --skip-existing --verbose third_party/sglang/python/dist/*.whl
|
||||
|
||||
# ── kt-kernel ──
|
||||
build-kt-kernel:
|
||||
name: Build kt-kernel (Python ${{ matrix.python-version }})
|
||||
runs-on: [self-hosted, linux, x64, gpu]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.11', '3.12']
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Verify CUDA availability
|
||||
run: |
|
||||
nvidia-smi || (echo "ERROR: GPU not available" && exit 1)
|
||||
nvcc --version || (echo "ERROR: CUDA toolkit not found" && exit 1)
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
# System packages (cmake/libhwloc-dev/pkg-config/libnuma-dev) are expected to be
|
||||
# preinstalled on self-hosted runners. Skip apt-get to avoid sudo dependency.
|
||||
for pkg in cmake pkg-config; do command -v $pkg >/dev/null || { echo "ERROR: $pkg missing on runner"; exit 1; }; done
|
||||
python -m pip install --upgrade pip
|
||||
pip install build wheel setuptools
|
||||
pip install torch --index-url https://download.pytorch.org/whl/cu128
|
||||
|
||||
- name: Build kt-kernel wheel
|
||||
working-directory: kt-kernel
|
||||
env:
|
||||
CPUINFER_BUILD_ALL_VARIANTS: '1'
|
||||
CPUINFER_ENABLE_CPPTRACE: '0'
|
||||
CPUINFER_USE_CUDA: '1'
|
||||
CPUINFER_CUDA_ARCHS: '80;86;89;90;120'
|
||||
CPUINFER_CUDA_STATIC_RUNTIME: '1'
|
||||
CPUINFER_BUILD_TYPE: 'Release'
|
||||
CPUINFER_PARALLEL: '4'
|
||||
CPUINFER_FORCE_REBUILD: '1'
|
||||
CUDA_HOME: '/usr/local/cuda-12.8'
|
||||
run: |
|
||||
echo "Building kt-kernel with:"
|
||||
echo " - CUDA support (SM 80, 86, 89, 90, 120)"
|
||||
echo " - CPU multi-variant (AMX, AVX512, AVX2)"
|
||||
python -m build --wheel -v
|
||||
|
||||
- name: Verify wheel
|
||||
working-directory: kt-kernel
|
||||
run: |
|
||||
echo "Generated wheel:"
|
||||
ls -lh dist/
|
||||
|
||||
# Install and test
|
||||
pip install dist/*.whl
|
||||
python -c "import kt_kernel; print(f'✓ Version: {kt_kernel.__version__}')"
|
||||
python -c "import kt_kernel; print(f'✓ CPU variant: {kt_kernel.__cpu_variant__}')"
|
||||
|
||||
# Verify CUDA support
|
||||
python -c "
|
||||
from kt_kernel import kt_kernel_ext
|
||||
cpu_infer = kt_kernel_ext.CPUInfer(4)
|
||||
methods = dir(cpu_infer)
|
||||
has_cuda = 'submit_with_cuda_stream' in methods
|
||||
print(f'✓ CUDA support: {has_cuda}')
|
||||
"
|
||||
|
||||
# Verify CPU multi-variant support
|
||||
echo "Checking CPU variants in wheel..."
|
||||
python -m zipfile -l dist/*.whl | grep "_kt_kernel_ext_" || echo "Warning: No variant .so files found"
|
||||
python -m zipfile -l dist/*.whl | grep "_kt_kernel_ext_amx.cpython" && echo "✓ AMX variant found" || echo "Note: AMX variant missing"
|
||||
python -m zipfile -l dist/*.whl | grep "_kt_kernel_ext_avx512" && echo "✓ AVX512 variants found" || echo "Note: AVX512 variants missing"
|
||||
python -m zipfile -l dist/*.whl | grep "_kt_kernel_ext_avx2.cpython" && echo "✓ AVX2 variant found" || echo "Note: AVX2 variant missing"
|
||||
|
||||
# Verify static linking (should NOT depend on libcudart.so).
|
||||
# Use $RUNNER_TEMP (honors TMPDIR redirect to /mnt) — /tmp is the
|
||||
# system disk on self-hosted runners and can be tight.
|
||||
CHECK_DIR="${RUNNER_TEMP:-/tmp}/check"
|
||||
rm -rf "$CHECK_DIR"
|
||||
unzip -q dist/*.whl -d "$CHECK_DIR"
|
||||
if ldd "$CHECK_DIR"/kt_kernel/*.so 2>/dev/null | grep -q "libcudart.so"; then
|
||||
echo "ERROR: Dynamic cudart found, should be statically linked"
|
||||
exit 1
|
||||
else
|
||||
echo "✓ CUDA runtime statically linked"
|
||||
fi
|
||||
|
||||
- name: Repair wheel for manylinux
|
||||
working-directory: kt-kernel
|
||||
run: |
|
||||
pip install auditwheel patchelf
|
||||
mkdir -p wheelhouse
|
||||
for wheel in dist/*.whl; do
|
||||
auditwheel repair "$wheel" --plat manylinux_2_35_x86_64 --exclude libcuda.so.1 -w wheelhouse/
|
||||
done
|
||||
rm -f dist/*.whl && cp wheelhouse/*.whl dist/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: kt-kernel-wheels-py${{ matrix.python-version }}
|
||||
path: kt-kernel/dist/*.whl
|
||||
retention-days: 7
|
||||
|
||||
publish-pypi:
|
||||
name: Publish kt-kernel to PyPI
|
||||
needs: [build-and-publish-sglang-kt, build-kt-kernel]
|
||||
runs-on: [self-hosted, linux, x64]
|
||||
if: github.repository == 'kvcache-ai/ktransformers' && github.ref == 'refs/heads/main'
|
||||
environment: prod
|
||||
permissions:
|
||||
id-token: write # For trusted publishing (OIDC)
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Download all wheel artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts/
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Organize wheels into dist/
|
||||
run: |
|
||||
mkdir -p dist/
|
||||
find artifacts/ -name "*.whl" -exec cp {} dist/ \;
|
||||
echo "Wheels to publish:"
|
||||
ls -lh dist/
|
||||
|
||||
- name: Get version from wheel
|
||||
id: get_version
|
||||
run: |
|
||||
# Extract version from first wheel filename
|
||||
wheel_name=$(ls dist/*.whl | head -1 | xargs basename)
|
||||
# Extract version (format: kt_kernel-X.Y.Z-...)
|
||||
version=$(echo "$wheel_name" | sed 's/kt_kernel-\([0-9.]*\)-.*/\1/')
|
||||
echo "VERSION=$version" >> $GITHUB_OUTPUT
|
||||
echo "Publishing version: $version"
|
||||
|
||||
- name: Install twine
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install twine
|
||||
|
||||
- name: Publish to TestPyPI (if requested)
|
||||
if: github.event.inputs.test_pypi == 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload \
|
||||
--repository testpypi \
|
||||
--skip-existing \
|
||||
--verbose \
|
||||
dist/*.whl
|
||||
|
||||
- name: Publish to PyPI
|
||||
if: github.event.inputs.test_pypi != 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload \
|
||||
--skip-existing \
|
||||
--verbose \
|
||||
dist/*.whl
|
||||
|
||||
- name: Create release summary
|
||||
run: |
|
||||
echo "## 🎉 kt-kernel v${{ steps.get_version.outputs.VERSION }} Published to PyPI" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Installation" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
||||
echo "pip install kt-kernel==${{ steps.get_version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Published Wheels" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Total: $(ls -1 dist/*.whl | wc -l) wheels (Python 3.10, 3.11, 3.12)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Features" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**CPU Multi-Variant Support:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ AMX (Intel Sapphire Rapids+, 2023)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ AVX512 Base/VNNI/VBMI/BF16 (Intel Skylake-X/Ice Lake/Cascade Lake, 2017+)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ AVX2 (Maximum compatibility, 2013+)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 🔧 Runtime CPU detection: Automatically selects optimal variant" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**CUDA Support:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ SM 80 (Ampere: A100, RTX 3000 series)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ SM 86 (Ampere: RTX 3060-3090)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ SM 89 (Ada Lovelace: RTX 4000 series)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- ✅ SM 90 (Hopper: H100)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 🔧 Static CUDA runtime: Compatible with CUDA 11.8+ and 12.x drivers" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 🔧 Works on CPU-only systems (CUDA features disabled gracefully)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Requirements:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Python 3.10, 3.11, or 3.12" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Linux x86-64 (manylinux_2_17 compatible)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- For CUDA features: NVIDIA driver with CUDA 11.8+ or 12.x support" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "PyPI link: https://pypi.org/project/kt-kernel/${{ steps.get_version.outputs.VERSION }}/" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -0,0 +1,129 @@
|
||||
name: Release sglang-kt to PyPI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "third_party/sglang"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_pypi:
|
||||
description: 'Publish to TestPyPI instead of PyPI (for testing)'
|
||||
required: false
|
||||
default: 'false'
|
||||
type: choice
|
||||
options:
|
||||
- 'true'
|
||||
- 'false'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-sglang-kt:
|
||||
name: Build sglang-kt wheel
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install build tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build wheel setuptools
|
||||
|
||||
- name: Build sglang-kt wheel
|
||||
working-directory: third_party/sglang/python
|
||||
run: |
|
||||
# Read version from ktransformers version.py
|
||||
KT_VERSION=$(python3 -c "exec(open('${{ github.workspace }}/version.py').read()); print(__version__)")
|
||||
export SGLANG_KT_VERSION="$KT_VERSION"
|
||||
echo "Building sglang-kt v${KT_VERSION} wheel..."
|
||||
python -m build --wheel -v
|
||||
|
||||
- name: Verify wheel
|
||||
working-directory: third_party/sglang/python
|
||||
run: |
|
||||
echo "Generated wheel:"
|
||||
ls -lh dist/
|
||||
# Verify the wheel has the correct package name
|
||||
ls dist/ | grep -q "sglang_kt" || (echo "ERROR: Wheel name does not contain sglang_kt" && exit 1)
|
||||
echo "Wheel name verified."
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sglang-kt-wheel
|
||||
path: third_party/sglang/python/dist/*.whl
|
||||
retention-days: 7
|
||||
|
||||
publish-pypi:
|
||||
name: Publish sglang-kt to PyPI
|
||||
needs: [build-sglang-kt]
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'kvcache-ai/ktransformers' && github.ref == 'refs/heads/main'
|
||||
environment: prod
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Download wheel artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: sglang-kt-wheel
|
||||
path: dist/
|
||||
|
||||
- name: Display wheels
|
||||
run: |
|
||||
echo "Wheels to publish:"
|
||||
ls -lh dist/
|
||||
|
||||
- name: Install twine
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install twine
|
||||
|
||||
- name: Publish to TestPyPI (if requested)
|
||||
if: github.event.inputs.test_pypi == 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload \
|
||||
--repository testpypi \
|
||||
--skip-existing \
|
||||
--verbose \
|
||||
dist/*.whl
|
||||
|
||||
- name: Publish to PyPI
|
||||
if: github.event.inputs.test_pypi != 'true'
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: |
|
||||
python -m twine upload \
|
||||
--skip-existing \
|
||||
--verbose \
|
||||
dist/*.whl
|
||||
|
||||
- name: Create release summary
|
||||
run: |
|
||||
echo "## sglang-kt Published to PyPI" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Installation" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```bash' >> $GITHUB_STEP_SUMMARY
|
||||
echo "pip install sglang-kt" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "This is the kvcache-ai fork of SGLang with kt-kernel support." >> $GITHUB_STEP_SUMMARY
|
||||
echo "PyPI link: https://pypi.org/project/sglang-kt/" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Sync sglang submodule
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run daily at 08:00 UTC
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Check for sglang-kt updates
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Update sglang submodule to latest main
|
||||
id: update
|
||||
run: |
|
||||
OLD_SHA=$(git -C third_party/sglang rev-parse HEAD)
|
||||
git submodule update --remote third_party/sglang
|
||||
NEW_SHA=$(git -C third_party/sglang rev-parse HEAD)
|
||||
|
||||
echo "old_sha=$OLD_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "new_sha=$NEW_SHA" >> "$GITHUB_OUTPUT"
|
||||
|
||||
if [ "$OLD_SHA" = "$NEW_SHA" ]; then
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
echo "sglang submodule is already up to date ($OLD_SHA)"
|
||||
else
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Collect commit log between old and new
|
||||
COMMITS=$(git -C third_party/sglang log --oneline "$OLD_SHA..$NEW_SHA" | head -20)
|
||||
echo "commits<<EOF" >> "$GITHUB_OUTPUT"
|
||||
echo "$COMMITS" >> "$GITHUB_OUTPUT"
|
||||
echo "EOF" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# sglang-kt version = ktransformers version (from version.py)
|
||||
VERSION=$(python3 -c "exec(open('version.py').read()); print(__version__)" 2>/dev/null || echo "unknown")
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "sglang submodule updated: $OLD_SHA -> $NEW_SHA (v$VERSION)"
|
||||
fi
|
||||
|
||||
- name: Create pull request
|
||||
if: steps.update.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: |
|
||||
[build]: sync sglang submodule to ${{ steps.update.outputs.new_sha }}
|
||||
branch: auto/sync-sglang
|
||||
delete-branch: true
|
||||
title: "[build] Sync sglang-kt submodule (v${{ steps.update.outputs.version }})"
|
||||
body: |
|
||||
Automated sync of `third_party/sglang` submodule to latest `main`.
|
||||
|
||||
**Old ref:** `${{ steps.update.outputs.old_sha }}`
|
||||
**New ref:** `${{ steps.update.outputs.new_sha }}`
|
||||
**sglang-kt version:** `${{ steps.update.outputs.version }}`
|
||||
|
||||
### Commits included
|
||||
```
|
||||
${{ steps.update.outputs.commits }}
|
||||
```
|
||||
|
||||
---
|
||||
*This PR was created automatically by the [sync-sglang-submodule](${{ github.server_url }}/${{ github.repository }}/actions/workflows/sync-sglang-submodule.yml) workflow.*
|
||||
labels: |
|
||||
dependencies
|
||||
automated
|
||||
Reference in New Issue
Block a user