#!/usr/bin/env bash # Build the meshbay-common package: shared venv with ALL Python dependencies. # # Usage: ./build-common.sh [staging-dir] # staging-dir defaults to /tmp/meshbay-build # # Output: $STAGING/meshbay-common-root/ (ready for dpkg-deb or rpmbuild) set -euo pipefail REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" STAGING="${1:-/tmp/meshbay-build}" ROOT="$STAGING/meshbay-common-root" VENV_FINAL="/opt/meshbay-common/venv" VENV_BUILD="$ROOT$VENV_FINAL" WHEEL_DIR="$STAGING/wheels" VERSION=$(python3 -c " import tomllib, pathlib p = pathlib.Path('$REPO/packages/meshbay-common/pyproject.toml') print(tomllib.loads(p.read_text())['project']['version']) ") echo "==> meshbay-common $VERSION" rm -rf "$ROOT" mkdir -p "$ROOT/opt/meshbay-common" "$WHEEL_DIR" # --- Create venv ----------------------------------------------------------- echo " creating venv at $VENV_BUILD" python3 -m venv "$VENV_BUILD" "$VENV_BUILD/bin/pip" install --upgrade pip wheel 2>&1 | tail -1 # --- Build wheels for every package ---------------------------------------- echo " building wheels" for pkg in meshbay-common meshbay-hub meshbay-node meshbay-cli; do "$VENV_BUILD/bin/pip" wheel \ --no-deps \ --wheel-dir "$WHEEL_DIR" \ "$REPO/packages/$pkg" 2>&1 | tail -1 done # --- Install everything into the venv ------------------------------------- echo " installing all packages + dependencies" "$VENV_BUILD/bin/pip" install \ --find-links "$WHEEL_DIR" \ meshbay-common meshbay-hub meshbay-node 2>&1 | tail -3 # The command-line client goes in last, after a list of what the servers need: # whatever its install adds is the CLI's alone, and build-cli.sh moves it into # the meshbay-cli package, so a server carries no Textual. SITE_BUILD=$(echo "$VENV_BUILD"/lib/python3.*/site-packages) LC_ALL=C ls -1A "$SITE_BUILD" > "$STAGING/servers-site.txt" LC_ALL=C ls -1A "$VENV_BUILD/bin" > "$STAGING/servers-bin.txt" echo " installing meshbay-cli + its own dependencies" "$VENV_BUILD/bin/pip" install \ --find-links "$WHEEL_DIR" \ meshbay-cli 2>&1 | tail -1 # --- Third-party notices: every package the venv ships, with its licence ------- echo " writing THIRD-PARTY-NOTICES.txt" "$VENV_BUILD/bin/python" "$REPO/packaging/third_party_notices.py" \ -o "$ROOT/opt/meshbay-common/THIRD-PARTY-NOTICES.txt" meshbay-hub meshbay-node # --- Known vulnerabilities in what ships ----------------------------------- # One stops the build unless packaging/pip-audit-ignore.txt says why it does not # apply; no network only skips the audit, with a warning. pip-audit runs from a # venv of its own under the staging dir, never from the one shipped. echo " auditing dependencies (pip-audit)" "$VENV_BUILD/bin/python" "$REPO/packaging/audit_deps.py" --tool-dir "$STAGING/pip-audit" # --- Strip build tools from the venv (not needed at runtime) --------------- echo " stripping build tools" "$VENV_BUILD/bin/pip" uninstall -y pip setuptools wheel 2>&1 | tail -1 rm -rf "$VENV_BUILD/lib"/python*/site-packages/pip* rm -rf "$VENV_BUILD/lib"/python*/site-packages/setuptools* rm -rf "$VENV_BUILD/lib"/python*/site-packages/wheel* rm -f "$VENV_BUILD/bin/pip"* # --- Fix shebangs and pyvenv.cfg ------------------------------------------ # The venv was built under $ROOT but will be installed at /opt/meshbay-common/venv/ echo " fixing paths ($ROOT -> '')" for f in "$VENV_BUILD/bin"/*; do [ -f "$f" ] || continue [ -L "$f" ] && continue head -1 "$f" | grep -q "^#!" || continue # Line 2 too: past 127 characters, pip writes a `#!/bin/sh` trampoline that # names the interpreter on the next line. sed -i "1,2s|$ROOT||" "$f" done sed -i "s|$ROOT||g" "$VENV_BUILD/pyvenv.cfg" # --- Remove __pycache__ (will be regenerated on first import) -------------- find "$VENV_BUILD" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true # --- Keep a copy of the wheels for reference ------------------------------- mkdir -p "$ROOT/opt/meshbay-common/wheels" cp "$WHEEL_DIR"/meshbay_common-*.whl "$ROOT/opt/meshbay-common/wheels/" echo "==> meshbay-common staging ready at $ROOT" echo " venv: $VENV_BUILD" echo " version: $VERSION"