diff --git a/.buildkite/release-pipeline.yaml b/.buildkite/release-pipeline.yaml index 7b925d293..8f1642805 100644 --- a/.buildkite/release-pipeline.yaml +++ b/.buildkite/release-pipeline.yaml @@ -638,9 +638,93 @@ steps: depends_on: - step: upload-rocm-wheels allow_failure: true + - step: input-release-version + allow_failure: true agents: queue: cpu_queue_postmerge commands: - "bash .buildkite/scripts/annotate-rocm-release.sh" env: S3_BUCKET: "vllm-wheels" + + # ROCm Job 5: Generate Root Index for ROCm Wheels (for release only) + # This is the job to create https://wheels.vllm.ai/rocm/ index allowing + # users to install with `uv pip install vllm --extra-index-url https://wheels.vllm.ai/rocm/` + - block: "Generate Root Index for ROCm Wheels for Release" + key: block-generate-root-index-rocm-wheels + depends_on: upload-rocm-wheels + + - label: ":package: Generate Root Index for ROCm Wheels for Release" + depends_on: block-generate-root-index-rocm-wheels + id: generate-root-index-rocm-wheels + agents: + queue: cpu_queue_postmerge + commands: + - "bash tools/vllm-rocm/generate-rocm-wheels-root-index.sh" + env: + S3_BUCKET: "vllm-wheels" + VARIANT: "rocm700" + + # ROCm Job 5: Build ROCm Release Docker Image + - label: ":rocm: :docker: Build ROCm Release Docker Image" + id: build-rocm-release-image + depends_on: + - step: build-rocm-base-wheels + allow_failure: false + agents: + queue: cpu_queue_postmerge + timeout_in_minutes: 60 + commands: + - | + set -euo pipefail + + # Login to ECR + aws ecr-public get-login-password --region us-east-1 | \ + docker login --username AWS --password-stdin public.ecr.aws/q9t5s3a7 + + # Download Docker image from S3 (set by build-rocm-base-wheels) + DOCKER_IMAGE_S3_PATH="$$(buildkite-agent meta-data get rocm-docker-image-s3-path 2>/dev/null || echo '')" + if [ -z "$${DOCKER_IMAGE_S3_PATH}" ]; then + echo "ERROR: rocm-docker-image-s3-path metadata not found" + exit 1 + fi + + echo "Downloading base image from $${DOCKER_IMAGE_S3_PATH}" + mkdir -p artifacts/rocm-docker-image + aws s3 cp "$${DOCKER_IMAGE_S3_PATH}" artifacts/rocm-docker-image/rocm-base-image.tar.gz + + # Load base Docker image + echo "Loading base Docker image..." + LOAD_OUTPUT=$$(gunzip -c artifacts/rocm-docker-image/rocm-base-image.tar.gz | docker load) + BASE_IMAGE_TAG=$$(echo "$${LOAD_OUTPUT}" | grep "Loaded image:" | sed 's/Loaded image: //') + echo "Loaded base image: $${BASE_IMAGE_TAG}" + + # Tag and push the base image to ECR + docker tag "$${BASE_IMAGE_TAG}" public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base + docker push public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base + echo "Pushed base image: public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base" + + # Get GPU architectures from meta-data + PYTORCH_ROCM_ARCH="$$(buildkite-agent meta-data get rocm-pytorch-rocm-arch 2>/dev/null || echo '')" + PYTORCH_ROCM_ARCH="$${PYTORCH_ROCM_ARCH:-gfx90a;gfx942;gfx950;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151}" + + # Build vLLM ROCm release image using cached base + DOCKER_BUILDKIT=1 docker build \ + --build-arg max_jobs=16 \ + --build-arg BASE_IMAGE="$${BASE_IMAGE_TAG}" \ + --build-arg ARG_PYTORCH_ROCM_ARCH="$${PYTORCH_ROCM_ARCH}" \ + --build-arg USE_SCCACHE=1 \ + --build-arg SCCACHE_BUCKET_NAME=vllm-build-sccache \ + --build-arg SCCACHE_REGION_NAME=us-west-2 \ + --build-arg SCCACHE_S3_NO_CREDENTIALS=0 \ + --tag public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm \ + --target vllm-openai \ + --progress plain \ + -f docker/Dockerfile.rocm . + + # Push to ECR + docker push public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm + echo "Pushed: public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm" + env: + DOCKER_BUILDKIT: "1" + S3_BUCKET: "vllm-wheels" diff --git a/.buildkite/scripts/annotate-release.sh b/.buildkite/scripts/annotate-release.sh index d178fb888..ef9b457b8 100755 --- a/.buildkite/scripts/annotate-release.sh +++ b/.buildkite/scripts/annotate-release.sh @@ -32,6 +32,7 @@ To download and upload the image: \`\`\` docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-x86_64 docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-aarch64 +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-x86_64 vllm/vllm-openai:x86_64 @@ -46,11 +47,17 @@ docker tag vllm/vllm-openai:aarch64 vllm/vllm-openai:v${RELEASE_VERSION}-aarch64 docker push vllm/vllm-openai:latest-aarch64 docker push vllm/vllm-openai:v${RELEASE_VERSION}-aarch64 -docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai:rocm -docker tag vllm/vllm-openai:rocm vllm/vllm-openai:latest-rocm -docker tag vllm/vllm-openai:rocm vllm/vllm-openai:v${RELEASE_VERSION}-rocm -docker push vllm/vllm-openai:latest-rocm -docker push vllm/vllm-openai:v${RELEASE_VERSION}-rocm +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:latest-base +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base +docker push vllm/vllm-openai-rocm:latest-base +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base + +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:latest +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:v${RELEASE_VERSION} +docker push vllm/vllm-openai-rocm:latest +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION} docker manifest rm vllm/vllm-openai:latest docker manifest create vllm/vllm-openai:latest vllm/vllm-openai:latest-x86_64 vllm/vllm-openai:latest-aarch64 diff --git a/.buildkite/scripts/annotate-rocm-release.sh b/.buildkite/scripts/annotate-rocm-release.sh index fcc7c290e..8e7dbfb9e 100755 --- a/.buildkite/scripts/annotate-rocm-release.sh +++ b/.buildkite/scripts/annotate-rocm-release.sh @@ -3,25 +3,32 @@ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project # # Generate Buildkite annotation for ROCm wheel release - set -ex # Get build configuration from meta-data # Extract ROCm version dynamically from Dockerfile.rocm_base -# BASE_IMAGE format: rocm/dev-ubuntu-22.04:7.1-complete -> extracts "7.1" +# BASE_IMAGE format: rocm/dev-ubuntu-22.04:7.0-complete -> extracts "7.0" ROCM_VERSION=$(grep -E '^ARG BASE_IMAGE=' docker/Dockerfile.rocm_base | sed -E 's/.*:([0-9]+\.[0-9]+).*/\1/' || echo "unknown") PYTHON_VERSION=$(buildkite-agent meta-data get rocm-python-version 2>/dev/null || echo "3.12") PYTORCH_ROCM_ARCH=$(buildkite-agent meta-data get rocm-pytorch-rocm-arch 2>/dev/null || echo "gfx90a;gfx942;gfx950;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151") +# TODO: Enable the nightly build for ROCm +# Get release version, default to 1.0.0.dev for nightly/per-commit builds +RELEASE_VERSION=$(buildkite-agent meta-data get release-version 2>/dev/null || echo "") +if [ -z "${RELEASE_VERSION}" ]; then + RELEASE_VERSION="1.0.0.dev" +fi + # S3 URLs S3_BUCKET="${S3_BUCKET:-vllm-wheels}" S3_REGION="${AWS_DEFAULT_REGION:-us-west-2}" -S3_URL="https://${S3_BUCKET}.s3.${S3_REGION}.amazonaws.com" -ROCM_PATH="rocm/${BUILDKITE_COMMIT}" +S3_URL="http://${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com" +# Format ROCm version for path (e.g., "7.1" -> "rocm710") +ROCM_VERSION_PATH="rocm$(echo ${ROCM_VERSION} | tr -d '.')" +ROCM_PATH="rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}" buildkite-agent annotate --style 'success' --context 'rocm-release-workflow' << EOF -## :rocm: ROCm Wheel Release - +## ROCm Wheel and Docker Image Releases ### Build Configuration | Setting | Value | |---------|-------| @@ -34,41 +41,72 @@ buildkite-agent annotate --style 'success' --context 'rocm-release-workflow' << ### :package: Installation **Install from this build (by commit):** -\`\`\`bash -uv pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/{rocm_variant}/ -# Example: -uv pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/rocm700/ +\`\`\`bash +pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com + +# Example for ROCm ${ROCM_VERSION}: +pip install vllm --extra-index-url ${S3_URL}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com \`\`\` **Install from nightly (if published):** + \`\`\`bash -uv pip install vllm --extra-index-url ${S3_URL}/rocm/nightly/ +pip install vllm --extra-index-url ${S3_URL}/rocm/nightly/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com \`\`\` ### :floppy_disk: Download Wheels Directly \`\`\`bash # List all ROCm wheels -aws s3 ls s3://${S3_BUCKET}/${ROCM_PATH}/ - +aws s3 ls s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/ # Download specific wheels -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/vllm-*.whl . -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/torch-*.whl . -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/triton_rocm-*.whl . -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/torchvision-*.whl . -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/amdsmi-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/vllm-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torch-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/triton-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/triton-kernels-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torchvision-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torchaudio-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/amdsmi-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/aiter-*.whl . +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/flash-attn-*.whl . \`\`\` ### :gear: Included Packages - **vllm**: vLLM with ROCm support - **torch**: PyTorch built for ROCm ${ROCM_VERSION} -- **triton_rocm**: Triton built for ROCm +- **triton**: Triton +- **triton-kernels**: Triton kernels - **torchvision**: TorchVision for ROCm PyTorch +- **torchaudio**: Torchaudio for ROCm PyTorch - **amdsmi**: AMD SMI Python bindings +- **aiter**: Aiter for ROCm +- **flash-attn**: Flash Attention for ROCm ### :warning: Notes - These wheels are built for **ROCm ${ROCM_VERSION}** and will NOT work with CUDA GPUs - Supported GPU architectures: ${PYTORCH_ROCM_ARCH} - Platform: Linux x86_64 only + +### :package: Docker Image Release + +To download and upload the image: + +\`\`\` +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm + +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:latest-base +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base +docker push vllm/vllm-openai-rocm:latest-base +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base + +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:latest +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:v${RELEASE_VERSION} +docker push vllm/vllm-openai-rocm:latest +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION} +\`\`\` + EOF diff --git a/docker/Dockerfile.rocm b/docker/Dockerfile.rocm index dc4c8deaf..0178d23b7 100644 --- a/docker/Dockerfile.rocm +++ b/docker/Dockerfile.rocm @@ -227,7 +227,7 @@ RUN if [ "$GIT_REPO_CHECK" != "0" ]; then \ # This ensures setuptools_scm sees clean repo state for version detection RUN --mount=type=bind,source=.git,target=vllm/.git \ cd vllm \ - && pip install setuptools_scm \ + && pip install setuptools_scm regex \ && VLLM_VERSION=$(python3 -c "import setuptools_scm; print(setuptools_scm.get_version())") \ && echo "Detected vLLM version: ${VLLM_VERSION}" \ && echo "${VLLM_VERSION}" > /tmp/vllm_version.txt @@ -342,6 +342,19 @@ RUN mkdir src && mv vllm src/vllm FROM base AS final RUN python3 -m pip install --upgrade pip && rm -rf /var/lib/apt/lists/* + +# Clean up sccache from release image (not needed at runtime) +# This removes the binary and wrappers that may have been installed during build +RUN rm -f /usr/bin/sccache || true \ + && rm -rf /opt/sccache-wrappers || true + +# Unset sccache environment variables for the release image +# This prevents S3 bucket config from leaking into production images +ENV SCCACHE_BUCKET= +ENV SCCACHE_REGION= +ENV SCCACHE_S3_NO_CREDENTIALS= +ENV SCCACHE_IDLE_TIMEOUT= + # Error related to odd state for numpy 1.20.3 where there is no METADATA etc, but an extra LICENSES_bundled.txt. # Manually remove it so that later steps of numpy upgrade can continue RUN case "$(which python3)" in \ diff --git a/tools/vllm-rocm/generate-rocm-wheels-root-index.sh b/tools/vllm-rocm/generate-rocm-wheels-root-index.sh new file mode 100755 index 000000000..02b4fbdd0 --- /dev/null +++ b/tools/vllm-rocm/generate-rocm-wheels-root-index.sh @@ -0,0 +1,233 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# +# Generate S3 PyPI Root Index for Latest Version +# +# Creates a PEP 503 compatible index.html at rocm/ pointing to the latest +# semantic version's packages. This enables users to install with: +# uv pip install vllm --extra-index-url s3://vllm-wheels/rocm +# +# Usage: +# generate-root-index.sh [options] +# +# Options: +# --dry-run Preview changes without uploading +# --version VER Use specific version instead of auto-detecting latest +# +# Environment variables: +# S3_BUCKET - Bucket name (default: vllm-wheels) +# VARIANT - ROCm variant (default: rocm700) +# DRY_RUN - Set to 1 for preview mode (same as --dry-run) + +set -euo pipefail + +# ======== Configuration ======== +BUCKET="${S3_BUCKET:-vllm-wheels}" +VARIANT="${VARIANT:-rocm700}" +DRY_RUN="${DRY_RUN:-0}" +FORCE_VERSION="" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --dry-run) + DRY_RUN=1 + shift + ;; + --version) + FORCE_VERSION="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Working directory for generated files +WORK_DIR=$(mktemp -d) +trap 'rm -rf "$WORK_DIR"' EXIT + +echo "========================================" +echo "Generate Root Index for Latest Version" +echo "========================================" +echo "S3 Bucket: $BUCKET" +echo "ROCm Variant: $VARIANT" +echo "Dry Run: $DRY_RUN" +echo "========================================" +echo "" + +# ======== Step 1: Find latest semantic version ======== + +echo "Step 1: Finding latest semantic version..." + +# List all directories under rocm/ +aws s3api list-objects-v2 \ + --bucket "$BUCKET" \ + --prefix "rocm/" \ + --delimiter "/" \ + --query 'CommonPrefixes[].Prefix' \ + --output text | tr '\t' '\n' > "$WORK_DIR/all_prefixes.txt" + +# Filter for semantic versions (x.y.z pattern) +grep -oE 'rocm/[0-9]+\.[0-9]+\.[0-9]+/' "$WORK_DIR/all_prefixes.txt" | \ + sed 's|rocm/||; s|/||' | \ + sort -V > "$WORK_DIR/versions.txt" || true + +if [[ ! -s "$WORK_DIR/versions.txt" ]]; then + echo "ERROR: No semantic versions found under s3://$BUCKET/rocm/" + exit 1 +fi + +echo "Found versions:" +cat "$WORK_DIR/versions.txt" +echo "" + +if [[ -n "$FORCE_VERSION" ]]; then + LATEST_VERSION="$FORCE_VERSION" + echo "Using forced version: $LATEST_VERSION" +else + LATEST_VERSION=$(tail -1 "$WORK_DIR/versions.txt") + echo "Latest version (auto-detected): $LATEST_VERSION" +fi + +# Verify the version exists +if ! grep -qx "$LATEST_VERSION" "$WORK_DIR/versions.txt"; then + echo "ERROR: Version $LATEST_VERSION not found in bucket" + exit 1 +fi + +# ======== Step 2: List packages from latest version ======== + +echo "" +echo "Step 2: Listing packages from rocm/$LATEST_VERSION/$VARIANT/..." + +VERSION_PREFIX="rocm/$LATEST_VERSION/$VARIANT/" + +# List package directories +aws s3api list-objects-v2 \ + --bucket "$BUCKET" \ + --prefix "$VERSION_PREFIX" \ + --delimiter "/" \ + --query 'CommonPrefixes[].Prefix' \ + --output text | tr '\t' '\n' > "$WORK_DIR/package_prefixes.txt" || true + +if [[ ! -s "$WORK_DIR/package_prefixes.txt" ]]; then + echo "ERROR: No packages found under s3://$BUCKET/$VERSION_PREFIX" + exit 1 +fi + +# Extract package names +sed "s|${VERSION_PREFIX}||; s|/||g" "$WORK_DIR/package_prefixes.txt" | \ + grep -v '^$' > "$WORK_DIR/packages.txt" + +echo "Found packages:" +cat "$WORK_DIR/packages.txt" +echo "" + +# ======== Step 3: Generate root index.html ======== + +echo "Step 3: Generating root index.html..." + +mkdir -p "$WORK_DIR/output" + +{ + cat <<'EOF' + + +
+ + + +EOF + + while read -r pkg; do + echo " $pkg