| name: Build and Push Development Docker Images |
|
|
| on: |
| workflow_dispatch: |
| inputs: |
| pr_number: |
| description: "PR number to build from (leave empty to use current branch)" |
| required: false |
| default: "" |
| tag: |
| description: "Custom tag suffix (overrides pr_number in tag). E.g. 'my-test' → dev-x86-my-test, dev-cu13-my-test, etc." |
| required: false |
| default: "" |
| schedule: |
| - cron: "0 0 * * *" |
|
|
| concurrency: |
| group: release-docker-dev-${{ inputs.tag || inputs.pr_number || 'nightly' }} |
| cancel-in-progress: true |
|
|
| jobs: |
| build-dev: |
| if: ${{ github.repository == 'sgl-project/sglang' }} |
| runs-on: ${{ matrix.runner }} |
| strategy: |
| matrix: |
| include: |
| - runner: x64-docker-build-node |
| platform: linux/amd64 |
| build_type: all |
| grace_blackwell: 0 |
| arch_tag: x86 |
| version: 12.9.1 |
| - runner: arm-docker-build-node |
| platform: linux/arm64 |
| build_type: all |
| grace_blackwell: 1 |
| arch_tag: arm64 |
| version: 12.9.1 |
| - runner: x64-docker-build-node |
| platform: linux/amd64 |
| build_type: all |
| grace_blackwell: 0 |
| arch_tag: x86-cu13 |
| version: 13.0.1 |
| - runner: arm-docker-build-node |
| platform: linux/arm64 |
| build_type: all |
| grace_blackwell: 1 |
| arch_tag: arm64-cu13 |
| version: 13.0.1 |
| steps: |
| - name: Delete huge unnecessary tools folder |
| run: rm -rf /opt/hostedtoolcache |
|
|
| - name: Checkout repository |
| uses: actions/checkout@v4 |
| with: |
| ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || github.ref }} |
|
|
| - name: Free disk space |
| uses: jlumbroso/free-disk-space@main |
| with: |
| tool-cache: true |
| docker-images: true |
| android: true |
| dotnet: true |
| haskell: true |
| large-packages: true |
| swap-storage: true |
|
|
| - name: Prune Docker to reclaim disk space |
| run: | |
| docker buildx prune --filter "until=72h" -f |
| docker system prune -af --filter "until=72h" |
| docker volume prune -af |
| |
| - name: Set up Docker Buildx |
| uses: docker/setup-buildx-action@v3 |
|
|
| - name: Login to Docker Hub |
| uses: docker/login-action@v2 |
| with: |
| username: ${{ secrets.DOCKERHUB_USERNAME }} |
| password: ${{ secrets.DOCKERHUB_TOKEN }} |
|
|
| - name: Build and Push Dev Image |
| run: | |
| # Tag suffix: custom tag > pr number > none |
| SUFFIX="" |
| if [ -n "${{ inputs.tag }}" ]; then |
| SUFFIX="-${{ inputs.tag }}" |
| elif [ -n "${{ inputs.pr_number }}" ]; then |
| SUFFIX="-pr-${{ inputs.pr_number }}" |
| fi |
| |
| TAG="dev-${{ matrix.arch_tag }}${SUFFIX}" |
|
|
| |
| if [ "${{ github.event_name }}" = "schedule" ]; then |
| SOURCE_ARG="--build-arg USE_LATEST_SGLANG=1" |
| else |
| SOURCE_ARG="--build-arg BRANCH_TYPE=local" |
| fi |
|
|
| echo "Building lmsysorg/sglang:${TAG}" |
|
|
| docker buildx build \ |
| --platform ${{ matrix.platform }} \ |
| --push \ |
| --target framework \ |
| -f docker/Dockerfile \ |
| --build-arg CUDA_VERSION=${{ matrix.version }} \ |
| --build-arg BUILD_TYPE=${{ matrix.build_type }} \ |
| --build-arg CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) \ |
| --build-arg GRACE_BLACKWELL=${{ matrix.grace_blackwell }} \ |
| ${SOURCE_ARG} \ |
| --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ |
| -t lmsysorg/sglang:${TAG} \ |
| --no-cache \ |
| . |
|
|
| create-manifests: |
| runs-on: ubuntu-22.04 |
| needs: [build-dev] |
| if: ${{ github.repository == 'sgl-project/sglang' }} |
| strategy: |
| matrix: |
| variant: |
| - base: dev |
| x86: x86 |
| arm64: arm64 |
| - base: dev-cu13 |
| x86: x86-cu13 |
| arm64: arm64-cu13 |
| steps: |
| - uses: docker/setup-buildx-action@v3 |
|
|
| - uses: docker/login-action@v2 |
| with: |
| username: ${{ secrets.DOCKERHUB_USERNAME }} |
| password: ${{ secrets.DOCKERHUB_TOKEN }} |
|
|
| - name: Create multi-arch manifest |
| run: | |
| SUFFIX="" |
| if [ -n "${{ inputs.tag }}" ]; then |
| SUFFIX="-${{ inputs.tag }}" |
| elif [ -n "${{ inputs.pr_number }}" ]; then |
| SUFFIX="-pr-${{ inputs.pr_number }}" |
| fi |
| |
| TAG="${{ matrix.variant.base }}${SUFFIX}" |
| X86_TAG="dev-${{ matrix.variant.x86 }}${SUFFIX}" |
| ARM64_TAG="dev-${{ matrix.variant.arm64 }}${SUFFIX}" |
|
|
| |
| EXTRA_TAG="" |
| if [ -z "${SUFFIX}" ]; then |
| SHORT_SHA="${{ github.sha }}" |
| EXTRA_TAG="-t lmsysorg/sglang:nightly-${TAG}-$(date +%Y%m%d)-${SHORT_SHA:0:8}" |
| fi |
|
|
| docker buildx imagetools create \ |
| -t lmsysorg/sglang:${TAG} \ |
| ${EXTRA_TAG} \ |
| lmsysorg/sglang:${X86_TAG} \ |
| lmsysorg/sglang:${ARM64_TAG} |
|
|
| echo "✓ Published lmsysorg/sglang:${TAG}" |
|
|
| - name: Cleanup Old Nightly Builds |
| if: ${{ !inputs.tag && !inputs.pr_number }} |
| run: | |
| TOKEN=$(curl -s -H "Content-Type: application/json" \ |
| -X POST -d '{"username": "${{ secrets.DOCKERHUB_USERNAME }}", "password": "${{ secrets.DOCKERHUB_TOKEN }}"}' \ |
| https://hub.docker.com/v2/users/login/ | jq -r .token) |
| |
| TAGS_RESPONSE=$(curl -s -H "Authorization: JWT $TOKEN" \ |
| "https://hub.docker.com/v2/repositories/lmsysorg/sglang/tags/?page_size=100") |
|
|
| TAGS=$(echo "$TAGS_RESPONSE" | jq -r \ |
| '.results[] | select(.name | test("^nightly-${{ matrix.variant.base }}-[0-9]")) | "\(.last_updated)|\(.name)"' \ |
| | sort -r | cut -d'|' -f2) |
|
|
| TAG_COUNT=$(echo "$TAGS" | wc -l) |
| if [ "$TAG_COUNT" -gt 14 ]; then |
| echo "Found $TAG_COUNT nightly builds, keeping only the 14 most recent" |
| TAGS_TO_DELETE=$(echo "$TAGS" | tail -n +15) |
| for tag in $TAGS_TO_DELETE; do |
| echo "Deleting tag: $tag" |
| curl -X DELETE -H "Authorization: JWT $TOKEN" \ |
| "https://hub.docker.com/v2/repositories/lmsysorg/sglang/tags/$tag/" |
| done |
| else |
| echo "Only $TAG_COUNT nightly builds found, no cleanup needed" |
| fi |
|
|