kirche-einfach/.devcontainer/setup.sh

101 lines
3.8 KiB
Bash

#!/bin/bash
# Dev-only setup (runs via postCreateCommand in the attached `api` container).
# Production needs none of this: images carry their dependencies and the
# api entrypoint migrates on every start.
set -eo pipefail
REPO=/srv/kirche-einfach
# Run a command as vscode with the current environment intact.
# (`su vscode -c` resets the environment, which used to drop
# UV_PROJECT_ENVIRONMENT/UV_PYTHON_INSTALL_DIR plus every compose-provided
# variable — uv then created a project-local backend/.venv in the bind-mount
# instead of using /opt/venv, and sync_flows.py ran without its settings.)
# -H repoints HOME to /home/vscode: without it HOME stays /root (from the
# outer sudo) and uv/pip caches fail with Permission denied.
as_vscode() {
sudo -H -u vscode -E bash -c "$*"
}
# Venv lives outside the bind-mount (see backend/Dockerfile).
export UV_PYTHON_INSTALL_DIR=/opt/python UV_PROJECT_ENVIRONMENT=/opt/venv
echo "=== Setting up kirche-einfach ==="
# Writable dirs first: this script runs via sudo as root, but the editor and
# most commands run as vscode. (A root-created backend/data/ or venv used to
# break the DB and the interpreter for vscode.)
mkdir -p "$REPO/backend/data" \
"$REPO/frontend/node_modules" \
/opt/python /opt/venv \
/home/vscode/.cache \
/home/vscode/.local/share/uv \
/home/vscode/.local/share/opencode \
/home/vscode/.config/opencode
chown -R vscode:vscode "$REPO/backend/data" \
"$REPO/frontend/node_modules" \
/opt/python /opt/venv \
/home/vscode/.cache \
/home/vscode/.local/share/uv \
/home/vscode/.local/share/opencode \
/home/vscode/.config/opencode 2>/dev/null || true
# Backend deps into /opt/venv, as vscode (a root-owned venv is unusable for
# the editor; uv resolves at setup time, no lockfile is committed).
echo "--- Installing Python dependencies ---"
cd "$REPO/backend"
as_vscode "uv sync"
# opencode CLI (dev tooling; intentionally not baked into the image).
if [ ! -x /home/vscode/.opencode/bin/opencode ]; then
echo "--- Installing opencode ---"
as_vscode "curl -fsSL https://opencode.ai/install | bash"
ln -sf /home/vscode/.opencode/bin/opencode /usr/local/bin/opencode
fi
# Compose services (langflow, lfx) must be up; fail loudly otherwise.
# (api/frontend are starting alongside this script.)
# Fresh clones have no `.env` (gitignored) and compose `env_file` is
# optional, so provision one from the example instead of failing setup.
# Fill in real secrets afterwards; empty SMTP_* means the API logs mail.
if [ ! -f "$REPO/.env" ]; then
echo "WARN: $REPO/.env missing — copying .env.example (fill in secrets)."
cp "$REPO/.env.example" "$REPO/.env"
chown vscode:vscode "$REPO/.env" 2>/dev/null || true
fi
echo "--- Waiting for compose services ---"
python3 - <<'EOF'
import socket
import sys
import time
targets = [("langflow", 7860), ("lfx", 6004)]
deadline = time.time() + 180
pending = dict(targets)
while pending and time.time() < deadline:
for host, port in list(pending.items()):
s = socket.socket()
s.settimeout(2)
try:
s.connect((host, port))
print(f"OK {host}:{port}", flush=True)
del pending[host]
except OSError:
pass
finally:
s.close()
if pending:
time.sleep(2)
if pending:
sys.exit(f"ERROR: compose services not ready: {sorted(pending)}")
EOF
# Reconcile backend/flows into the DB + LFX (schema is migrated by the api
# entrypoint on every start).
echo "--- Syncing canonical flows ---"
cd "$REPO/backend"
as_vscode "uv run python scripts/sync_flows.py --sync" || echo "WARN: flow sync failed (check backend/flows and LFX)"
echo ""
echo "=== Setup complete ==="
echo "Forgejo username: $FORGEJO_USERNAME"