Skip to content

Commit 8a4bdf5

Browse files
Migrate wheel builds to wanda (x86_64)
This migrates ray wheel builds from CLI-based approach to wanda-based container builds for x86_64. Changes: - Add ray-wheel.wanda.yaml and Dockerfile for wheel builds - Update build.rayci.yml wheel steps to use wanda - Add wheel upload steps that extract from wanda cache Topic: ray-wheel Labels: draft Signed-off-by: andrew <[email protected]>
1 parent 9700991 commit 8a4bdf5

File tree

6 files changed

+234
-7
lines changed

6 files changed

+234
-7
lines changed

.buildkite/build.rayci.yml

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,46 @@ steps:
3535
HOSTTYPE: "x86_64"
3636
MANYLINUX_VERSION: "260103.868e54c"
3737

38-
- label: ":tapioca: build: wheel {{matrix}} (x86_64)"
39-
key: linux_wheels
38+
- name: ray-wheel-build
39+
label: "wanda: wheel py{{matrix}} (x86_64)"
40+
wanda: ci/docker/ray-wheel.wanda.yaml
41+
matrix:
42+
- "3.10"
43+
- "3.11"
44+
- "3.12"
45+
- "3.13"
46+
env:
47+
PYTHON_VERSION: "{{matrix}}"
48+
ARCH_SUFFIX: ""
49+
HOSTTYPE: "x86_64"
50+
MANYLINUX_VERSION: "260103.868e54c"
4051
tags:
4152
- release_wheels
4253
- linux_wheels
4354
- oss
44-
instance_type: large
55+
depends_on:
56+
- ray-core-build
57+
- ray-java-build
58+
- ray-dashboard-build
59+
60+
# Upload wheels to S3
61+
- label: ":s3: upload: wheel py{{matrix}} (x86_64)"
62+
key: linux_wheels_upload
63+
instance_type: small
4564
commands:
46-
- bazel run //ci/ray_ci:build_in_docker -- wheel --python-version {{matrix}} --architecture x86_64 --upload
65+
- ./ci/build/extract_wanda_wheels.sh ray-wheel-py{{matrix}}
66+
- ./ci/build/copy_build_artifacts.sh wheel
4767
matrix:
4868
- "3.10"
4969
- "3.11"
5070
- "3.12"
5171
- "3.13"
5272
depends_on:
53-
- manylinux-x86_64
54-
- forge
73+
- ray-wheel-build
74+
tags:
75+
- release_wheels
76+
- skip-on-premerge
77+
- oss
5578

5679
- label: ":tapioca: build: jar"
5780
key: java_wheels

.rayciversion

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.21.0
1+
0.22.0

ci/build/extract_wanda_wheels.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
set -exuo pipefail
4+
5+
# Extract wheels from a Wanda-cached image.
6+
#
7+
# Usage: ./ci/build/extract_wanda_wheels.sh <wanda_image_name>
8+
#
9+
# Example:
10+
# ./ci/build/extract_wanda_wheels.sh ray-wheel-py3.10
11+
#
12+
# The script will:
13+
# 1. Pull the wanda image from ECR cache
14+
# 2. Extract .whl files from the image
15+
# 3. Move them to .whl/ directory
16+
17+
WANDA_IMAGE_NAME=${1:?Usage: $0 <wanda_image_name>}
18+
19+
# Construct full image tag from environment
20+
WANDA_IMAGE="${RAYCI_WORK_REPO}:${RAYCI_BUILD_ID}-${WANDA_IMAGE_NAME}"
21+
22+
echo "Extracting wheels from: ${WANDA_IMAGE}"
23+
24+
# Create container from wanda image (without running it)
25+
container_id=$(docker create "${WANDA_IMAGE}")
26+
27+
# Extract wheels to temp directory
28+
mkdir -p /tmp/wheels
29+
docker cp "${container_id}":/ /tmp/wheels/
30+
31+
# Clean up container
32+
docker rm "${container_id}"
33+
34+
# Move wheels to .whl directory
35+
mkdir -p .whl
36+
mv /tmp/wheels/*.whl .whl/
37+
38+
echo "Extracted wheels:"
39+
ls -la .whl/

ci/docker/ray-wheel.Dockerfile

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# syntax=docker/dockerfile:1.3-labs
2+
#
3+
# Ray Wheel Builder (Unified)
4+
# ===========================
5+
# Builds manylinux2014-compatible wheels using pre-built C++ artifacts from wanda cache.
6+
#
7+
# Build Types:
8+
# - ray wheel: WHEEL_TYPE=ray (default) - Standard Ray Python wheel
9+
# - ray-cpp wheel: WHEEL_TYPE=cpp - Ray C++ API wheel
10+
#
11+
# GLIBC Compatibility:
12+
# --------------------
13+
# manylinux2014 requires GLIBC <= 2.17 for broad Linux compatibility.
14+
# The pre-built _raylet.so is compiled inside manylinux2014 with GLIBC 2.17.
15+
#
16+
17+
ARG RAY_CORE_IMAGE
18+
ARG RAY_CPP_CORE_IMAGE=scratch
19+
ARG RAY_JAVA_IMAGE
20+
ARG RAY_DASHBOARD_IMAGE
21+
ARG MANYLINUX_VERSION
22+
ARG HOSTTYPE
23+
24+
FROM ${RAY_CORE_IMAGE} AS ray-core
25+
FROM ${RAY_CPP_CORE_IMAGE} AS ray-cpp-core
26+
FROM ${RAY_JAVA_IMAGE} AS ray-java
27+
FROM ${RAY_DASHBOARD_IMAGE} AS ray-dashboard
28+
29+
# Main build stage - manylinux2014 provides GLIBC 2.17
30+
FROM rayproject/manylinux2014:${MANYLINUX_VERSION}-jdk-${HOSTTYPE} AS builder
31+
32+
ARG PYTHON_VERSION=3.10
33+
ARG BUILDKITE_COMMIT
34+
ARG WHEEL_TYPE=ray
35+
36+
# Set environment variables for the build
37+
# - BUILDKITE_COMMIT: Used for ray.__commit__. Defaults to "unknown" for local builds.
38+
# - SKIP_BAZEL_BUILD=1: Skip bazel build, use pre-built artifacts from ray-core/ray-java/ray-dashboard
39+
# - RAY_DISABLE_EXTRA_CPP: 1 for ray wheel only, 0 for ray-cpp wheel
40+
# - WHEEL_TYPE: "ray" or "cpp" - determines which wheel to build
41+
ENV BUILDKITE_COMMIT=${BUILDKITE_COMMIT:-unknown} \
42+
PYTHON_VERSION=${PYTHON_VERSION} \
43+
SKIP_BAZEL_BUILD=1 \
44+
WHEEL_TYPE=${WHEEL_TYPE}
45+
46+
WORKDIR /home/forge/ray
47+
48+
# Copy artifacts from all stages
49+
COPY --from=ray-core /ray_pkg.zip /tmp/
50+
COPY --from=ray-core /ray_py_proto.zip /tmp/
51+
COPY --from=ray-java /ray_java_pkg.zip /tmp/
52+
COPY --from=ray-dashboard /dashboard.tar.gz /tmp/
53+
54+
# Source files needed for wheel build
55+
COPY --chown=2000:100 ci/build/build-manylinux-wheel.sh ci/build/
56+
COPY --chown=2000:100 README.rst pyproject.toml ./
57+
COPY --chown=2000:100 rllib/ rllib/
58+
COPY --chown=2000:100 python/ python/
59+
60+
USER forge
61+
# Note: ray-cpp-core may be "scratch" (empty) for ray-only builds
62+
RUN --mount=from=ray-cpp-core,source=/,target=/ray-cpp-core,ro \
63+
<<'EOF'
64+
#!/bin/bash
65+
set -euo pipefail
66+
67+
PY_VERSION="${PYTHON_VERSION//./}"
68+
PY_BIN="cp${PY_VERSION}-cp${PY_VERSION}"
69+
70+
# Verify required artifacts exist before unpacking
71+
for f in /tmp/ray_pkg.zip /tmp/ray_py_proto.zip /tmp/ray_java_pkg.zip /tmp/dashboard.tar.gz; do
72+
[[ -f "$f" ]] || { echo "ERROR: missing artifact: $f"; exit 1; }
73+
done
74+
75+
# Clean extraction dirs to avoid stale leftovers
76+
rm -rf /tmp/ray_pkg /tmp/ray_java_pkg /tmp/ray_cpp_pkg
77+
mkdir -p /tmp/ray_pkg /tmp/ray_java_pkg
78+
79+
# Unpack common pre-built artifacts
80+
unzip -o /tmp/ray_pkg.zip -d /tmp/ray_pkg
81+
unzip -o /tmp/ray_py_proto.zip -d python/
82+
unzip -o /tmp/ray_java_pkg.zip -d /tmp/ray_java_pkg
83+
mkdir -p python/ray/dashboard/client/build
84+
tar -xzf /tmp/dashboard.tar.gz -C python/ray/dashboard/client/build/
85+
86+
# C++ core artifacts
87+
cp -r /tmp/ray_pkg/ray/* python/ray/
88+
89+
# Java JARs
90+
cp -r /tmp/ray_java_pkg/ray/* python/ray/
91+
92+
# Handle wheel type specific setup
93+
if [[ "$WHEEL_TYPE" == "cpp" ]]; then
94+
# C++ API artifacts (headers, libs, examples)
95+
if [[ -f /ray-cpp-core/ray_cpp_pkg.zip ]]; then
96+
mkdir -p /tmp/ray_cpp_pkg
97+
unzip -o /ray-cpp-core/ray_cpp_pkg.zip -d /tmp/ray_cpp_pkg
98+
cp -r /tmp/ray_cpp_pkg/ray/cpp python/ray/
99+
else
100+
echo "ERROR: ray_cpp_pkg.zip not found for cpp wheel build"
101+
exit 1
102+
fi
103+
export RAY_DISABLE_EXTRA_CPP=0
104+
else
105+
export RAY_DISABLE_EXTRA_CPP=1
106+
fi
107+
108+
# Build wheels
109+
./ci/build/build-manylinux-wheel.sh "$PY_BIN"
110+
111+
# Filter output based on wheel type
112+
if [[ "$WHEEL_TYPE" == "cpp" ]]; then
113+
# Keep only ray-cpp wheel
114+
rm -f .whl/ray-[0-9]*.whl
115+
fi
116+
117+
# Sanity check: ensure wheels exist
118+
shopt -s nullglob
119+
wheels=(.whl/*.whl)
120+
if (( ${#wheels[@]} == 0 )); then
121+
echo "ERROR: No wheels produced in .whl/"
122+
ls -la .whl || true
123+
exit 1
124+
fi
125+
126+
EOF
127+
128+
FROM scratch
129+
COPY --from=builder /home/forge/ray/.whl/*.whl /

ci/docker/ray-wheel.wanda.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: "ray-wheel-py$PYTHON_VERSION$ARCH_SUFFIX"
2+
disable_caching: true
3+
froms:
4+
- "rayproject/manylinux2014:$MANYLINUX_VERSION-jdk-$HOSTTYPE"
5+
- "cr.ray.io/rayproject/ray-core-py$PYTHON_VERSION$ARCH_SUFFIX" # C++ binaries (ray_pkg.zip)
6+
- "cr.ray.io/rayproject/ray-java-build$ARCH_SUFFIX" # Java JARs
7+
- "cr.ray.io/rayproject/ray-dashboard" # Dashboard
8+
dockerfile: ci/docker/ray-wheel.Dockerfile
9+
srcs:
10+
- pyproject.toml
11+
- README.rst
12+
- ci/build/build-manylinux-wheel.sh
13+
- python/
14+
- rllib/
15+
build_args:
16+
- PYTHON_VERSION
17+
- MANYLINUX_VERSION
18+
- HOSTTYPE
19+
- BUILDKITE_COMMIT
20+
- ARCH_SUFFIX
21+
- WHEEL_TYPE=ray
22+
- RAY_CORE_IMAGE=cr.ray.io/rayproject/ray-core-py$PYTHON_VERSION$ARCH_SUFFIX
23+
- RAY_JAVA_IMAGE=cr.ray.io/rayproject/ray-java-build$ARCH_SUFFIX
24+
- RAY_DASHBOARD_IMAGE=cr.ray.io/rayproject/ray-dashboard

ci/pipeline/test_rules.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
# file # File to match
1111
# dir/*.py # Pattern to match, using fnmatch, matches dir/a.py dir/dir/b.py or dir/.py
1212
# @ tag1 tag2 tag3 # Tags to emit for a rule. A rule without tags is a skipping rule.
13+
# \fallthrough # Tags are always included, matching continues to next rule
14+
# \default # Rule matches any file (catch-all)
1315
#
1416
# ; # Semicolon to separate rules
1517

@@ -20,6 +22,10 @@
2022
! linux_wheels macos_wheels docker doc python_dependencies tools
2123
! release_tests spark_on_ray
2224

25+
\fallthrough
26+
@ always lint
27+
;
28+
2329
python/ray/air/
2430
@ ml train tune data linux_wheels
2531
;
@@ -257,3 +263,9 @@ setup_hooks.sh
257263
.fossa.yml
258264
# pass
259265
;
266+
267+
\default
268+
@ ml tune train data serve
269+
@ core_cpp cpp java python doc
270+
@ linux_wheels macos_wheels dashboard tools release_tests
271+
;

0 commit comments

Comments
 (0)