diff --git a/.memory/worklog.json b/.memory/worklog.json new file mode 100644 index 0000000..87cbe5b --- /dev/null +++ b/.memory/worklog.json @@ -0,0 +1,11 @@ +{ + "entries": [ + { + "ts": "2026-04-18T15:56:14+08:00", + "type": "commit", + "message": "auto-save 2026-04-18 15:54 (+1)", + "hash": "a4201de", + "files_changed": 1 + } + ] +} diff --git a/images/base/build.sh b/images/base/build.sh new file mode 100644 index 0000000..d66b907 --- /dev/null +++ b/images/base/build.sh @@ -0,0 +1,113 @@ +#!/bin/bash +set -euo pipefail + +PROJECT="lobe-sandbox" +PROFILE="sandbox-default" +BUILDER="sb-builder" +IMAGE_ALIAS="lobe-sandbox-base" +BASE="images:debian/13" + +log() { echo "==> [$(date +%H:%M:%S)] $*"; } + +if incus info "$BUILDER" --project "$PROJECT" >/dev/null 2>&1; then + log "Removing existing builder" + incus delete "$BUILDER" --project "$PROJECT" --force +fi + +log "Launching builder from $BASE (4GB/4CPU for fast build)" +incus launch "$BASE" "$BUILDER" --project "$PROJECT" -p "$PROFILE" \ + -c limits.memory=4GiB -c limits.cpu=4 + +log "Waiting for network" +for i in {1..60}; do + if incus exec "$BUILDER" --project "$PROJECT" -- bash -c "getent hosts deb.debian.org >/dev/null 2>&1"; then + log "Network ready after ${i}s"; break + fi + sleep 1 +done + +log "Installing apt packages" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + set -e + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y --no-install-recommends \ + python3 python3-dev python3-venv python3-pip \ + ca-certificates curl wget git gnupg build-essential pkg-config \ + jq ripgrep fd-find bat fonts-noto-cjk \ + less tree unzip zip xz-utils sudo locales tzdata + ln -sf /usr/bin/fdfind /usr/local/bin/fd + ln -sf /usr/bin/batcat /usr/local/bin/bat + sed -i "/zh_CN.UTF-8/s/^# //;/en_US.UTF-8/s/^# //" /etc/locale.gen + locale-gen + ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +' + +log "Installing Node.js 20 via NodeSource" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + set -e + export DEBIAN_FRONTEND=noninteractive + curl -fsSL https://deb.nodesource.com/setup_20.x | bash - + apt-get install -y --no-install-recommends nodejs + corepack enable +' + +log "Installing uv" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + curl -LsSf https://astral.sh/uv/install.sh | env INSTALL_DIR=/usr/local/bin UV_UNMANAGED_INSTALL=1 sh + ls -la /usr/local/bin/uv +' + +log "Installing bun" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + curl -fsSL https://bun.sh/install | env BUN_INSTALL=/usr/local bash + ls -la /usr/local/bin/bun +' + +log "Creating sandbox user and /workspace" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + set -e + useradd --create-home --shell /bin/bash --uid 1000 sandbox + mkdir -p /workspace/data /workspace/output /workspace/tmp + chown -R sandbox:sandbox /workspace /home/sandbox + printf "cd /workspace\nexport LANG=zh_CN.UTF-8\n" >> /home/sandbox/.bashrc +' + +log "Cleaning apt cache" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + apt-get clean + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +' + +log "Verifying versions" +incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' + echo "python : $(python3 --version)" + echo "node : $(node --version)" + echo "bun : $(bun --version)" + echo "uv : $(uv --version)" + echo "git : $(git --version)" + echo "rg : $(rg --version | head -1)" + echo "fd : $(fd --version)" + echo "user : $(id sandbox)" + echo "space : $(du -sh /workspace)" + echo "rootfs : $(du -sh --one-file-system / 2>/dev/null | tail -1)" +' + +log "Stopping builder" +incus stop "$BUILDER" --project "$PROJECT" + +if incus image alias list --project "$PROJECT" | grep -q "$IMAGE_ALIAS"; then + log "Deleting old $IMAGE_ALIAS image" + incus image delete "$IMAGE_ALIAS" --project "$PROJECT" +fi + +log "Publishing as $IMAGE_ALIAS" +incus publish "$BUILDER" --project "$PROJECT" --alias "$IMAGE_ALIAS" + +log "Deleting builder" +incus delete "$BUILDER" --project "$PROJECT" + +log "Image info" +incus image list --project "$PROJECT" + +log "DONE"