feat: bundle Python 3.13 for Ubuntu 26.04
This commit is contained in:
parent
1a106d9f22
commit
73762d498f
@ -185,6 +185,9 @@ jobs:
|
||||
grep -Eq 'packages/playwright-browsers/.*/chrome-linux(64)?/chrome$' contents.txt
|
||||
grep -q 'metadata/apt/browser-deb-packages.txt' contents.txt
|
||||
fi
|
||||
if [[ "${{ matrix.distro }}:${{ matrix.version }}" == "ubuntu:26.04" ]]; then
|
||||
grep -Eq 'packages/python/.*/bin/python3.13$' contents.txt
|
||||
fi
|
||||
|
||||
publish-release:
|
||||
needs: test-offline-package
|
||||
|
||||
@ -10,6 +10,8 @@ NPM_RUNTIME_CACHE_DIR="${AI_WORKSPACE_NPM_CACHE_DIR:-/var/cache/ai-workspace/npm
|
||||
PIP_WHEEL_DIR="${ROOT}/packages/pip"
|
||||
PLAYWRIGHT_BROWSER_DIR="${ROOT}/packages/playwright-browsers"
|
||||
PLAYWRIGHT_BROWSER_INSTALL_DIR="${AI_WORKSPACE_PLAYWRIGHT_BROWSER_DIR:-/opt/ai-workspace/playwright-browsers}"
|
||||
PORTABLE_PYTHON_DIR="${ROOT}/packages/python"
|
||||
PORTABLE_PYTHON_INSTALL_DIR="${AI_WORKSPACE_PORTABLE_PYTHON_DIR:-/opt/ai-workspace/python}"
|
||||
STATE_DIR="${AI_WORKSPACE_OFFLINE_STATE_DIR:-/var/lib/ai-workspace/offline}"
|
||||
AI_WORKSPACE_DEPLOYMENT_LOCK_TIMEOUT="${AI_WORKSPACE_DEPLOYMENT_LOCK_TIMEOUT:-1800}"
|
||||
AI_WORKSPACE_APT_LOCK_TIMEOUT="${AI_WORKSPACE_APT_LOCK_TIMEOUT:-900}"
|
||||
@ -256,6 +258,46 @@ install_bundled_playwright_browser() {
|
||||
ln -sfn "${browser_binary}" /usr/local/bin/chromium
|
||||
}
|
||||
|
||||
install_bundled_python_runtime() {
|
||||
local packaged_python installed_python marker seed_checksum
|
||||
packaged_python="$(
|
||||
find -L "${PORTABLE_PYTHON_DIR}" -type f -path '*/bin/python3.13' -perm /111 -print -quit 2>/dev/null || true
|
||||
)"
|
||||
if [ -z "${packaged_python}" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
seed_checksum="$(sha256sum "${ROOT}/metadata/manifest.json" | awk '{print $1}')"
|
||||
marker="${PORTABLE_PYTHON_INSTALL_DIR}/.ai-workspace-seed-sha256"
|
||||
if [ "$(cat "${marker}" 2>/dev/null || true)" != "${seed_checksum}" ]; then
|
||||
info "Installing bundled portable Python runtime"
|
||||
rm -rf "${PORTABLE_PYTHON_INSTALL_DIR}"
|
||||
mkdir -p "${PORTABLE_PYTHON_INSTALL_DIR}"
|
||||
cp -a "${PORTABLE_PYTHON_DIR}/." "${PORTABLE_PYTHON_INSTALL_DIR}/"
|
||||
printf '%s\n' "${seed_checksum}" > "${marker}"
|
||||
else
|
||||
info "Reusing bundled portable Python runtime"
|
||||
fi
|
||||
|
||||
chown -R root:root "${PORTABLE_PYTHON_INSTALL_DIR}"
|
||||
chmod -R a+rX "${PORTABLE_PYTHON_INSTALL_DIR}"
|
||||
installed_python="$(
|
||||
find -L "${PORTABLE_PYTHON_INSTALL_DIR}" -type f -path '*/bin/python3.13' -perm /111 -print -quit
|
||||
)"
|
||||
if [ -z "${installed_python}" ]; then
|
||||
echo "Installed portable Python executable is missing." >&2
|
||||
exit 1
|
||||
fi
|
||||
ln -sfn "${installed_python}" /usr/local/bin/ai-workspace-python
|
||||
cat > /usr/local/bin/ai-workspace-pip <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
exec /usr/local/bin/ai-workspace-python -m pip "$@"
|
||||
EOF
|
||||
chmod 0755 /usr/local/bin/ai-workspace-pip
|
||||
export LITELLM_PYTHON_EXECUTABLE=/usr/local/bin/ai-workspace-python
|
||||
export LITELLM_PIP_EXECUTABLE=/usr/local/bin/ai-workspace-pip
|
||||
}
|
||||
|
||||
load_container_images() {
|
||||
if [ ! -d "${IMAGE_DIR}" ] || ! compgen -G "${IMAGE_DIR}/*.tar" >/dev/null; then
|
||||
return
|
||||
@ -372,6 +414,7 @@ main() {
|
||||
configure_local_git_sources
|
||||
install_bundled_binaries
|
||||
install_bundled_playwright_browser
|
||||
install_bundled_python_runtime
|
||||
load_container_images
|
||||
configure_language_package_caches
|
||||
run_bootstrap
|
||||
|
||||
@ -29,6 +29,8 @@ POSTGRES_IMAGE="${POSTGRES_IMAGE:-postgres:17.7}"
|
||||
OPENCLAW_VERSION="${OPENCLAW_VERSION:-2026.6.6}"
|
||||
PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION:-1.60.0}"
|
||||
GOOGLE_CHROME_VERSION="${GOOGLE_CHROME_VERSION:-149.0.7827.114-1}"
|
||||
UV_VERSION="${UV_VERSION:-0.11.21}"
|
||||
PORTABLE_PYTHON_VERSION="${PORTABLE_PYTHON_VERSION:-3.13.14}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
@ -81,8 +83,9 @@ download_apt_packages() {
|
||||
local apt_dir="${WORKDIR}/packages/apt"
|
||||
local apt_lists="${WORKDIR}/metadata/apt"
|
||||
local wheel_dir="${WORKDIR}/packages/pip"
|
||||
local python_dir="${WORKDIR}/packages/python"
|
||||
|
||||
mkdir -p "${apt_dir}" "${apt_lists}" "${wheel_dir}"
|
||||
mkdir -p "${apt_dir}" "${apt_lists}" "${wheel_dir}" "${python_dir}"
|
||||
|
||||
docker run --rm --platform "${platform}" \
|
||||
-e DISTRO_ID="${DISTRO_ID}" \
|
||||
@ -92,9 +95,12 @@ download_apt_packages() {
|
||||
-e NODEJS_24_VERSION="${NODEJS_24_VERSION}" \
|
||||
-e GOOGLE_CHROME_VERSION="${GOOGLE_CHROME_VERSION}" \
|
||||
-e LITELLM_DEBIAN_11_VERSION="${LITELLM_DEBIAN_11_VERSION}" \
|
||||
-e UV_VERSION="${UV_VERSION}" \
|
||||
-e PORTABLE_PYTHON_VERSION="${PORTABLE_PYTHON_VERSION}" \
|
||||
-v "${apt_dir}:/offline-apt" \
|
||||
-v "${apt_lists}:/offline-meta" \
|
||||
-v "${wheel_dir}:/offline-pip" \
|
||||
-v "${python_dir}:/offline-python" \
|
||||
-v "${WORKDIR}/repos/litellm:/litellm-src:ro" \
|
||||
"${image}" \
|
||||
bash -lc "$(cat <<'CONTAINER'
|
||||
@ -229,7 +235,27 @@ find . -maxdepth 1 -name '*.deb' -printf '%f\n' | sort > /offline-meta/deb-files
|
||||
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential git libpq-dev python3 python3-dev python3-pip python3-venv
|
||||
python3 -m venv /tmp/ai-workspace-wheel-builder
|
||||
python_bin=python3
|
||||
if [ "${DISTRO_ID}:${DISTRO_VERSION}" = "ubuntu:26.04" ]; then
|
||||
case "$(dpkg --print-architecture)" in
|
||||
amd64) uv_arch=x86_64 ;;
|
||||
arm64) uv_arch=aarch64 ;;
|
||||
*) echo "Unsupported uv architecture: $(dpkg --print-architecture)" >&2; exit 1 ;;
|
||||
esac
|
||||
curl -fsSL \
|
||||
"https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-${uv_arch}-unknown-linux-gnu.tar.gz" \
|
||||
-o /tmp/uv.tar.gz
|
||||
tar -xzf /tmp/uv.tar.gz -C /tmp
|
||||
install -m 0755 "$(find /tmp -type f -path '*/uv-*/uv' -print -quit)" /usr/local/bin/uv
|
||||
uv python install "${PORTABLE_PYTHON_VERSION}" --install-dir /offline-python --no-bin
|
||||
python_bin="$(find -L /offline-python -type f -path '*/bin/python3.13' -perm /111 -print -quit)"
|
||||
if [ -z "${python_bin}" ]; then
|
||||
echo "Portable Python ${PORTABLE_PYTHON_VERSION} was not installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${python_bin}" -m ensurepip --upgrade
|
||||
fi
|
||||
"${python_bin}" -m venv /tmp/ai-workspace-wheel-builder
|
||||
/tmp/ai-workspace-wheel-builder/bin/pip install --upgrade pip setuptools wheel
|
||||
litellm_package_spec="/litellm-src[proxy]"
|
||||
if [ "${DISTRO_ID}:${DISTRO_VERSION}" = "debian:11" ]; then
|
||||
@ -383,6 +409,8 @@ EOF
|
||||
"playwright": "${PLAYWRIGHT_VERSION}",
|
||||
"googleChrome": "${GOOGLE_CHROME_VERSION}",
|
||||
"litellmDebian11": "${LITELLM_DEBIAN_11_VERSION}",
|
||||
"uv": "${UV_VERSION}",
|
||||
"portablePython": "${PORTABLE_PYTHON_VERSION}",
|
||||
"postgresImage": "${POSTGRES_IMAGE}"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user