#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PYTHON_BIN="${PYTHON_BIN:-python3}" REQUIREMENTS_FILE="${REQUIREMENTS_FILE:-${SCRIPT_DIR}/offline-runtime-requirements.txt}" WHEELHOUSE_DIR="${WHEELHOUSE_DIR:-${SCRIPT_DIR}/wheelhouse}" PIP_INDEX_URL="${PIP_INDEX_URL:-https://pypi.org/simple}" # The supplied backend image is CPython 3.12 on Debian x86_64. These values can # be overridden when building an offline bundle for a different image/CPU. TARGET_PLATFORM="${TARGET_PLATFORM:-manylinux2014_x86_64}" TARGET_PYTHON_VERSION="${TARGET_PYTHON_VERSION:-312}" TARGET_IMPLEMENTATION="${TARGET_IMPLEMENTATION:-cp}" TARGET_ABI="${TARGET_ABI:-cp312}" die() { echo "ERROR: $*" >&2 exit 1 } require_cmd() { command -v "$1" >/dev/null 2>&1 || die "command not found: $1" } require_wheel() { local pattern="$1" compgen -G "${WHEELHOUSE_DIR}/${pattern}" >/dev/null || die "wheel not downloaded: ${pattern}" } require_cmd "${PYTHON_BIN}" require_cmd sha256sum [ -f "${REQUIREMENTS_FILE}" ] || die "requirements file not found: ${REQUIREMENTS_FILE}" "${PYTHON_BIN}" -m pip --version >/dev/null 2>&1 || die "pip is not available for ${PYTHON_BIN}" mkdir -p "${WHEELHOUSE_DIR}" download_args=( download --dest "${WHEELHOUSE_DIR}" --only-binary=:all: --platform "${TARGET_PLATFORM}" --python-version "${TARGET_PYTHON_VERSION}" --implementation "${TARGET_IMPLEMENTATION}" --abi "${TARGET_ABI}" ) echo "Downloading Linux/Python runtime wheels" echo " requirements: ${REQUIREMENTS_FILE}" echo " destination: ${WHEELHOUSE_DIR}" echo " platform: ${TARGET_PLATFORM}" echo " Python/ABI: ${TARGET_PYTHON_VERSION}/${TARGET_ABI}" "${PYTHON_BIN}" -m pip "${download_args[@]}" \ --index-url "${PIP_INDEX_URL}" \ --requirement "${REQUIREMENTS_FILE}" require_wheel 'croniter-6.2.2-*.whl' require_wheel 'hindsight_client-0.6.2-*.whl' require_wheel 'redis-5.2.1-*.whl' require_wheel 'aiomysql-0.3.2-*.whl' require_wheel 'pymysql-1.2.0-*.whl' require_wheel 'sqlalchemy-2.0.51-*.whl' require_wheel 'greenlet-3.2.5-*.whl' # Resolve the same requirements a second time using only wheelhouse. This # catches a missing transitive dependency before the bundle reaches offline. verify_dir="$(mktemp -d)" cleanup() { if [ -n "${verify_dir:-}" ] && [ -d "${verify_dir}" ]; then rm -rf -- "${verify_dir}" fi } trap cleanup EXIT verify_args=( download --dest "${verify_dir}" --no-index --find-links "${WHEELHOUSE_DIR}" --only-binary=:all: --platform "${TARGET_PLATFORM}" --python-version "${TARGET_PYTHON_VERSION}" --implementation "${TARGET_IMPLEMENTATION}" --abi "${TARGET_ABI}" --requirement "${REQUIREMENTS_FILE}" ) "${PYTHON_BIN}" -m pip "${verify_args[@]}" >/dev/null shopt -s nullglob wheels=("${WHEELHOUSE_DIR}"/*.whl) [ "${#wheels[@]}" -gt 0 ] || die "wheelhouse is empty: ${WHEELHOUSE_DIR}" ( cd "${WHEELHOUSE_DIR}" sha256sum -- *.whl | LC_ALL=C sort > SHA256SUMS ) echo echo "Wheelhouse is complete for the pinned runtime requirements." echo " wheel count: ${#wheels[@]}" echo " checksums: ${WHEELHOUSE_DIR}/SHA256SUMS" echo "Copy the wheelhouse directory with the deployment bundle."