Skip to content

feat(res-to-affine): land tree-sitter grammar build pipeline (Phase 2a, Refs #57) #579

feat(res-to-affine): land tree-sitter grammar build pipeline (Phase 2a, Refs #57)

feat(res-to-affine): land tree-sitter grammar build pipeline (Phase 2a, Refs #57) #579

Workflow file for this run

# SPDX-License-Identifier: MPL-2.0
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up OCaml
uses: ocaml/setup-ocaml@e32b06a3e831ff2fbc6f08cf35be2085e3918014 # v3
with:
ocaml-compiler: "5.1"
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with:
node-version: "20"
- name: Install dependencies
run: opam install . --deps-only --with-test --with-doc
- name: Build
run: opam exec -- dune build
- name: Run tests
run: opam exec -- dune runtest
- name: Run codegen WASM tests
run: opam exec -- ./tools/run_codegen_wasm_tests.sh
- name: Run codegen Deno-ESM tests (issue #122)
# Compiles tests/codegen-deno/*.affine with the --deno-esm backend
# and runs the *.harness.mjs under Node (CI has Node 20, not Deno;
# the Phase 1 fixtures are pure logic so Node ESM exercises them).
run: opam exec -- ./tools/run_codegen_deno_tests.sh
- name: Run face-transformer regression tests
run: opam exec -- ./tools/run_face_transformer_tests.sh
- name: Issue #35 Phase 3 — block extension.ts regression
# The vscode extension is now authored in extension.affine and
# compiled to extension.cjs. Re-introducing extension.ts would
# silently drift the source-of-truth back to TypeScript, which
# the policy forbids. See tools/check-no-extension-ts.sh for
# rationale + recovery instructions.
run: ./tools/check-no-extension-ts.sh
- name: Check formatting
run: opam exec -- dune build @fmt
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up OCaml
uses: ocaml/setup-ocaml@e32b06a3e831ff2fbc6f08cf35be2085e3918014 # v3
with:
ocaml-compiler: "5.1"
- name: Install dependencies
# Match the build job: `dune build` compiles everything including
# test/ (which depends on alcotest, with-test) and the @doc target
# below (which depends on odoc, with-doc). Without these flags, lint
# fails on missing alcotest before it ever reaches the doc step.
run: opam install . --deps-only --with-test --with-doc
- name: Build
run: opam exec -- dune build
- name: Lint with odoc
run: opam exec -- dune build @doc
continue-on-error: true
vscode-smoke:
# In-editor end-to-end smoke test for the .affine VS Code extension
# (issue #139). Loads the compiled out/extension.cjs in a real VS Code
# host via @vscode/test-electron and asserts: activation, command
# registration + invocation, restartLsp cycling, and deactivate
# teardown. The Node-based runner is a documented runtime carve-out
# (see CLAUDE.md "Runtime Exemptions") because the VS Code extension
# host is npm/Node-native and no Deno/JSR equivalent exists.
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 test runner dependencies
working-directory: editors/vscode
# The compiled out/extension.cjs is checked in (see #35 Phase 3),
# so the smoke test does not need the OCaml toolchain — only the
# Node-side test runner deps. peerDeps `vscode` is provided by
# @vscode/test-electron at launch; the extension's runtime dep on
# @hyperpolymath/affine-vscode is satisfied by npm install too.
run: npm install --no-audit --no-fund
- name: Run in-editor smoke (xvfb)
working-directory: editors/vscode
# 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]}"