From 8a0946ea3943b127580e86e956d292fa5d9c0424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 21:55:04 +0000 Subject: [PATCH] officer-setup section 3: dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bun install, as the account, in the checkout. Two things stated because a failure here is otherwise opaque. The lockfile is frozen — bunfig.toml sets [install] frozenLockfile = true — so bun resolves from bun.lock and nothing else. A package.json that disagrees with it is a hard failure rather than a quiet resolution, which is deliberate: the friction exists so an unexplained lockfile change shows up in a diff. If the install fails complaining about the lockfile, the section says that is the frozen lockfile working and that it wants a human to read the diff, rather than reporting a generic failure. node-pty has no Linux prebuild, so this compiles it from source on every machine. That is what build-essential and python3 are in machine-setup's core utils for, and the section says so — the failure would otherwise surface much later as a terminal that never starts. Success is checked by the artefact rather than by the exit status: bun can complete while the native module is not built, because it skips a dependency's lifecycle scripts unless it trusts the package. So the section looks for node_modules/node-pty/build/Release/*.node and, when it is missing, names the consequence and the command that fixes it instead of reporting success. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/setup/officer-setup.sh | 88 +++++++++++++++---------- scripts/setup/officer-setup/lib/repo.sh | 25 +++++++ 2 files changed, 80 insertions(+), 33 deletions(-) diff --git a/scripts/setup/officer-setup.sh b/scripts/setup/officer-setup.sh index 9ea1fb0c..59ac1287 100755 --- a/scripts/setup/officer-setup.sh +++ b/scripts/setup/officer-setup.sh @@ -211,43 +211,14 @@ if ! skip; then CLONE_URL="$OFFICER_REPO" - # Checked before cloning, for either scheme — see repo_reachable. - if ! repo_reachable "$CLONE_URL"; then - echo "" - warn "${USERNAME} cannot read ${CLONE_URL}" - echo " Either the host is not answering yet, or the repository is not" - echo " readable without credentials." - echo "" - echo " [1] try it anyway" - echo " [2] use a different URL" - echo " [3] stop here" - echo "" - REPO_PICK="" - while [[ -z "$REPO_PICK" ]]; do - if ! read -rp " Which one? (1/2/3) [1]: " REPO_CHOICE; then - echo "" - fail "No answer." - fi - case "${REPO_CHOICE:-1}" in - 1) REPO_PICK=go ;; - 2) - ask_required CLONE_URL "Repository URL" "$CLONE_URL" - REPO_PICK=go - ;; - 3) fail "Stopped. Nothing below can run without the repository." ;; - *) warn "Pick 1, 2 or 3." ;; - esac - done - fi - if confirm "Clone it now?"; then if clone_repo "$CLONE_URL"; then ok "cloned to ${PLATFORM_DIR} on $(repo_branch)" SUMMARY+=("Repository: cloned from ${CLONE_URL}") else - warn "the clone did not complete" - ERRORS+=("Repository: clone failed") - fail "Nothing below can run without the repository." + # GIT_TERMINAL_PROMPT=0 in clone_repo means this is a real failure rather + # than a prompt nobody answered. + fail "could not clone ${CLONE_URL} — nothing below can run without it." fi else fail "Nothing below can run without the repository." @@ -256,10 +227,61 @@ if ! skip; then step_ok fi +# ============================================================================= +# 3. Dependencies +# ============================================================================= + +step "Dependencies" +if ! skip; then + echo "" + info "Dependencies — bun install, as ${USERNAME}" + echo " node_modules: $(deps_installed && echo present || echo 'not there')" + echo " node-pty: $(node_pty_built && echo built || echo 'not built')" + echo "" + echo " The lockfile is frozen: bun resolves from bun.lock and nothing else," + echo " so a package.json that disagrees with it fails rather than quietly" + echo " picking newer versions. That friction is deliberate." + echo "" + echo " node-pty has no Linux prebuild, so this compiles it from source" + echo " every time — which is what build-essential and python3 are for." + + if deps_installed && node_pty_built; then + ok "already installed, and node-pty is built" + SUMMARY+=("Dependencies: already installed") + elif confirm "Install them?"; then + if install_deps; then + if node_pty_built; then + ok "installed, node-pty built" + SUMMARY+=("Dependencies: installed") + else + # The install can succeed while the native module does not get built — + # bun skips a dependency's lifecycle scripts unless it trusts the + # package. Worth naming, because the symptom is a terminal that never + # comes up rather than an install error. + warn "installed, but node-pty has no built module at node_modules/node-pty/build/Release/" + echo " The terminal sidecar cannot start without it. Try:" + echo " cd $(platform_dir) && bun install --force" + ERRORS+=("Dependencies: node-pty not built") + SUMMARY+=("Dependencies: installed, node-pty NOT built") + fi + else + warn "bun install failed" + echo " If it complained about the lockfile, package.json and bun.lock" + echo " disagree — that is the frozen lockfile doing its job, and it" + echo " wants a human to look at the diff." + ERRORS+=("Dependencies: bun install failed") + SUMMARY+=("Dependencies: FAILED") + fi + else + warn "skipped by request" + SUMMARY+=("Dependencies: SKIPPED by request") + fi + step_ok +fi + # ============================================================================= # NOT BUILT YET # ============================================================================= -# 3 Dependencies bun install # 4 Database Postgres in docker, or one you already run # 5 Environment .env # 6 Schema db:push diff --git a/scripts/setup/officer-setup/lib/repo.sh b/scripts/setup/officer-setup/lib/repo.sh index bc5ec993..c55592ff 100644 --- a/scripts/setup/officer-setup/lib/repo.sh +++ b/scripts/setup/officer-setup/lib/repo.sh @@ -55,3 +55,28 @@ clone_repo() { } pull_repo() { as_owner "git -C '$(platform_dir)' pull --ff-only" /; } + +# ----------------------------------------------------------------------------- +# Dependencies +# ----------------------------------------------------------------------------- +# +# ── The lockfile is frozen, and that is the point ── +# +# bunfig.toml sets [install] frozenLockfile = true, so `bun install` resolves from +# bun.lock and nothing else. A package.json that disagrees with the lockfile is a +# hard failure rather than a quiet resolution — which is deliberate: the friction +# exists so that an unexplained lockfile change shows up in a diff. See the +# supply-chain note in CLAUDE.md. +# +# So a failure here is usually one of two things, and they need different +# answers: the lockfile genuinely disagrees with package.json, or node-pty failed +# to build. Both are reported as such rather than as "install failed". + +deps_installed() { [[ -d "$(platform_dir)/node_modules" ]]; } + +# node-pty has no Linux prebuild, so `bun install` compiles it every time. This is +# the artefact that proves it worked, and its absence is why the terminal sidecar +# would not start. +node_pty_built() { compgen -G "$(platform_dir)/node_modules/node-pty/build/Release/*.node" >/dev/null 2>&1; } + +install_deps() { as_owner "cd '$(platform_dir)' && bun install 2>&1"; }