Skip to content

Commit 0a74279

Browse files
feat(ppc64le) codeserver workbench image build on power (#2317)
Signed-off-by: Md. Shafi Hussain <[email protected]> Co-authored-by: Md. Shafi Hussain <[email protected]>
1 parent a788979 commit 0a74279

File tree

5 files changed

+212
-9
lines changed

5 files changed

+212
-9
lines changed

.tekton/odh-workbench-codeserver-datascience-cpu-py312-ubi9-pull-request.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ spec:
3636
- name: build-platforms
3737
value:
3838
- linux/x86_64
39+
- linux/ppc64le
3940
- name: dockerfile
4041
value: codeserver/ubi9-python-3.12/Dockerfile.cpu
4142
- name: path-context

codeserver/ubi9-python-3.12/Dockerfile.cpu

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,59 @@
33
#########################
44
ARG BASE_IMAGE
55

6+
####################
7+
# rpm-base #
8+
####################
9+
# e.g., registry.access.redhat.com/ubi9/python-312:latest
10+
FROM ${BASE_IMAGE} AS rpm-base
11+
12+
USER root
13+
WORKDIR /root
14+
15+
ENV HOME=/root
16+
17+
ARG CODESERVER_SOURCE_CODE=codeserver/ubi9-python-3.12
18+
19+
ARG NODE_VERSION=20
20+
21+
ARG CODESERVER_VERSION=v4.98.0
22+
23+
COPY ${CODESERVER_SOURCE_CODE}/get_code_server_rpm.sh .
24+
25+
# create dummy file to ensure this stage is awaited before installing rpm
26+
RUN ./get_code_server_rpm.sh && touch /tmp/control
27+
28+
#######################
29+
# wheel caching stage #
30+
#######################
31+
FROM registry.access.redhat.com/ubi9/python-312:latest AS whl-cache
32+
33+
USER root
34+
WORKDIR /root
35+
36+
ENV HOME=/root
37+
38+
ARG CODESERVER_SOURCE_CODE=codeserver/ubi9-python-3.12
39+
40+
# copy requirements and scripts
41+
COPY ${CODESERVER_SOURCE_CODE}/pylock.toml ./
42+
COPY ${CODESERVER_SOURCE_CODE}/devel_env_setup.sh ./
43+
44+
# This stage installs (builds) all the packages needed and caches it in uv-cache
45+
# Important: Since HOME & USER for the python-312 has been changed,
46+
# we need to ensure the same cache directory is mounted in
47+
# the final stage with the necessary permissions to consume from cache
48+
RUN --mount=type=cache,target=/root/.cache/uv \
49+
pip install --no-cache uv && \
50+
# the devel script is ppc64le specific - sets up build-time dependencies
51+
source ./devel_env_setup.sh && \
52+
# This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
53+
# we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
54+
uv pip install --strict --no-deps --refresh --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml
55+
56+
# dummy file to make image build wait for this stage
57+
RUN touch /tmp/control
58+
659
####################
760
# cpu-base #
861
####################
@@ -21,6 +74,15 @@ RUN dnf -y upgrade --refresh --best --nodocs --noplugins --setopt=install_weak_d
2174
# Install useful OS packages
2275
RUN dnf install -y mesa-libGL skopeo && dnf clean all && rm -rf /var/cache/yum
2376

77+
# (ARCH-ppc64le): since wheels are compiled from source, we need shared libs available at runtime
78+
RUN --mount=type=cache,from=whl-cache,source=/root/OpenBLAS,target=/OpenBlas,rw \
79+
bash -c ' \
80+
if [[ $(uname -m) == "ppc64le" ]]; then \
81+
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm; \
82+
dnf install -y lcms2 libraqm libimagequant openjpeg2; \
83+
PREFIX=/usr/ make install -C /OpenBlas; \
84+
fi '
85+
2486
# Other apps and tools installed as default user
2587
USER 1001
2688

@@ -62,8 +124,13 @@ WORKDIR /opt/app-root/bin
62124
# Install useful OS packages
63125
RUN dnf install -y jq git-lfs libsndfile && dnf clean all && rm -rf /var/cache/yum
64126

127+
# wait for rpm-base stage (rpm builds for ppc64le)
128+
COPY --from=rpm-base /tmp/control /dev/null
129+
65130
# Install code-server
66-
RUN dnf install -y "https://github.com/coder/code-server/releases/download/${CODESERVER_VERSION}/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm" && \
131+
# Note: Use cache mounts, bind mounts fail on konflux
132+
RUN --mount=type=cache,from=rpm-base,source=/tmp/,target=/code-server-rpm/,rw \
133+
dnf install -y "/code-server-rpm/code-server-${CODESERVER_VERSION/v/}-${TARGETARCH}.rpm" && \
67134
dnf -y clean all --enablerepo='*'
68135

69136
COPY --chown=1001:0 ${CODESERVER_SOURCE_CODE}/utils utils/
@@ -142,18 +209,28 @@ ENV SHELL=/bin/bash
142209

143210
ENV PYTHONPATH=/opt/app-root/bin/python3
144211

145-
USER 1001
146-
147212
# Install useful packages from requirements.txt
148213
COPY ${CODESERVER_SOURCE_CODE}/pylock.toml ./
149214

215+
# wait for whl-cache stage (builds uv cache)
216+
COPY --from=whl-cache /tmp/control /dev/null
217+
150218
# Install packages and cleanup
151-
RUN echo "Installing softwares and packages" && \
152-
# This may have to download and compile some dependencies, and as we don't lock requirements from `build-system.requires`,
153-
# we often don't know the correct hashes and `--require-hashes` would therefore fail on non amd64, where building is common.
154-
uv pip install --strict --no-deps --no-cache --no-config --no-progress --verify-hashes --compile-bytecode --index-strategy=unsafe-best-match --requirements=./pylock.toml && \
155-
# Fix permissions to support pip in Openshift environments \
156-
chmod -R g+w /opt/app-root/lib/python3.12/site-packages && \
219+
# install packages as USER 0 (this will allow us to consume uv cache)
220+
RUN --mount=type=cache,target=/root/.cache/uv \
221+
echo "Installing softwares and packages" && \
222+
# we can ensure wheels are consumed from the cache only by restricting internet access for uv install with '--offline' flag
223+
uv pip install --offline --cache-dir /root/.cache/uv --requirements=./pylock.toml && \
224+
# Note: debugpy wheel availabe on pypi (in uv cache) is none-any but bundles amd64.so files
225+
# Build debugpy from source instead
226+
uv pip install --no-cache git+https://github.com/microsoft/debugpy.git@v$(grep -A1 '\"debugpy\"' ./pylock.toml | grep -Eo '\b[0-9\.]+\b') && \
227+
# change ownership to default user (all packages were installed as root and has root:root ownership \
228+
chown -R 1001:0 /opt/app-root/lib
229+
230+
USER 1001
231+
232+
# Fix permissions to support pip in Openshift environments
233+
RUN chmod -R g+w /opt/app-root/lib/python3.12/site-packages && \
157234
fix-permissions /opt/app-root -P
158235

159236
WORKDIR /opt/app-root/src
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
set -eoux pipefail
3+
4+
#####################################################################################################
5+
# This script is expected to be run on ppc64le hosts as `root` #
6+
# It installs the required build-time dependencies for python wheels #
7+
# OpenBlas is built from source (instead of distro provided) with recommended flags for performance #
8+
#####################################################################################################
9+
10+
if [[ $(uname -m) == "ppc64le" ]]; then
11+
# install development packages
12+
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
13+
dnf install -y cmake gcc-toolset-13 fribidi-devel lcms2-devel \
14+
libimagequant-devel libraqm-devel openjpeg2-devel tcl-devel tk-devel
15+
16+
# install rust
17+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
18+
19+
source /opt/rh/gcc-toolset-13/enable
20+
source "$HOME/.cargo/env"
21+
22+
export MAX_JOBS=${MAX_JOBS:-$(nproc)}
23+
export OPENBLAS_VERSION=${OPENBLAS_VERSION:-0.3.30}
24+
25+
# Install OpenBlas
26+
# IMPORTANT: Ensure Openblas is installed in the final image
27+
curl -L https://github.com/OpenMathLib/OpenBLAS/releases/download/v${OPENBLAS_VERSION}/OpenBLAS-${OPENBLAS_VERSION}.tar.gz | tar xz
28+
# rename directory for mounting (without knowing version numbers) in multistage builds
29+
mv OpenBLAS-${OPENBLAS_VERSION}/ OpenBLAS/
30+
cd OpenBLAS/
31+
make -j${MAX_JOBS} TARGET=POWER9 BINARY=64 USE_OPENMP=1 USE_THREAD=1 NUM_THREADS=120 DYNAMIC_ARCH=1 INTERFACE64=0
32+
make install
33+
cd ..
34+
35+
# set path for openblas
36+
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/OpenBLAS/lib/
37+
export PKG_CONFIG_PATH=$(find / -type d -name "pkgconfig" 2>/dev/null | tr '\n' ':')
38+
export CMAKE_ARGS="-DPython3_EXECUTABLE=python"
39+
else
40+
# only for mounting on non-ppc64le
41+
mkdir -p /root/OpenBLAS/
42+
fi
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/bin/bash
2+
set -euxo pipefail
3+
4+
##############################################################################
5+
# This script is expected to be run as `root` #
6+
# It builds code-server rpm for `ppc64le` #
7+
# For other architectures, the rpm is downloaded from the available releases #
8+
##############################################################################
9+
10+
11+
# Mapping of `uname -m` values to equivalent GOARCH values
12+
declare -A UNAME_TO_GOARCH
13+
UNAME_TO_GOARCH["x86_64"]="amd64"
14+
UNAME_TO_GOARCH["aarch64"]="arm64"
15+
UNAME_TO_GOARCH["ppc64le"]="ppc64le"
16+
UNAME_TO_GOARCH["s390x"]="s390x"
17+
18+
ARCH="${UNAME_TO_GOARCH[$(uname -m)]}"
19+
20+
if [[ "$ARCH" == "ppc64le" ]]; then
21+
22+
export MAX_JOBS=${MAX_JOBS:-$(nproc)}
23+
export NODE_VERSION=${NODE_VERSION:-20}
24+
export CODESERVER_VERSION=${CODESERVER_VERSION:-v4.98.0}
25+
26+
export NVM_DIR=/root/.nvm VENV=/opt/.venv
27+
export PATH=${VENV}/bin:$PATH
28+
29+
export ELECTRON_SKIP_BINARY_DOWNLOAD=1 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
30+
31+
# install build dependencies
32+
# dnf install -y \
33+
# git gcc-toolset-13 automake libtool rsync krb5-devel libX11-devel gettext jq patch
34+
dnf install -y jq libtool gcc-toolset-13
35+
36+
. /opt/rh/gcc-toolset-13/enable
37+
38+
# build libxkbfile
39+
git clone https://gitlab.freedesktop.org/xorg/util/macros.git
40+
cd macros/
41+
./autogen.sh && make install -j ${MAX_JOBS}
42+
export ACLOCAL_PATH=/usr/local/share/aclocal/
43+
cd .. && rm -rf macros
44+
git clone https://gitlab.freedesktop.org/xorg/lib/libxkbfile.git
45+
cd libxkbfile/
46+
./autogen.sh && make install -j ${MAX_JOBS}
47+
cd .. && rm -rf libxkbfile
48+
export PKG_CONFIG_PATH=$(find / -type d -name "pkgconfig" 2>/dev/null | tr '\n' ':')
49+
50+
# install nfpm to build rpm
51+
NFPM_VERSION=$(curl -s "https://api.github.com/repos/goreleaser/nfpm/releases/latest" | jq -r '.tag_name') \
52+
&& dnf install -y https://github.com/goreleaser/nfpm/releases/download/${NFPM_VERSION}/nfpm-${NFPM_VERSION:1}-1.$(uname -m).rpm
53+
54+
# install node
55+
NVM_VERSION=$(curl -s "https://api.github.com/repos/nvm-sh/nvm/releases/latest" | jq -r '.tag_name') \
56+
&& curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash \
57+
&& source ${NVM_DIR}/nvm.sh && nvm install ${NODE_VERSION}
58+
59+
# build codeserver
60+
git clone https://github.com/coder/code-server.git
61+
cd code-server
62+
git checkout ${CODESERVER_VERSION}
63+
git submodule update --init
64+
source ${NVM_DIR}/nvm.sh
65+
while IFS= read -r src_patch; do echo "patches/$src_patch"; patch -p1 < "patches/$src_patch"; done < patches/series
66+
nvm use ${NODE_VERSION}
67+
npm install
68+
npm run build
69+
VERSION=${CODESERVER_VERSION/v/} npm run build:vscode
70+
npm run release
71+
npm run release:standalone
72+
73+
# build codeserver rpm
74+
VERSION=${CODESERVER_VERSION/v/} npm run package
75+
cp release-packages/code-server-${CODESERVER_VERSION/v/}-ppc64le.rpm /tmp/
76+
77+
else
78+
79+
# download RPM for other architectures
80+
curl -L "https://github.com/coder/code-server/releases/download/${CODESERVER_VERSION}/code-server-${CODESERVER_VERSION/v/}-${ARCH}.rpm" -o /tmp/code-server-${CODESERVER_VERSION/v/}-${ARCH}.rpm
81+
82+
fi

scripts/generate_pull_request_pipelineruns.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def transform_build_pipeline_to_pr_pipeline(push_pipeline_path: pathlib.Path):
142142
build_platforms.extend(["linux/arm64"])
143143

144144
if component in [
145+
"odh-workbench-codeserver-datascience-cpu-py312-ubi9",
145146
"odh-workbench-jupyter-minimal-cpu-py312-ubi9",
146147
"odh-pipeline-runtime-minimal-cpu-py312-ubi9",
147148
"odh-pipeline-runtime-datascience-cpu-py312-ubi9",

0 commit comments

Comments
 (0)