113c9f0bb0
Main changes: - Extract opencode.json generation from entrypoint-user.sh into a standalone Python script (rootfs/usr/local/lib/opencode-devbox/ generate-config.py). Preserves the never-overwrite-existing-config guarantee. Cuts entrypoint-user.sh from 176 to 97 lines. - Install MemPalace via 'uv tool install' into an isolated venv at /opt/uv-tools/mempalace/ with a /usr/local/bin/mempalace-mcp-server wrapper, replacing the 'pip install --break-system-packages' escape hatch. The wrapper is what generate-config.py references in the auto-generated opencode.json. Also fix 'mempalace init' in entrypoint-user.sh to use --yes so first-start initialization isn't interactive (this used to hang or print prompts into the user's terminal). Gated by INSTALL_MEMPALACE build arg (default true) so users who don't need AI memory can shave ~300 MB. - Sentinel-file pattern in entrypoint.sh volume-ownership loop: write .devbox-owner after a successful chown -R, skip the recursive walk on subsequent starts when the sentinel matches FINAL_UID:FINAL_GID. Cuts multi-second startup costs to milliseconds on large volumes (nvim plugins, palace data). UID changes still trigger a full chown. - Float all GitHub/Gitea-hosted binary versions: gosu, fzf, git-lfs, neovim, bat, eza, zoxide, uv, gitea-mcp now default to 'latest' and resolve the newest upstream release at build time via the /releases/ latest redirect. Go (go.dev JSON feed) and oh-my-opencode-slim (npm @latest) likewise. Intentional pins still in place: OPENCODE_VERSION, NODE_VERSION=22, DEBIAN_VERSION=trixie-slim. Each *_VERSION ARG accepts an explicit value to lock a specific version when needed. - New scripts/smoke-test.sh verifies binary presence, opencode startup, entrypoint user drop, generate-config idempotency, bun's presence- per-variant, and image size against thresholds (2500 MB base, 3000 MB OMOS). Prints resolved component versions as its first step so CI logs always record what got baked into a given image. - New .gitea/workflows/validate.yml runs on push to main and PRs: single-arch amd64 build, smoke test, DOCKER_HUB.md sync check. Tag- triggered docker-publish.yml now smoke-tests each variant on amd64 before the full multi-arch push. - scripts/generate-dockerhub-md.py auto-generates DOCKER_HUB.md from README.md using explicit SECTION_RULES. --check mode fails CI when the committed file is out of sync. Enforces the 25 kB Docker Hub limit. Adding a new README section forces an explicit keep/drop/ replace decision. - Remove dead INSTALL_PYTHON build arg (was a no-op since mempalace added python3 unconditionally).
101 lines
4.0 KiB
Bash
101 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ── Shell defaults: copy baked files from /etc/skel-devbox/ if absent
|
|
# Respects host bind-mounts and user customizations — existing files
|
|
# are never overwritten. To restore defaults: rm ~/.bash_aliases (or
|
|
# .inputrc) and recreate the container, or cp from /etc/skel-devbox/
|
|
# directly.
|
|
SKEL_DIR="/etc/skel-devbox"
|
|
if [ -d "$SKEL_DIR" ]; then
|
|
for f in .bash_aliases .inputrc; do
|
|
if [ -f "$SKEL_DIR/$f" ] && [ ! -e "$HOME/$f" ]; then
|
|
cp "$SKEL_DIR/$f" "$HOME/$f"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ── MemPalace: initialize palace for the workspace if mempalace is installed
|
|
# Creates the palace directory structure on first run. Idempotent — skips
|
|
# if palace already exists, so upgrades from older versions preserve
|
|
# existing data. `--yes` auto-accepts detected entities so the init is
|
|
# non-interactive — the container entrypoint has no usable stdin for
|
|
# prompts anyway.
|
|
if command -v mempalace &>/dev/null && [ -d /workspace ]; then
|
|
PALACE_DIR="${HOME}/.mempalace"
|
|
if [ ! -d "$PALACE_DIR/palace" ]; then
|
|
echo "Initializing MemPalace for workspace (non-interactive)..."
|
|
mempalace init --yes /workspace >/dev/null 2>&1 || true
|
|
fi
|
|
fi
|
|
|
|
# ── Git config defaults ──────────────────────────────────────────────
|
|
if [ -n "${GIT_USER_NAME:-}" ] && ! git config --global user.name &>/dev/null; then
|
|
git config --global user.name "$GIT_USER_NAME"
|
|
fi
|
|
if [ -n "${GIT_USER_EMAIL:-}" ] && ! git config --global user.email &>/dev/null; then
|
|
git config --global user.email "$GIT_USER_EMAIL"
|
|
fi
|
|
|
|
# ── Generate opencode config from env vars if no config mounted ──────
|
|
# Delegated to a standalone Python script for clarity and testability.
|
|
# The script is idempotent: it never overwrites an existing opencode.json
|
|
# (bind-mounted from host, persisted in named volume, or previously
|
|
# generated) and no-ops if OPENCODE_PROVIDER is unset.
|
|
python3 /usr/local/lib/opencode-devbox/generate-config.py
|
|
|
|
CONFIG_DIR="$HOME/.config/opencode"
|
|
OMOS_CONFIG="$CONFIG_DIR/oh-my-opencode-slim.json"
|
|
|
|
# ── oh-my-opencode-slim setup (multi-agent orchestration) ────────────
|
|
# Activated by ENABLE_OMOS=true. Requires the image to be built with
|
|
# INSTALL_OMOS=true (which installs bun + the oh-my-opencode-slim package).
|
|
OMOS_CONFIG="$CONFIG_DIR/oh-my-opencode-slim.json"
|
|
|
|
if [ "${ENABLE_OMOS:-false}" = "true" ]; then
|
|
if ! command -v bunx &>/dev/null; then
|
|
echo "WARNING: ENABLE_OMOS=true but bun is not installed."
|
|
echo "Rebuild with: docker compose build --build-arg INSTALL_OMOS=true"
|
|
elif [ ! -f "$OMOS_CONFIG" ]; then
|
|
echo "Setting up oh-my-opencode-slim agents..."
|
|
|
|
# Determine installer flags
|
|
OMOS_TMUX_FLAG="no"
|
|
if [ "${OMOS_TMUX:-false}" = "true" ]; then
|
|
OMOS_TMUX_FLAG="yes"
|
|
fi
|
|
|
|
OMOS_SKILLS_FLAG="yes"
|
|
if [ "${OMOS_SKILLS:-true}" = "false" ]; then
|
|
OMOS_SKILLS_FLAG="no"
|
|
fi
|
|
|
|
bunx oh-my-opencode-slim@latest install \
|
|
--no-tui \
|
|
--tmux="${OMOS_TMUX_FLAG}" \
|
|
--skills="${OMOS_SKILLS_FLAG}"
|
|
|
|
echo "oh-my-opencode-slim configured successfully."
|
|
else
|
|
echo "oh-my-opencode-slim config found at $OMOS_CONFIG (use OMOS_RESET=true to overwrite)."
|
|
|
|
# Allow reset via env var (creates backup automatically)
|
|
if [ "${OMOS_RESET:-false}" = "true" ]; then
|
|
echo "OMOS_RESET=true — regenerating oh-my-opencode-slim config..."
|
|
OMOS_TMUX_FLAG="no"
|
|
[ "${OMOS_TMUX:-false}" = "true" ] && OMOS_TMUX_FLAG="yes"
|
|
OMOS_SKILLS_FLAG="yes"
|
|
[ "${OMOS_SKILLS:-true}" = "false" ] && OMOS_SKILLS_FLAG="no"
|
|
|
|
bunx oh-my-opencode-slim@latest install \
|
|
--no-tui \
|
|
--tmux="${OMOS_TMUX_FLAG}" \
|
|
--skills="${OMOS_SKILLS_FLAG}" \
|
|
--reset
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ── Execute command ──────────────────────────────────────────────────
|
|
exec "$@"
|