From 77fdb6af8146947095186c9f9d4629f2a372af4d Mon Sep 17 00:00:00 2001 From: Douglas Yang Date: Thu, 19 Feb 2026 23:37:40 -0800 Subject: [PATCH] feature: docker patch workflow (#19025) --- .github/workflows/patch-docker-dev.yml | 99 ++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 .github/workflows/patch-docker-dev.yml diff --git a/.github/workflows/patch-docker-dev.yml b/.github/workflows/patch-docker-dev.yml new file mode 100644 index 000000000..0026c2a10 --- /dev/null +++ b/.github/workflows/patch-docker-dev.yml @@ -0,0 +1,99 @@ +name: Patch Docker Image + +on: + workflow_dispatch: + inputs: + pr_numbers: + description: "Comma-separated PR numbers to apply (e.g. 18962,19010)" + required: false + default: "" + image_tag: + description: "Base image tag to patch (e.g. dev-x86, dev-x86-cu13)" + required: true + +concurrency: + group: patch-docker-${{ inputs.image_tag }} + cancel-in-progress: true + +jobs: + patch: + if: github.repository == 'sgl-project/sglang' + runs-on: x64-docker-build-node + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Pull base image and extract commit + run: | + IMAGE="lmsysorg/sglang:${{ inputs.image_tag }}" + docker pull "${IMAGE}" + BASE_SHA=$(docker run --rm "${IMAGE}" git -C /sgl-workspace/sglang rev-parse HEAD) + echo "Image built from commit: ${BASE_SHA}" + echo "BASE_SHA=${BASE_SHA}" >> "$GITHUB_ENV" + + - name: Generate patches + run: | + git fetch origin "${BASE_SHA}" + mkdir -p /tmp/patch-ctx + + if [ -n "${{ inputs.pr_numbers }}" ]; then + IFS=',' read -ra PRS <<< "${{ inputs.pr_numbers }}" + for pr in "${PRS[@]}"; do + pr=$(echo "${pr}" | xargs) + echo "Fetching PR #${pr}" + git fetch origin "pull/${pr}/head:pr-${pr}" + git diff "${BASE_SHA}..pr-${pr}" > "/tmp/patch-ctx/${pr}.patch" + echo " PR #${pr}: $(wc -l < /tmp/patch-ctx/${pr}.patch) lines" + done + else + echo "Generating diff: image ${BASE_SHA} → latest main" + git fetch origin main + git diff "${BASE_SHA}..origin/main" > /tmp/patch-ctx/main.patch + echo " main: $(wc -l < /tmp/patch-ctx/main.patch) lines" + fi + + TOTAL=$(cat /tmp/patch-ctx/*.patch | wc -l) + if [ "${TOTAL}" -eq 0 ]; then + echo "::warning::All patches are empty — image is already up to date" + echo "SKIP_BUILD=true" >> "$GITHUB_ENV" + fi + + - name: Build patched image + if: env.SKIP_BUILD != 'true' + run: | + IMAGE="lmsysorg/sglang:${{ inputs.image_tag }}" + + cat <<'DOCKERFILE' > /tmp/patch-ctx/Dockerfile + ARG BASE_IMAGE + FROM ${BASE_IMAGE} + COPY *.patch /tmp/patches/ + RUN cd /sgl-workspace/sglang \ + && for p in /tmp/patches/*.patch; do \ + echo "Applying ${p}..." \ + && git apply --stat "${p}" \ + && git apply "${p}"; \ + done \ + && rm -rf /tmp/patches + DOCKERFILE + + docker build \ + --no-cache \ + --build-arg BASE_IMAGE="${IMAGE}" \ + -t "${IMAGE}" \ + /tmp/patch-ctx/ + + - name: Push patched image + if: env.SKIP_BUILD != 'true' + run: | + IMAGE="lmsysorg/sglang:${{ inputs.image_tag }}" + docker push "${IMAGE}" + + echo "### Patched \`${IMAGE}\`" >> "$GITHUB_STEP_SUMMARY" + echo "- **Base commit:** \`${BASE_SHA}\`" >> "$GITHUB_STEP_SUMMARY" + echo "- **Source:** ${{ inputs.pr_numbers && format('PRs: {0}', inputs.pr_numbers) || 'latest main' }}" >> "$GITHUB_STEP_SUMMARY"