A native-speed rewrite of the roblox-ts compiler in golang
rotor CONTRIBUTING.md
3.7 kB · 62 lines
Markdown

Contributing to rotor #

Building #

Requires Go 1.25+:

git clone https://github.com/uproot/rotor && cd rotor
go build ./cmd/rotor

Running the tests #

go test ./internal/... -count=1                           # full test suite
go test ./internal/diff/ -v -run TestDifferential          # differential suite only (see below)
go test ./internal/luau/render/ -bench . -benchmem        # renderer benchmarks
go test ./internal/spike/ -v                              # checker integration spike
go vet ./internal/...                                     # required clean before commits

No Node is required to run rotor itself or the committed differential goldens. A clean clone still needs fixture dependencies installed inside testdata/diff/project, testdata/conformance/project, and testdata/transformers/project (plus tools/sidecar) before the project-layer, conformance, and real-package transformer suites run. Use bun install --no-save first; npm install --no-audit --no-fund still works as a fallback.

The differential suite (how rotor proves byte-parity) #

internal/diff compiles every fixture project under testdata/diff/project/src/ with rotor and byte-compares the output against committed goldens in testdata/diff/golden/ — which were generated by the real rbxtsc 3.0.0. A fixture passes only when rotor's output is byte-identical; the first diverging line is reported.

Adding a fixture:

  1. Write the TypeScript in testdata/diff/project/src/ (it must compile cleanly under rbxtsc).
  2. Regenerate goldens: powershell -File tools/oracle/oracle.ps1 (this is the only step that needs the JS toolchain — the script prefers Bun for fixture installs, falls back to npm, and runs the pinned roblox-ts@3.0.0 over the fixture project).
  3. Enable the fixture in internal/diff/manifest.go and run go test ./internal/diff/ -v.

Existing goldens must stay byte-unchanged when regenerating — git diff testdata/diff/golden/ should only show your new files.

Releasing a new version #

rotor's version is defined in code: internal/version/version.go. Maintainer flow:

  1. Bump the Version constant (e.g. "1.4.0") and package.json's version in lockstep (the npm shim derives its binary-download URL from it) and commit.
  2. Tag and push — the tag must match the constant:
git tag v1.4.0
git push origin v1.4.0

The tag triggers the release GitHub Actions workflow, which verifies the tag matches internal/version, runs the test suite, cross-builds rotor for Windows/macOS/Linux (amd64 + arm64) via GoReleaser, and publishes the archives, checksums, and GitHub Release automatically. A tag that doesn't match the code version fails the workflow before anything is published.

Project docs #

Ground rules #

  • Byte-parity is law: everything that compiles must be byte-identical to rbxtsc 3.0.0. Never silently emit different output — fail loudly with a "not yet supported" diagnostic instead.
  • tsgo/ is a generated mirror — never edit it by hand; regenerate with go run ./tools/mirror.
  • go vet ./internal/... must be clean before commits.