@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / f9d03599ef
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 9, 10:00 UTC

[Release] [CI] Optim release pipeline (#33156)

Signed-off-by: tjtanaa <tunjian.tan@embeddedllm.com>

TJian committed Jan 29, 2026 at 14:45 UTC f9d03599ef1528b1b1d35f90d858db88b5857ce1
5 files changed +399 -24
.buildkite/release-pipeline.yaml
+84
@@ -638,9 +638,93 @@ steps:
638 depends_on:
639 - step: upload-rocm-wheels
640 allow_failure: true
641 + - step: input-release-version
642 + allow_failure: true
643 agents:
644 queue: cpu_queue_postmerge
645 commands:
646 - "bash .buildkite/scripts/annotate-rocm-release.sh"
647 env:
648 S3_BUCKET: "vllm-wheels"
649 +
650 + # ROCm Job 5: Generate Root Index for ROCm Wheels (for release only)
651 + # This is the job to create https://wheels.vllm.ai/rocm/ index allowing
652 + # users to install with `uv pip install vllm --extra-index-url https://wheels.vllm.ai/rocm/`
653 + - block: "Generate Root Index for ROCm Wheels for Release"
654 + key: block-generate-root-index-rocm-wheels
655 + depends_on: upload-rocm-wheels
656 +
657 + - label: ":package: Generate Root Index for ROCm Wheels for Release"
658 + depends_on: block-generate-root-index-rocm-wheels
659 + id: generate-root-index-rocm-wheels
660 + agents:
661 + queue: cpu_queue_postmerge
662 + commands:
663 + - "bash tools/vllm-rocm/generate-rocm-wheels-root-index.sh"
664 + env:
665 + S3_BUCKET: "vllm-wheels"
666 + VARIANT: "rocm700"
667 +
668 + # ROCm Job 5: Build ROCm Release Docker Image
669 + - label: ":rocm: :docker: Build ROCm Release Docker Image"
670 + id: build-rocm-release-image
671 + depends_on:
672 + - step: build-rocm-base-wheels
673 + allow_failure: false
674 + agents:
675 + queue: cpu_queue_postmerge
676 + timeout_in_minutes: 60
677 + commands:
678 + - |
679 + set -euo pipefail
680 +
681 + # Login to ECR
682 + aws ecr-public get-login-password --region us-east-1 | \
683 + docker login --username AWS --password-stdin public.ecr.aws/q9t5s3a7
684 +
685 + # Download Docker image from S3 (set by build-rocm-base-wheels)
686 + DOCKER_IMAGE_S3_PATH="$$(buildkite-agent meta-data get rocm-docker-image-s3-path 2>/dev/null || echo '')"
687 + if [ -z "$${DOCKER_IMAGE_S3_PATH}" ]; then
688 + echo "ERROR: rocm-docker-image-s3-path metadata not found"
689 + exit 1
690 + fi
691 +
692 + echo "Downloading base image from $${DOCKER_IMAGE_S3_PATH}"
693 + mkdir -p artifacts/rocm-docker-image
694 + aws s3 cp "$${DOCKER_IMAGE_S3_PATH}" artifacts/rocm-docker-image/rocm-base-image.tar.gz
695 +
696 + # Load base Docker image
697 + echo "Loading base Docker image..."
698 + LOAD_OUTPUT=$$(gunzip -c artifacts/rocm-docker-image/rocm-base-image.tar.gz | docker load)
699 + BASE_IMAGE_TAG=$$(echo "$${LOAD_OUTPUT}" | grep "Loaded image:" | sed 's/Loaded image: //')
700 + echo "Loaded base image: $${BASE_IMAGE_TAG}"
701 +
702 + # Tag and push the base image to ECR
703 + docker tag "$${BASE_IMAGE_TAG}" public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base
704 + docker push public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base
705 + echo "Pushed base image: public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm-base"
706 +
707 + # Get GPU architectures from meta-data
708 + PYTORCH_ROCM_ARCH="$$(buildkite-agent meta-data get rocm-pytorch-rocm-arch 2>/dev/null || echo '')"
709 + PYTORCH_ROCM_ARCH="$${PYTORCH_ROCM_ARCH:-gfx90a;gfx942;gfx950;gfx1100;gfx1101;gfx1200;gfx1201;gfx1150;gfx1151}"
710 +
711 + # Build vLLM ROCm release image using cached base
712 + DOCKER_BUILDKIT=1 docker build \
713 + --build-arg max_jobs=16 \
714 + --build-arg BASE_IMAGE="$${BASE_IMAGE_TAG}" \
715 + --build-arg ARG_PYTORCH_ROCM_ARCH="$${PYTORCH_ROCM_ARCH}" \
716 + --build-arg USE_SCCACHE=1 \
717 + --build-arg SCCACHE_BUCKET_NAME=vllm-build-sccache \
718 + --build-arg SCCACHE_REGION_NAME=us-west-2 \
719 + --build-arg SCCACHE_S3_NO_CREDENTIALS=0 \
720 + --tag public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm \
721 + --target vllm-openai \
722 + --progress plain \
723 + -f docker/Dockerfile.rocm .
724 +
725 + # Push to ECR
726 + docker push public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm
727 + echo "Pushed: public.ecr.aws/q9t5s3a7/vllm-release-repo:$${BUILDKITE_COMMIT}-rocm"
728 + env:
729 + DOCKER_BUILDKIT: "1"
730 + S3_BUCKET: "vllm-wheels"
.buildkite/scripts/annotate-release.sh
+12 -5
@@ -32,6 +32,7 @@ To download and upload the image:
32 \`\`\`
33 docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-x86_64
34 docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-aarch64
35 +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base
36 docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm
37
38 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
47 docker push vllm/vllm-openai:latest-aarch64
48 docker push vllm/vllm-openai:v${RELEASE_VERSION}-aarch64
49
49 -docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai:rocm
50 -docker tag vllm/vllm-openai:rocm vllm/vllm-openai:latest-rocm
51 -docker tag vllm/vllm-openai:rocm vllm/vllm-openai:v${RELEASE_VERSION}-rocm
52 -docker push vllm/vllm-openai:latest-rocm
53 -docker push vllm/vllm-openai:v${RELEASE_VERSION}-rocm
50 +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base
51 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:latest-base
52 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base
53 +docker push vllm/vllm-openai-rocm:latest-base
54 +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base
55 +
56 +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}
57 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:latest
58 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:v${RELEASE_VERSION}
59 +docker push vllm/vllm-openai-rocm:latest
60 +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}
61
62 docker manifest rm vllm/vllm-openai:latest
63 docker manifest create vllm/vllm-openai:latest vllm/vllm-openai:latest-x86_64 vllm/vllm-openai:latest-aarch64
.buildkite/scripts/annotate-rocm-release.sh
+56 -18
@@ -3,25 +3,32 @@
3 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4 #
5 # Generate Buildkite annotation for ROCm wheel release
6 -
6 set -ex
7
8 # Get build configuration from meta-data
9 # Extract ROCm version dynamically from Dockerfile.rocm_base
11 -# BASE_IMAGE format: rocm/dev-ubuntu-22.04:7.1-complete -> extracts "7.1"
10 +# BASE_IMAGE format: rocm/dev-ubuntu-22.04:7.0-complete -> extracts "7.0"
11 ROCM_VERSION=$(grep -E '^ARG BASE_IMAGE=' docker/Dockerfile.rocm_base | sed -E 's/.*:([0-9]+\.[0-9]+).*/\1/' || echo "unknown")
12 PYTHON_VERSION=$(buildkite-agent meta-data get rocm-python-version 2>/dev/null || echo "3.12")
13 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")
14
15 +# TODO: Enable the nightly build for ROCm
16 +# Get release version, default to 1.0.0.dev for nightly/per-commit builds
17 +RELEASE_VERSION=$(buildkite-agent meta-data get release-version 2>/dev/null || echo "")
18 +if [ -z "${RELEASE_VERSION}" ]; then
19 + RELEASE_VERSION="1.0.0.dev"
20 +fi
21 +
22 # S3 URLs
23 S3_BUCKET="${S3_BUCKET:-vllm-wheels}"
24 S3_REGION="${AWS_DEFAULT_REGION:-us-west-2}"
19 -S3_URL="https://${S3_BUCKET}.s3.${S3_REGION}.amazonaws.com"
20 -ROCM_PATH="rocm/${BUILDKITE_COMMIT}"
25 +S3_URL="http://${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com"
26
27 +# Format ROCm version for path (e.g., "7.1" -> "rocm710")
28 +ROCM_VERSION_PATH="rocm$(echo ${ROCM_VERSION} | tr -d '.')"
29 +ROCM_PATH="rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}"
30 buildkite-agent annotate --style 'success' --context 'rocm-release-workflow' << EOF
23 -## :rocm: ROCm Wheel Release
24 -
31 +## ROCm Wheel and Docker Image Releases
32 ### Build Configuration
33 | Setting | Value |
34 |---------|-------|
@@ -34,41 +41,72 @@ buildkite-agent annotate --style 'success' --context 'rocm-release-workflow' <<
41 ### :package: Installation
42
43 **Install from this build (by commit):**
44 +
45 \`\`\`bash
38 -uv pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/{rocm_variant}/
46 +pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com
47
40 -# Example:
41 -uv pip install vllm --extra-index-url ${S3_URL}/${ROCM_PATH}/rocm700/
48 +# Example for ROCm ${ROCM_VERSION}:
49 +pip install vllm --extra-index-url ${S3_URL}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com
50 \`\`\`
51
52 **Install from nightly (if published):**
53 +
54 \`\`\`bash
46 -uv pip install vllm --extra-index-url ${S3_URL}/rocm/nightly/
55 +pip install vllm --extra-index-url ${S3_URL}/rocm/nightly/ --trusted-host ${S3_BUCKET}.s3-website-${S3_REGION}.amazonaws.com
56 \`\`\`
57
58 ### :floppy_disk: Download Wheels Directly
59
60 \`\`\`bash
61 # List all ROCm wheels
53 -aws s3 ls s3://${S3_BUCKET}/${ROCM_PATH}/
54 -
62 +aws s3 ls s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/
63 # Download specific wheels
56 -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/vllm-*.whl .
57 -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/torch-*.whl .
58 -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/triton_rocm-*.whl .
59 -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/torchvision-*.whl .
60 -aws s3 cp s3://${S3_BUCKET}/${ROCM_PATH}/amdsmi-*.whl .
64 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/vllm-*.whl .
65 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torch-*.whl .
66 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/triton-*.whl .
67 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/triton-kernels-*.whl .
68 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torchvision-*.whl .
69 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/torchaudio-*.whl .
70 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/amdsmi-*.whl .
71 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/aiter-*.whl .
72 +aws s3 cp s3://${S3_BUCKET}/rocm/${BUILDKITE_COMMIT}/${ROCM_VERSION_PATH}/flash-attn-*.whl .
73 \`\`\`
74
75 ### :gear: Included Packages
76 - **vllm**: vLLM with ROCm support
77 - **torch**: PyTorch built for ROCm ${ROCM_VERSION}
66 -- **triton_rocm**: Triton built for ROCm
78 +- **triton**: Triton
79 +- **triton-kernels**: Triton kernels
80 - **torchvision**: TorchVision for ROCm PyTorch
81 +- **torchaudio**: Torchaudio for ROCm PyTorch
82 - **amdsmi**: AMD SMI Python bindings
83 +- **aiter**: Aiter for ROCm
84 +- **flash-attn**: Flash Attention for ROCm
85
86 ### :warning: Notes
87 - These wheels are built for **ROCm ${ROCM_VERSION}** and will NOT work with CUDA GPUs
88 - Supported GPU architectures: ${PYTORCH_ROCM_ARCH}
89 - Platform: Linux x86_64 only
90 +
91 +### :package: Docker Image Release
92 +
93 +To download and upload the image:
94 +
95 +\`\`\`
96 +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base
97 +docker pull public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm
98 +
99 +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm-base vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base
100 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:latest-base
101 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}-base vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base
102 +docker push vllm/vllm-openai-rocm:latest-base
103 +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}-base
104 +
105 +docker tag public.ecr.aws/q9t5s3a7/vllm-release-repo:${BUILDKITE_COMMIT}-rocm vllm/vllm-openai-rocm:${BUILDKITE_COMMIT}
106 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:latest
107 +docker tag vllm/vllm-openai-rocm:${BUILDKITE_COMMIT} vllm/vllm-openai-rocm:v${RELEASE_VERSION}
108 +docker push vllm/vllm-openai-rocm:latest
109 +docker push vllm/vllm-openai-rocm:v${RELEASE_VERSION}
110 +\`\`\`
111 +
112 EOF
docker/Dockerfile.rocm
+14 -1
@@ -227,7 +227,7 @@ RUN if [ "$GIT_REPO_CHECK" != "0" ]; then \
227 # This ensures setuptools_scm sees clean repo state for version detection
228 RUN --mount=type=bind,source=.git,target=vllm/.git \
229 cd vllm \
230 - && pip install setuptools_scm \
230 + && pip install setuptools_scm regex \
231 && VLLM_VERSION=$(python3 -c "import setuptools_scm; print(setuptools_scm.get_version())") \
232 && echo "Detected vLLM version: ${VLLM_VERSION}" \
233 && echo "${VLLM_VERSION}" > /tmp/vllm_version.txt
@@ -342,6 +342,19 @@ RUN mkdir src && mv vllm src/vllm
342 FROM base AS final
343
344 RUN python3 -m pip install --upgrade pip && rm -rf /var/lib/apt/lists/*
345 +
346 +# Clean up sccache from release image (not needed at runtime)
347 +# This removes the binary and wrappers that may have been installed during build
348 +RUN rm -f /usr/bin/sccache || true \
349 + && rm -rf /opt/sccache-wrappers || true
350 +
351 +# Unset sccache environment variables for the release image
352 +# This prevents S3 bucket config from leaking into production images
353 +ENV SCCACHE_BUCKET=
354 +ENV SCCACHE_REGION=
355 +ENV SCCACHE_S3_NO_CREDENTIALS=
356 +ENV SCCACHE_IDLE_TIMEOUT=
357 +
358 # Error related to odd state for numpy 1.20.3 where there is no METADATA etc, but an extra LICENSES_bundled.txt.
359 # Manually remove it so that later steps of numpy upgrade can continue
360 RUN case "$(which python3)" in \
tools/vllm-rocm/generate-rocm-wheels-root-index.sh new
+233
@@ -0,0 +1,233 @@
1 +#!/usr/bin/env bash
2 +# SPDX-License-Identifier: Apache-2.0
3 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4 +#
5 +# Generate S3 PyPI Root Index for Latest Version
6 +#
7 +# Creates a PEP 503 compatible index.html at rocm/ pointing to the latest
8 +# semantic version's packages. This enables users to install with:
9 +# uv pip install vllm --extra-index-url s3://vllm-wheels/rocm
10 +#
11 +# Usage:
12 +# generate-root-index.sh [options]
13 +#
14 +# Options:
15 +# --dry-run Preview changes without uploading
16 +# --version VER Use specific version instead of auto-detecting latest
17 +#
18 +# Environment variables:
19 +# S3_BUCKET - Bucket name (default: vllm-wheels)
20 +# VARIANT - ROCm variant (default: rocm700)
21 +# DRY_RUN - Set to 1 for preview mode (same as --dry-run)
22 +
23 +set -euo pipefail
24 +
25 +# ======== Configuration ========
26 +BUCKET="${S3_BUCKET:-vllm-wheels}"
27 +VARIANT="${VARIANT:-rocm700}"
28 +DRY_RUN="${DRY_RUN:-0}"
29 +FORCE_VERSION=""
30 +
31 +# Parse command line arguments
32 +while [[ $# -gt 0 ]]; do
33 + case $1 in
34 + --dry-run)
35 + DRY_RUN=1
36 + shift
37 + ;;
38 + --version)
39 + FORCE_VERSION="$2"
40 + shift 2
41 + ;;
42 + *)
43 + echo "Unknown option: $1"
44 + exit 1
45 + ;;
46 + esac
47 +done
48 +
49 +# Working directory for generated files
50 +WORK_DIR=$(mktemp -d)
51 +trap 'rm -rf "$WORK_DIR"' EXIT
52 +
53 +echo "========================================"
54 +echo "Generate Root Index for Latest Version"
55 +echo "========================================"
56 +echo "S3 Bucket: $BUCKET"
57 +echo "ROCm Variant: $VARIANT"
58 +echo "Dry Run: $DRY_RUN"
59 +echo "========================================"
60 +echo ""
61 +
62 +# ======== Step 1: Find latest semantic version ========
63 +
64 +echo "Step 1: Finding latest semantic version..."
65 +
66 +# List all directories under rocm/
67 +aws s3api list-objects-v2 \
68 + --bucket "$BUCKET" \
69 + --prefix "rocm/" \
70 + --delimiter "/" \
71 + --query 'CommonPrefixes[].Prefix' \
72 + --output text | tr '\t' '\n' > "$WORK_DIR/all_prefixes.txt"
73 +
74 +# Filter for semantic versions (x.y.z pattern)
75 +grep -oE 'rocm/[0-9]+\.[0-9]+\.[0-9]+/' "$WORK_DIR/all_prefixes.txt" | \
76 + sed 's|rocm/||; s|/||' | \
77 + sort -V > "$WORK_DIR/versions.txt" || true
78 +
79 +if [[ ! -s "$WORK_DIR/versions.txt" ]]; then
80 + echo "ERROR: No semantic versions found under s3://$BUCKET/rocm/"
81 + exit 1
82 +fi
83 +
84 +echo "Found versions:"
85 +cat "$WORK_DIR/versions.txt"
86 +echo ""
87 +
88 +if [[ -n "$FORCE_VERSION" ]]; then
89 + LATEST_VERSION="$FORCE_VERSION"
90 + echo "Using forced version: $LATEST_VERSION"
91 +else
92 + LATEST_VERSION=$(tail -1 "$WORK_DIR/versions.txt")
93 + echo "Latest version (auto-detected): $LATEST_VERSION"
94 +fi
95 +
96 +# Verify the version exists
97 +if ! grep -qx "$LATEST_VERSION" "$WORK_DIR/versions.txt"; then
98 + echo "ERROR: Version $LATEST_VERSION not found in bucket"
99 + exit 1
100 +fi
101 +
102 +# ======== Step 2: List packages from latest version ========
103 +
104 +echo ""
105 +echo "Step 2: Listing packages from rocm/$LATEST_VERSION/$VARIANT/..."
106 +
107 +VERSION_PREFIX="rocm/$LATEST_VERSION/$VARIANT/"
108 +
109 +# List package directories
110 +aws s3api list-objects-v2 \
111 + --bucket "$BUCKET" \
112 + --prefix "$VERSION_PREFIX" \
113 + --delimiter "/" \
114 + --query 'CommonPrefixes[].Prefix' \
115 + --output text | tr '\t' '\n' > "$WORK_DIR/package_prefixes.txt" || true
116 +
117 +if [[ ! -s "$WORK_DIR/package_prefixes.txt" ]]; then
118 + echo "ERROR: No packages found under s3://$BUCKET/$VERSION_PREFIX"
119 + exit 1
120 +fi
121 +
122 +# Extract package names
123 +sed "s|${VERSION_PREFIX}||; s|/||g" "$WORK_DIR/package_prefixes.txt" | \
124 + grep -v '^$' > "$WORK_DIR/packages.txt"
125 +
126 +echo "Found packages:"
127 +cat "$WORK_DIR/packages.txt"
128 +echo ""
129 +
130 +# ======== Step 3: Generate root index.html ========
131 +
132 +echo "Step 3: Generating root index.html..."
133 +
134 +mkdir -p "$WORK_DIR/output"
135 +
136 +{
137 + cat <<'EOF'
138 +<!DOCTYPE html>
139 +<html>
140 +<head>
141 + <meta name="pypi:repository-version" content="1.0">
142 +</head>
143 +<body>
144 +EOF
145 +
146 + while read -r pkg; do
147 + echo " <a href=\"$pkg/\">$pkg</a><br>"
148 + done < "$WORK_DIR/packages.txt"
149 +
150 + cat <<'EOF'
151 +</body>
152 +</html>
153 +EOF
154 +} > "$WORK_DIR/output/index.html"
155 +
156 +echo "Generated root index.html:"
157 +cat "$WORK_DIR/output/index.html"
158 +echo ""
159 +
160 +# ======== Step 4: Copy and adjust package index files ========
161 +
162 +echo "Step 4: Copying and adjusting package index files..."
163 +
164 +while read -r pkg; do
165 + echo "Processing package: $pkg"
166 +
167 + # Download existing index.html from versioned path
168 + SOURCE_INDEX="s3://$BUCKET/$VERSION_PREFIX$pkg/index.html"
169 +
170 + mkdir -p "$WORK_DIR/output/$pkg"
171 +
172 + if aws s3 cp "$SOURCE_INDEX" "$WORK_DIR/output/$pkg/index.html" 2>/dev/null; then
173 + # Adjust relative paths:
174 + # Original: href="../../../{commit}/wheel.whl" (from rocm/0.13.0/rocm710/vllm/)
175 + # New: href="../{commit}/wheel.whl" (from rocm/vllm/)
176 + sed -i 's|href="\.\./\.\./\.\./|href="../|g' "$WORK_DIR/output/$pkg/index.html"
177 + echo " - Downloaded and adjusted: $pkg/index.html"
178 + else
179 + echo " - WARNING: Could not download index for $pkg"
180 + fi
181 +done < "$WORK_DIR/packages.txt"
182 +
183 +echo ""
184 +
185 +# ======== Step 5: Upload to S3 ========
186 +
187 +echo "Step 5: Uploading to s3://$BUCKET/rocm/..."
188 +echo ""
189 +
190 +# List what would be uploaded
191 +echo "Files to upload:"
192 +find "$WORK_DIR/output" -name "*.html" -type f | while read -r file; do
193 + rel_path="${file#$WORK_DIR/output/}"
194 + echo " rocm/$rel_path"
195 +done
196 +echo ""
197 +
198 +if [[ "$DRY_RUN" == "1" ]]; then
199 + echo "DRY RUN - Skipping upload"
200 + echo ""
201 + echo "Preview of generated files:"
202 + echo "----------------------------------------"
203 + echo "rocm/index.html:"
204 + cat "$WORK_DIR/output/index.html"
205 + echo ""
206 + echo "----------------------------------------"
207 + echo "Sample package index (first package):"
208 + FIRST_PKG=$(head -1 "$WORK_DIR/packages.txt")
209 + if [[ -f "$WORK_DIR/output/$FIRST_PKG/index.html" ]]; then
210 + echo "rocm/$FIRST_PKG/index.html:"
211 + cat "$WORK_DIR/output/$FIRST_PKG/index.html"
212 + fi
213 +else
214 + # Upload all generated files
215 + aws s3 cp --recursive "$WORK_DIR/output/" "s3://$BUCKET/rocm/" \
216 + --content-type "text/html"
217 +
218 + echo "Upload complete!"
219 +fi
220 +
221 +# ======== Summary ========
222 +
223 +echo ""
224 +echo "========================================"
225 +echo "Root Index Generation Complete!"
226 +echo "========================================"
227 +echo ""
228 +echo "Latest version: $LATEST_VERSION"
229 +echo "Packages indexed: $(wc -l < "$WORK_DIR/packages.txt")"
230 +echo ""
231 +echo "Install command:"
232 +echo " uv pip install vllm --extra-index-url https://wheels.vllm.ai/rocm/"
233 +echo "========================================"