|
| 1 | +#!/bin/bash |
| 2 | +# SPDX-License-Identifier: MPL-2.0 |
| 3 | +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell |
| 4 | +# |
| 5 | +# SessionStart hook — provision the OCaml toolchain + tree-sitter grammar so |
| 6 | +# Claude Code on the web can `dune build` / `dune runtest` this project |
| 7 | +# without manual setup. |
| 8 | +# |
| 9 | +# Why apt and not opam: this repo's web environment reaches the Ubuntu archive |
| 10 | +# and github.com, but opam.ocaml.org is blocked by the network policy (its |
| 11 | +# index returns 403). Ubuntu's OCaml packages happen to satisfy the project's |
| 12 | +# version pins (dune 3.14, cmdliner 1.2, alcotest 1.7, menhir 20231231, |
| 13 | +# sedlex 3.2, ppx_deriving 5.2, ppxlib 0.32, yojson 2.1, js_of_ocaml 5.6), so |
| 14 | +# apt is the reliable install path here. This exact set was verified to give a |
| 15 | +# clean full `dune build` + `dune runtest`. |
| 16 | +# |
| 17 | +# Best-effort and idempotent: a failed step logs a warning to stderr but never |
| 18 | +# aborts session start; already-installed steps are skipped. Synchronous, so |
| 19 | +# the toolchain is guaranteed ready before the session begins. |
| 20 | + |
| 21 | +set -uo pipefail |
| 22 | + |
| 23 | +# Web sessions only — local dev environments manage their own toolchain. |
| 24 | +if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then |
| 25 | + exit 0 |
| 26 | +fi |
| 27 | + |
| 28 | +log() { echo "[session-start] $*" >&2; } |
| 29 | +warn() { echo "[session-start] WARNING: $*" >&2; } |
| 30 | + |
| 31 | +REPO="${CLAUDE_PROJECT_DIR:-$(pwd)}" |
| 32 | + |
| 33 | +# 1. OCaml toolchain via apt (skip if dune is already on PATH). |
| 34 | +if command -v dune >/dev/null 2>&1; then |
| 35 | + log "OCaml toolchain present (dune $(dune --version 2>/dev/null)); skipping apt" |
| 36 | +else |
| 37 | + log "installing OCaml toolchain via apt ..." |
| 38 | + export DEBIAN_FRONTEND=noninteractive |
| 39 | + apt-get update -qq || warn "apt-get update failed; install may be incomplete" |
| 40 | + apt-get install -y -qq \ |
| 41 | + ocaml-nox ocaml-dune ocaml-findlib \ |
| 42 | + libcmdliner-ocaml-dev libfmt-ocaml-dev libalcotest-ocaml-dev \ |
| 43 | + menhir libmenhir-ocaml-dev libsedlex-ocaml-dev \ |
| 44 | + libppx-deriving-ocaml-dev libppxlib-ocaml-dev libyojson-ocaml-dev \ |
| 45 | + js-of-ocaml libjs-of-ocaml-dev \ |
| 46 | + || warn "apt install of the OCaml toolchain failed; 'dune build' may not work" |
| 47 | +fi |
| 48 | + |
| 49 | +# 2. tree-sitter CLI (needed by the res-to-affine walker tests in |
| 50 | +# tools/res-to-affine/test/). Skip if already on PATH. |
| 51 | +if command -v tree-sitter >/dev/null 2>&1; then |
| 52 | + log "tree-sitter present ($(tree-sitter --version 2>/dev/null)); skipping npm" |
| 53 | +elif command -v npm >/dev/null 2>&1; then |
| 54 | + log "installing tree-sitter CLI ..." |
| 55 | + npm install -g tree-sitter-cli@^0.25.0 \ |
| 56 | + || warn "tree-sitter CLI install failed; walker tests will auto-skip" |
| 57 | +else |
| 58 | + warn "npm not found; cannot install tree-sitter CLI (walker tests will skip)" |
| 59 | +fi |
| 60 | + |
| 61 | +# 3. Pinned tree-sitter-rescript grammar — generates the parser the walker |
| 62 | +# shells out to. install.sh re-checks out the pinned commit; skip if the |
| 63 | +# generated parser is already present. |
| 64 | +if [ -f "$REPO/tools/vendor/tree-sitter-rescript/src/parser.c" ]; then |
| 65 | + log "tree-sitter-rescript grammar already built" |
| 66 | +elif command -v tree-sitter >/dev/null 2>&1; then |
| 67 | + log "building pinned tree-sitter-rescript grammar ..." |
| 68 | + ( cd "$REPO" && ./editors/tree-sitter-rescript/scripts/install.sh ) \ |
| 69 | + || warn "grammar build failed; res-to-affine walker tests will auto-skip" |
| 70 | +fi |
| 71 | + |
| 72 | +log "ready. build: dune build | test: dune runtest" |
| 73 | +exit 0 |
0 commit comments