after moving all to cipher
This commit is contained in:
@@ -368,11 +368,23 @@ RUBY
|
||||
return 0
|
||||
}
|
||||
|
||||
# First-use setup writes to two places with different lifetimes, so it takes two markers:
|
||||
# host — the commit checkout, in the bind-mounted repo dir; survives any container.
|
||||
# ctr — deps (node_modules / gems / venv / cargo target), databases and ~/.bashrc; all of
|
||||
# these live in this container and die with it.
|
||||
# Tracking both with one host-side marker makes a second or rebuilt container skip an install
|
||||
# it never ran, leaving the member pointed at a node_modules that isn't there.
|
||||
CTR_MARKER_DIR="/opt/raccoon-setup"
|
||||
# Record <repo> as set up in THIS container. Best-effort: if the marker can't be written the
|
||||
# only consequence is that setup runs again next time, and every step of it is idempotent.
|
||||
_mark_ctr_setup() { mkdir -p "$CTR_MARKER_DIR" 2>/dev/null && : > "$CTR_MARKER_DIR/$1.done" 2>/dev/null || true; }
|
||||
|
||||
# First-use setup for a member repo: checkout its commit, install deps, prepare DB.
|
||||
# Idempotent via a marker file. Runtime-driven; the marker is written only on success.
|
||||
# Runtime-driven; each marker is written only once its own half has succeeded.
|
||||
setup_repo() {
|
||||
local repo="$1" dir="/workspace/repos/$1" marker="/workspace/repos/$1/.raccoon-setup-done"
|
||||
[ -f "$marker" ] && return 0
|
||||
local repo="$1" dir="/workspace/repos/$1"
|
||||
local hostmarker="/workspace/repos/$1/.raccoon-setup-done" ctrmarker="$CTR_MARKER_DIR/$1.done"
|
||||
[ -f "$ctrmarker" ] && return 0
|
||||
local commit runtime kind ver bootenv setupcmd
|
||||
commit=$(_poly_field "$repo" defaultCommit)
|
||||
runtime=$(_poly_field "$repo" runtime); kind=${runtime%%:*}; ver=${runtime#*:}
|
||||
@@ -390,7 +402,10 @@ setup_repo() {
|
||||
# is non-fatal (a warning) — a member that can still be explored shouldn't be blocked by
|
||||
# a seed hiccup, mirroring the `|| true` seeds in post-create.sh for single-repo kits.
|
||||
setupcmd=$(_poly_field "$repo" setupCmd)
|
||||
if [ -n "$commit" ] && ! git -C "$dir" -c advice.detachedHead=false checkout "$commit" >/dev/null 2>&1; then
|
||||
# Only the first container to reach a given repo dir checks it out: the checkout is host-side
|
||||
# state, so redoing it later would move a worker off a commit they had deliberately chosen.
|
||||
if [ ! -f "$hostmarker" ] && [ -n "$commit" ] \
|
||||
&& ! git -C "$dir" -c advice.detachedHead=false checkout "$commit" >/dev/null 2>&1; then
|
||||
printf "${RED}checkout %s failed for %s${RESET}\n" "$commit" "$repo"; return 1
|
||||
fi
|
||||
# Keep the setup marker out of `git status` — and out of snapshot patches, which
|
||||
@@ -399,6 +414,10 @@ setup_repo() {
|
||||
mkdir -p "$dir/.git/info"
|
||||
grep -qxF '.raccoon-setup-done' "$dir/.git/info/exclude" 2>/dev/null \
|
||||
|| printf '\n# raccoon-explore: run-app first-use setup marker\n.raccoon-setup-done\n' >> "$dir/.git/info/exclude"
|
||||
# Same for the node_modules symlink: a `node_modules/` .gitignore entry doesn't match it.
|
||||
grep -qxF 'node_modules' "$dir/.git/info/exclude" 2>/dev/null \
|
||||
|| printf '\n# raccoon-explore: run-app node_modules symlink\nnode_modules\n' >> "$dir/.git/info/exclude"
|
||||
touch "$hostmarker" 2>/dev/null || true
|
||||
# Persist bootEnv as real exports for ALL the worker's container shells (deduped per repo).
|
||||
if [ -n "$bootenv" ] && ! grep -q "raccoon-bootenv:$repo" "$HOME/.bashrc" 2>/dev/null; then
|
||||
{ echo "# raccoon-bootenv:$repo"; for kv in $bootenv; do echo "export $kv"; done; } >> "$HOME/.bashrc"
|
||||
@@ -406,12 +425,12 @@ setup_repo() {
|
||||
printf " ${GRAY}first-time setup for %s (%s) \xe2\x80\x94 runs once\xe2\x80\xa6${RESET}\n" "$repo" "${runtime:-explore-only}"
|
||||
case "$kind" in
|
||||
ruby)
|
||||
_rb_have "$ver" || { printf " ${GRAY}(Ruby %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; touch "$marker"; return 0; }
|
||||
_rb_have "$ver" || { printf " ${GRAY}(Ruby %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; _mark_ctr_setup "$repo"; return 0; }
|
||||
( cd "$dir" \
|
||||
&& export PATH="$RBENV_PATH:$PATH" RBENV_VERSION="$ver" \
|
||||
&& { [ -f config/database.yml.example ] && cp -n config/database.yml.example config/database.yml; true; } \
|
||||
&& { [ -f .env.example ] && cp -n .env.example .env; true; } \
|
||||
&& { [ -n "$bootenv" ] && printf '%s\n' $bootenv >> .env; true; } \
|
||||
&& { for kv in $bootenv; do grep -qxF "$kv" .env 2>/dev/null || echo "$kv" >> .env; done; true; } \
|
||||
&& { bundle lock --add-platform x86_64-linux aarch64-linux >/dev/null 2>&1 || true; } \
|
||||
&& { bundle install || bundle install --full-index; } \
|
||||
&& { if [ -f db/source_schema.rb ]; then \
|
||||
@@ -432,7 +451,7 @@ setup_repo() {
|
||||
fi; } ) || return 1 ;;
|
||||
node)
|
||||
nbin=$(_node_bin "$ver")
|
||||
[ -z "$nbin" ] && { printf " ${GRAY}(Node %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; touch "$marker"; return 0; }
|
||||
[ -z "$nbin" ] && { printf " ${GRAY}(Node %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; _mark_ctr_setup "$repo"; return 0; }
|
||||
# Install node_modules to a CONTAINER-LOCAL path, not the bind-mounted repo dir. On
|
||||
# macOS Docker Desktop the repo is a host bind mount; writing a huge node_modules tree
|
||||
# across the file-sharing layer is slow AND exhausts the HOST's open-file table (ENFILE
|
||||
@@ -443,7 +462,7 @@ setup_repo() {
|
||||
&& export PATH="$nbin:$PATH" \
|
||||
&& _nm_link "$repo" \
|
||||
&& { [ -f .env.example ] && cp -n .env.example .env; true; } \
|
||||
&& { [ -n "$bootenv" ] && printf '%s\n' $bootenv >> .env; true; } \
|
||||
&& { for kv in $bootenv; do grep -qxF "$kv" .env 2>/dev/null || echo "$kv" >> .env; done; true; } \
|
||||
&& { if [ -f yarn.lock ]; then yarn install; elif [ -f package-lock.json ]; then npm install; else yarn install; fi; } ) || return 1 ;;
|
||||
python)
|
||||
if _py_uv_ok "$ver"; then
|
||||
@@ -454,14 +473,14 @@ setup_repo() {
|
||||
&& uv venv "$vdir" -p "$ver" -q \
|
||||
&& . "$vdir/bin/activate" \
|
||||
&& { [ -f .env.example ] && cp -n .env.example .env; true; } \
|
||||
&& { [ -n "$bootenv" ] && printf '%s\n' $bootenv >> .env; true; } \
|
||||
&& { for kv in $bootenv; do grep -qxF "$kv" .env 2>/dev/null || echo "$kv" >> .env; done; true; } \
|
||||
&& { if [ -f pyproject.toml ]; then uv pip install -q -e . || uv pip install -q -r requirements.txt 2>/dev/null || true; \
|
||||
elif [ -f requirements.txt ]; then uv pip install -q -r requirements.txt; \
|
||||
elif [ -f server/requirements.txt ]; then uv pip install -q -r server/requirements.txt; \
|
||||
elif [ -f setup.py ]; then uv pip install -q -e .; else true; fi; } ) || return 1
|
||||
touch "$marker"; return 0
|
||||
_mark_ctr_setup "$repo"; return 0
|
||||
fi
|
||||
_py_have "$ver" || { printf " ${GRAY}(Python %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; touch "$marker"; return 0; }
|
||||
_py_have "$ver" || { printf " ${GRAY}(Python %s not in this image; skipping deps \xe2\x80\x94 explore-only)${RESET}\n" "$ver"; _mark_ctr_setup "$repo"; return 0; }
|
||||
# Some poetry repos depend on sibling repos via `git = "ssh://git@github.com/AskZeta/<name>.git"`,
|
||||
# which can't resolve in the container (no SSH key, no network). The deps are TRANSITIVE
|
||||
# (cx-chatbot → compiler-agent → agent-tools → leaves), so rewrite the target AND every
|
||||
@@ -472,7 +491,7 @@ setup_repo() {
|
||||
done
|
||||
( cd "$dir" && export PATH="$PYENV_PATH:$PATH" PYENV_VERSION="$ver" \
|
||||
&& { [ -f .env.example ] && cp -n .env.example .env; true; } \
|
||||
&& { [ -n "$bootenv" ] && printf '%s\n' $bootenv >> .env; true; } \
|
||||
&& { for kv in $bootenv; do grep -qxF "$kv" .env 2>/dev/null || echo "$kv" >> .env; done; true; } \
|
||||
&& { if [ -f pyproject.toml ]; then \
|
||||
# The git→path rewrite invalidates poetry.lock ("changed significantly");
|
||||
# regenerate it before installing. Poetry 2.x `lock` preserves pins by
|
||||
@@ -487,12 +506,12 @@ setup_repo() {
|
||||
elif [ -f requirements.txt ]; then pip install -r requirements.txt; \
|
||||
elif [ -f setup.py ]; then pip install -e .; else true; fi; } ) || return 1 ;;
|
||||
rust)
|
||||
command -v cargo >/dev/null 2>&1 || { printf " ${GRAY}(Rust not in this image; skipping build \xe2\x80\x94 explore-only)${RESET}\n"; touch "$marker"; return 0; }
|
||||
command -v cargo >/dev/null 2>&1 || { printf " ${GRAY}(Rust not in this image; skipping build \xe2\x80\x94 explore-only)${RESET}\n"; _mark_ctr_setup "$repo"; return 0; }
|
||||
# Build to a container-local target dir (same ENFILE/bind-mount rationale as
|
||||
# node_modules): a Cargo workspace target tree is huge and rebuilds often.
|
||||
( cd "$dir" \
|
||||
&& { [ -f .env.example ] && cp -n .env.example .env; true; } \
|
||||
&& { [ -n "$bootenv" ] && printf '%s\n' $bootenv >> .env; true; } \
|
||||
&& { for kv in $bootenv; do grep -qxF "$kv" .env 2>/dev/null || echo "$kv" >> .env; done; true; } \
|
||||
&& CARGO_TARGET_DIR="/opt/raccoon-cargo-target/$repo" cargo build --workspace ) || return 1 ;;
|
||||
none|"") : ;; # no-code / explore-only: nothing to install
|
||||
*) printf "${YELLOW}unknown runtime '%s' for %s \xe2\x80\x94 explore-only${RESET}\n" "$runtime" "$repo" ;;
|
||||
@@ -524,7 +543,7 @@ setup_repo() {
|
||||
printf " ${GRAY}what went wrong: %s${RESET}\n" "$slog"
|
||||
fi
|
||||
fi
|
||||
touch "$marker"
|
||||
_mark_ctr_setup "$repo"
|
||||
}
|
||||
|
||||
start_poly() {
|
||||
@@ -649,6 +668,12 @@ start_poly() {
|
||||
printf " ${RESET}${CYAN}http://localhost:%s/dev-login${RESET}${GRAY} to sign in as a seeded admin\n" "$CLIENT_HOST_PORT"
|
||||
printf " (${RESET}${GRAY}?role=MSS${RESET}${GRAY} or ${RESET}${GRAY}?role=MEMBER${RESET}${GRAY} for the other roles). The DB was seeded during setup.${RESET}\n"
|
||||
;;
|
||||
potion-app)
|
||||
printf " ${GRAY}Sign-in normally goes through Google or LinkedIn, neither reachable offline,\n"
|
||||
printf " so setup seeded a verified local account. Log in at\n"
|
||||
printf " ${RESET}${CYAN}http://localhost:%s/auth/login${RESET}${GRAY} with ${RESET}${GRAY}dev@example.com${RESET}${GRAY} / ${RESET}${GRAY}devpassword123${RESET}${GRAY}\n" "$CLIENT_HOST_PORT"
|
||||
printf " — note ${RESET}${GRAY}/login${RESET}${GRAY} and ${RESET}${GRAY}/auth${RESET}${GRAY} both redirect elsewhere.${RESET}\n"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
printf " ${RED}\xe2\x9a\xa0 %s didn't come up in time${RESET} \xe2\x80\x94 ${GRAY}run-app --logs${RESET}\n" "$repo"
|
||||
@@ -667,13 +692,6 @@ start_rails() {
|
||||
local login_hint="${1:-}" url_note="${2:-}"
|
||||
_spawn app /workspace/repo "bin/rails server -b 0.0.0.0 -p 3000"
|
||||
printf " ${YELLOW}\xe2\x96\xb6${RESET} starting Rails (puma)\xe2\x80\xa6\n"
|
||||
# Repos built on tailwindcss-rails need the watcher running too, or their
|
||||
# compiled app/assets/builds/application.css never gets generated and Propshaft
|
||||
# silently falls back to serving an unrelated same-named stylesheet instead.
|
||||
if [ -d /workspace/repo/app/assets/tailwind ]; then
|
||||
_spawn css /workspace/repo "bin/rails tailwindcss:watch"
|
||||
printf " ${YELLOW}\xe2\x96\xb6${RESET} starting Tailwind CSS watcher\xe2\x80\xa6\n"
|
||||
fi
|
||||
printf " ${GRAY}\xe2\x8f\xb3 waiting for the app to come up\xe2\x80\xa6${RESET}\n"
|
||||
if _wait_tcp 3000; then
|
||||
printf " ${YELLOW}\xe2\x9c\x85 app is up${RESET}\n"
|
||||
|
||||
Reference in New Issue
Block a user