diff --git a/.github/workflows/release-docker-cu13-framework.yml b/.github/workflows/release-docker-cu13-framework.yml index a0800b7fe..725bed429 100644 --- a/.github/workflows/release-docker-cu13-framework.yml +++ b/.github/workflows/release-docker-cu13-framework.yml @@ -57,22 +57,32 @@ jobs: - name: Build and Push AMD64 Framework (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-amd64 docker buildx build \ --target framework \ --platform linux/amd64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=all \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg GRACE_BLACKWELL=0 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-amd64-framework.txt + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digest-cu130-amd64 + path: /tmp/digest-cu130-amd64-framework.txt + retention-days: 1 + publish-arm64: if: github.repository == 'sgl-project/sglang' runs-on: arm-docker-build-node @@ -109,22 +119,32 @@ jobs: - name: Build and Push ARM64 Framework (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-arm64 docker buildx build \ --target framework \ --platform linux/arm64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=all \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg GRACE_BLACKWELL=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-arm64-framework.txt + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digest-cu130-arm64 + path: /tmp/digest-cu130-arm64-framework.txt + retention-days: 1 + create-manifest: runs-on: ubuntu-22.04 needs: [publish-x86, publish-arm64] @@ -139,18 +159,32 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Download amd64 digest + uses: actions/download-artifact@v4 + with: + name: digest-cu130-amd64 + path: /tmp/digests/amd64 + + - name: Download arm64 digest + uses: actions/download-artifact@v4 + with: + name: digest-cu130-arm64 + path: /tmp/digests/arm64 + - name: Create multi-arch manifest run: | version=${{ github.event.inputs.version }} + AMD64_DIGEST=$(cat /tmp/digests/amd64/digest-cu130-amd64-framework.txt) + ARM64_DIGEST=$(cat /tmp/digests/arm64/digest-cu130-arm64-framework.txt) # Create versioned CUDA 13 framework manifest docker buildx imagetools create \ -t lmsysorg/sglang:v${version}-cu130 \ - lmsysorg/sglang:v${version}-cu130-amd64 \ - lmsysorg/sglang:v${version}-cu130-arm64 + lmsysorg/sglang@${AMD64_DIGEST} \ + lmsysorg/sglang@${ARM64_DIGEST} # Create latest CUDA 13 framework manifest docker buildx imagetools create \ -t lmsysorg/sglang:latest-cu130 \ - lmsysorg/sglang:v${version}-cu130-amd64 \ - lmsysorg/sglang:v${version}-cu130-arm64 + lmsysorg/sglang@${AMD64_DIGEST} \ + lmsysorg/sglang@${ARM64_DIGEST} diff --git a/.github/workflows/release-docker-dev.yml b/.github/workflows/release-docker-dev.yml index 18dbed573..baf7bae2c 100644 --- a/.github/workflows/release-docker-dev.yml +++ b/.github/workflows/release-docker-dev.yml @@ -8,7 +8,7 @@ on: 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." + description: "Custom tag suffix (overrides pr_number in tag). E.g. 'my-test' → dev-my-test, dev-cu13-my-test, etc." required: false default: "" schedule: @@ -86,16 +86,6 @@ jobs: - 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}" - # Nightly (schedule) installs latest release; manual dispatch builds from checked-out source if [ "${{ github.event_name }}" = "schedule" ]; then SOURCE_ARG="--build-arg USE_LATEST_SGLANG=1" @@ -103,11 +93,9 @@ jobs: SOURCE_ARG="--build-arg BRANCH_TYPE=local" fi - echo "Building lmsysorg/sglang:${TAG}" - docker buildx build \ --platform ${{ matrix.platform }} \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ --target framework \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=${{ matrix.version }} \ @@ -116,10 +104,21 @@ jobs: --build-arg GRACE_BLACKWELL=${{ matrix.grace_blackwell }} \ ${SOURCE_ARG} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ - -t lmsysorg/sglang:${TAG} \ + --metadata-file /tmp/metadata.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest.txt + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digest-${{ matrix.arch_tag }} + path: /tmp/digest.txt + retention-days: 1 + create-manifests: runs-on: ubuntu-22.04 needs: [build-dev] @@ -141,8 +140,23 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Download x86 digest + uses: actions/download-artifact@v4 + with: + name: digest-${{ matrix.variant.x86 }} + path: /tmp/digests/x86 + + - name: Download arm64 digest + uses: actions/download-artifact@v4 + with: + name: digest-${{ matrix.variant.arm64 }} + path: /tmp/digests/arm64 + - name: Create multi-arch manifest run: | + X86_DIGEST=$(cat /tmp/digests/x86/digest.txt) + ARM64_DIGEST=$(cat /tmp/digests/arm64/digest.txt) + SUFFIX="" if [ -n "${{ inputs.tag }}" ]; then SUFFIX="-${{ inputs.tag }}" @@ -151,8 +165,6 @@ jobs: fi TAG="${{ matrix.variant.base }}${SUFFIX}" - X86_TAG="dev-${{ matrix.variant.x86 }}${SUFFIX}" - ARM64_TAG="dev-${{ matrix.variant.arm64 }}${SUFFIX}" # For nightly (no suffix), also stamp a dated tag EXTRA_TAG="" @@ -164,8 +176,8 @@ jobs: docker buildx imagetools create \ -t lmsysorg/sglang:${TAG} \ ${EXTRA_TAG} \ - lmsysorg/sglang:${X86_TAG} \ - lmsysorg/sglang:${ARM64_TAG} + lmsysorg/sglang@${X86_DIGEST} \ + lmsysorg/sglang@${ARM64_DIGEST} echo "✓ Published lmsysorg/sglang:${TAG}" diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index ecca43722..2f503d22e 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -4,11 +4,11 @@ name: Release Docker Images # # Framework images (full development environment): # - lmsysorg/sglang:v{version}, lmsysorg/sglang:latest -# - lmsysorg/sglang:v{version}-cu129-{amd64,arm64} +# - lmsysorg/sglang:v{version}-cu130, lmsysorg/sglang:latest-cu130 # # Runtime images (production-optimized, ~50% smaller): # - lmsysorg/sglang:v{version}-runtime, lmsysorg/sglang:latest-runtime -# - lmsysorg/sglang:v{version}-cu129-{amd64,arm64}-runtime +# - lmsysorg/sglang:v{version}-cu130-runtime, lmsysorg/sglang:latest-cu130-runtime # on: push: @@ -83,79 +83,98 @@ jobs: - name: Build AMD64 Framework run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu129-amd64 docker buildx build \ --target framework \ --platform linux/amd64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=${{ matrix.variant.cuda_version }} \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg GRACE_BLACKWELL=${{ matrix.variant.grace_blackwell }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu129-framework.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu129-framework.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu129-amd64-framework.txt + - name: Build and Push AMD64 Runtime run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu129-amd64-runtime docker buildx build \ --target runtime \ --platform linux/amd64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=${{ matrix.variant.cuda_version }} \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg GRACE_BLACKWELL=${{ matrix.variant.grace_blackwell }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu129-runtime.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu129-runtime.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu129-amd64-runtime.txt + - name: Build and Push AMD64 Framework (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-amd64 docker buildx build \ --target framework \ --platform linux/amd64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg GRACE_BLACKWELL=0 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu130-framework.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu130-framework.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-amd64-framework.txt + - name: Build and Push AMD64 Runtime (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-amd64-runtime docker buildx build \ --target runtime \ --platform linux/amd64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg GRACE_BLACKWELL=0 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu130-runtime.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu130-runtime.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-amd64-runtime.txt + + - name: Upload digests + uses: actions/upload-artifact@v4 + with: + name: digests-amd64 + path: /tmp/digest-*.txt + retention-days: 1 + publish-arm64: if: github.repository == 'sgl-project/sglang' environment: "prod" @@ -207,78 +226,97 @@ jobs: - name: Build ARM64 Framework run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu129-arm64 docker buildx build \ --target framework \ --platform linux/arm64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=${{ matrix.variant.cuda_version }} \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg GRACE_BLACKWELL=${{ matrix.variant.grace_blackwell }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu129-framework.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu129-framework.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu129-arm64-framework.txt + - name: Build and Push ARM64 Runtime run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu129-arm64-runtime docker buildx build \ --target runtime \ --platform linux/arm64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=${{ matrix.variant.cuda_version }} \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg GRACE_BLACKWELL=${{ matrix.variant.grace_blackwell }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu129-runtime.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu129-runtime.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu129-arm64-runtime.txt + - name: Build and Push ARM64 Framework (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-arm64 docker buildx build \ --target framework \ --platform linux/arm64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ --build-arg GRACE_BLACKWELL=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu130-framework.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu130-framework.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-arm64-framework.txt + - name: Build and Push ARM64 Runtime (CUDA 13) run: | version=${{ steps.version.outputs.version }} - tag=v${version}-cu130-arm64-runtime docker buildx build \ --target runtime \ --platform linux/arm64 \ - --push \ + --output type=image,name=lmsysorg/sglang,push-by-digest=true,name-canonical=true,push=true \ -f docker/Dockerfile \ --build-arg CUDA_VERSION=13.0.1 \ --build-arg BUILD_TYPE=${{ matrix.variant.build_type }} \ --build-arg GRACE_BLACKWELL=1 \ --build-arg SGL_VERSION=${version} \ - -t lmsysorg/sglang:${tag} \ + --metadata-file /tmp/metadata-cu130-runtime.json \ --no-cache \ . + DIGEST=$(python3 -c "import json; print(json.load(open('/tmp/metadata-cu130-runtime.json'))['containerimage.digest'])") + echo "Pushed digest: ${DIGEST}" + echo "${DIGEST}" > /tmp/digest-cu130-arm64-runtime.txt + + - name: Upload digests + uses: actions/upload-artifact@v4 + with: + name: digests-arm64 + path: /tmp/digest-*.txt + retention-days: 1 + create-manifests: runs-on: ubuntu-22.04 needs: [publish-x86, publish-arm64] @@ -319,54 +357,76 @@ jobs: echo "version=${VERSION}" >> $GITHUB_OUTPUT + - name: Download amd64 digests + uses: actions/download-artifact@v4 + with: + name: digests-amd64 + path: /tmp/digests/amd64 + + - name: Download arm64 digests + uses: actions/download-artifact@v4 + with: + name: digests-arm64 + path: /tmp/digests/arm64 + - name: Create multi-arch manifests run: | version=${{ steps.version.outputs.version }} + # Load all digests + CU129_AMD64_FW=$(cat /tmp/digests/amd64/digest-cu129-amd64-framework.txt) + CU129_AMD64_RT=$(cat /tmp/digests/amd64/digest-cu129-amd64-runtime.txt) + CU130_AMD64_FW=$(cat /tmp/digests/amd64/digest-cu130-amd64-framework.txt) + CU130_AMD64_RT=$(cat /tmp/digests/amd64/digest-cu130-amd64-runtime.txt) + CU129_ARM64_FW=$(cat /tmp/digests/arm64/digest-cu129-arm64-framework.txt) + CU129_ARM64_RT=$(cat /tmp/digests/arm64/digest-cu129-arm64-runtime.txt) + CU130_ARM64_FW=$(cat /tmp/digests/arm64/digest-cu130-arm64-framework.txt) + CU130_ARM64_RT=$(cat /tmp/digests/arm64/digest-cu130-arm64-runtime.txt) + # Create versioned framework manifest (default) docker buildx imagetools create \ -t lmsysorg/sglang:v${version} \ - lmsysorg/sglang:v${version}-cu129-amd64 \ - lmsysorg/sglang:v${version}-cu129-arm64 + lmsysorg/sglang@${CU129_AMD64_FW} \ + lmsysorg/sglang@${CU129_ARM64_FW} # Create latest framework manifest (default) docker buildx imagetools create \ -t lmsysorg/sglang:latest \ - lmsysorg/sglang:v${version}-cu129-amd64 \ - lmsysorg/sglang:v${version}-cu129-arm64 + lmsysorg/sglang@${CU129_AMD64_FW} \ + lmsysorg/sglang@${CU129_ARM64_FW} # Create versioned runtime manifest docker buildx imagetools create \ -t lmsysorg/sglang:v${version}-runtime \ - lmsysorg/sglang:v${version}-cu129-amd64-runtime \ - lmsysorg/sglang:v${version}-cu129-arm64-runtime + lmsysorg/sglang@${CU129_AMD64_RT} \ + lmsysorg/sglang@${CU129_ARM64_RT} # Create latest runtime manifest docker buildx imagetools create \ -t lmsysorg/sglang:latest-runtime \ - lmsysorg/sglang:v${version}-cu129-amd64-runtime \ - lmsysorg/sglang:v${version}-cu129-arm64-runtime + lmsysorg/sglang@${CU129_AMD64_RT} \ + lmsysorg/sglang@${CU129_ARM64_RT} # Create versioned CUDA 13 framework manifest docker buildx imagetools create \ -t lmsysorg/sglang:v${version}-cu130 \ - lmsysorg/sglang:v${version}-cu130-amd64 \ - lmsysorg/sglang:v${version}-cu130-arm64 + lmsysorg/sglang@${CU130_AMD64_FW} \ + lmsysorg/sglang@${CU130_ARM64_FW} # Create latest CUDA 13 framework manifest docker buildx imagetools create \ -t lmsysorg/sglang:latest-cu130 \ - lmsysorg/sglang:v${version}-cu130-amd64 \ - lmsysorg/sglang:v${version}-cu130-arm64 + lmsysorg/sglang@${CU130_AMD64_FW} \ + lmsysorg/sglang@${CU130_ARM64_FW} # Create versioned CUDA 13 runtime manifest docker buildx imagetools create \ -t lmsysorg/sglang:v${version}-cu130-runtime \ - lmsysorg/sglang:v${version}-cu130-amd64-runtime \ - lmsysorg/sglang:v${version}-cu130-arm64-runtime + lmsysorg/sglang@${CU130_AMD64_RT} \ + lmsysorg/sglang@${CU130_ARM64_RT} # Create latest CUDA 13 runtime manifest docker buildx imagetools create \ -t lmsysorg/sglang:latest-cu130-runtime \ - lmsysorg/sglang:v${version}-cu130-amd64-runtime \ - lmsysorg/sglang:v${version}-cu130-arm64-runtime + lmsysorg/sglang@${CU130_AMD64_RT} \ + lmsysorg/sglang@${CU130_ARM64_RT}