diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8293527..b83edfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,3 +119,68 @@ jobs: # Headless display required because @vscode/test-electron launches # the real Electron-based VS Code binary. run: xvfb-run -a npm test + + migration-assistant: + # Build pinned tree-sitter-rescript grammar consumed by the + # `.res → .affine` migration assistant (#57 Phase 2). The grammar + # is manifest-vendored (`editors/tree-sitter-rescript/package.json`) + # so this job exists to (a) verify the install script and pinned + # commit still build cleanly and (b) gate `tools/res-to-affine/` + # walker work that depends on the generated parser. + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4 + with: + node-version: "20" + + - name: Install tree-sitter CLI + # npm install of tree-sitter-cli is the fast CI path (~5 s vs. + # ~5 min for `cargo install tree-sitter-cli`). The repo's + # preferred local path is cargo (see editors/tree-sitter-rescript/ + # README.md) — both produce the same `tree-sitter` binary that + # the install script invokes via `command -v`. The version + # tracks `tree-sitter-rescript`'s package.json devDependency + # range. + run: npm install -g tree-sitter-cli@^0.25.0 + + - name: Build pinned tree-sitter-rescript grammar + # Direct script invocation rather than `just install-grammar` — + # GitHub Actions runners do not ship `just` preinstalled, and + # there is no other recipe used in this workflow that justifies + # adding a setup step for it. The justfile recipe still exists + # for local developer ergonomics; both call the same script. + run: ./editors/tree-sitter-rescript/scripts/install.sh + + - name: Verify generated parser + # `tree-sitter generate` is supposed to drop src/parser.c into + # the cloned grammar. If it didn't, the install path is broken + # and Phase-2 walker work cannot proceed; fail loudly here + # rather than at the OCaml link step in a downstream PR. + run: | + test -f tools/vendor/tree-sitter-rescript/src/parser.c \ + || { echo "error: parser.c not produced by tree-sitter generate" >&2; exit 1; } + echo "parser.c size: $(wc -c < tools/vendor/tree-sitter-rescript/src/parser.c) bytes" + + - name: Smoke-parse a sample .res file + # Sanity-check that the grammar actually parses a non-trivial + # ReScript source. Picks the existing res-to-affine test fixture + # so any drift in the pinned commit's syntactic surface area + # surfaces here rather than at walker-rule writing time. + run: | + shopt -s nullglob + fixtures=(tools/res-to-affine/test/fixtures/*.res) + if [ ${#fixtures[@]} -eq 0 ]; then + echo "no .res fixtures to smoke-parse; skipping" + exit 0 + fi + tree-sitter parse \ + --quiet \ + "${fixtures[0]}" \ + --paths tools/vendor/tree-sitter-rescript \ + > /dev/null + echo "smoke-parsed: ${fixtures[0]}" diff --git a/editors/tree-sitter-rescript/README.md b/editors/tree-sitter-rescript/README.md index f5148b0..69b554e 100644 --- a/editors/tree-sitter-rescript/README.md +++ b/editors/tree-sitter-rescript/README.md @@ -25,13 +25,38 @@ snapshots, since AST shapes may shift. ## Install +From the repo root: + ```sh -./scripts/install.sh +just install-grammar # justfile recipe +# or directly: +./editors/tree-sitter-rescript/scripts/install.sh ``` This writes a `tree-sitter-rescript` directory under `tools/vendor/` (gitignored — same convention as the WASI adapter pinning), containing -the generated parser. Requires `git` and `tree-sitter` CLI on PATH. +the generated parser. Requires `git` and the `tree-sitter` CLI on PATH. + +The `tree-sitter` CLI can be installed either way: + +```sh +cargo install tree-sitter-cli # Rust-native, repo-preferred +npm install -g tree-sitter-cli # Node-based, also fine +``` + +CI installs via `npm` for speed (`tree-sitter-cli` from npm is a pre-built +binary, ~5 s install). The `cargo` path builds from source (~5 min on a +cold cache) and is the recommended local install because it keeps the +contributor toolchain centred on Rust rather than Node. The +`package.json` in this directory pins the version range; bump it in +sync when the upstream grammar pin moves. + +## Continuous integration + +The `migration-assistant` job in `.github/workflows/ci.yml` runs `just +install-grammar` on every PR, then smoke-parses +`tools/res-to-affine/test/fixtures/sample.res`. If the pinned commit +stops building cleanly, this job is the first signal. ## Why manifest, not copy diff --git a/editors/tree-sitter-rescript/scripts/install.sh b/editors/tree-sitter-rescript/scripts/install.sh index e4fa37d..9b171f5 100755 --- a/editors/tree-sitter-rescript/scripts/install.sh +++ b/editors/tree-sitter-rescript/scripts/install.sh @@ -15,7 +15,9 @@ BUILD_DIR="${REPO_ROOT}/tools/vendor/tree-sitter-rescript" if ! command -v tree-sitter >/dev/null 2>&1; then echo "error: tree-sitter CLI not found on PATH" >&2 - echo " install via: npm install -g tree-sitter-cli" >&2 + echo " install via either:" >&2 + echo " cargo install tree-sitter-cli (Rust-native, repo-preferred)" >&2 + echo " npm install -g tree-sitter-cli (Node-based, also fine)" >&2 exit 2 fi diff --git a/justfile b/justfile index 527902a..ac0d768 100644 --- a/justfile +++ b/justfile @@ -123,6 +123,16 @@ regen-idaptik-wasm: dune exec affinescript -- tea-bridge -o ../../idaptik/public/assets/wasm/titlescreen.wasm @echo "[AffineTEA] titlescreen.wasm regenerated" +# ── Tooling (manifest-driven dev deps) ──────────────────────────────────────── + +# Fetch + build the pinned tree-sitter-rescript grammar used by the +# `.res → .affine` migration assistant (#57 Phase 2). Output is written +# to `tools/vendor/tree-sitter-rescript/` (gitignored). Requires the +# `tree-sitter` CLI on PATH — install via `cargo install tree-sitter-cli` +# (Rust-native, repo-preferred) or `npm install -g tree-sitter-cli`. +install-grammar: + ./editors/tree-sitter-rescript/scripts/install.sh + # ── Validation ──────────────────────────────────────────────────────────────── # Verify golden path end-to-end