Files
a46aa641f9 feat: add R language support (#8263)
* feat: add R language support

Add R as a new supported scripting language in Windmill, following the
same pattern used for Ruby. Includes:

- Backend: ScriptLang::Rlang enum variant, DB migration, tree-sitter-r
  parser crate with tests, WASM parser binding, R executor with NSJail
  sandboxing, job dispatch and signature parsing
- Frontend: language picker, R icon, syntax highlighting, editor bar
  insertions (Sys.getenv, get_variable, get_resource), schema inference,
  init code template, BETA badge
- CLI: .r extension mapping, sync support, bootstrap template

R scripts use `main <- function(...)` syntax, jsonlite for JSON
serialization, and system curl for the Windmill client helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add R package resolution and installation

Parse library()/require() calls from R scripts to extract dependencies.
Resolve versions from CRAN, cache lockfiles in pip_resolution_cache,
and install packages to a shared R library cache. The run step sets
R_LIBS_USER so installed packages are available to the script.

- Parser: parse_r_requirements() extracts package names from AST
- Executor: resolve() generates lockfile, install() installs from CRAN
- Worker lockfiles: wire up R resolve for dependency jobs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add nsjail sandboxing for R resolve and install phases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: fix R get_variable/get_resource and add sandbox annotation + e2e tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: fix R arg inference with JS fallback parser and get_variable/get_resource

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix flake

* nsjail

* nits

* fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits

- Suppress renv verbose output during resolve and install (controlled by #verbose annotation)
- Filter renv from install list (already loaded, causes noisy restart message)
- Log compact "resolved N packages" instead of full renv.lock JSON
- Add R (r-base, r-cran-renv) to DockerfileFull and DockerfileFullEe
- Use disable_rl for nsjail install config (R compiles from source)
- Reduce default concurrency from 20 to 5
- Add rlang to openflow.openapi.yaml
- Fix MainArgSignature (no_main_func -> auto_kind) after main merge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* final

* fix: remove accidental R install from multiplayer Dockerfile

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: remove R from Windows build and DockerfileExtra

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: rename R migration to avoid timestamp collision with trigger_filter_logic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* all

* fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add clear error when Rscript binary is missing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: fix type errors in R fallback parser, use format! in wrap(), add R system prompts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: pyranota <pyra@duck.com>
2026-04-01 06:11:37 +00:00

75 lines
2.8 KiB
TOML

cargo-features = ["panic-immediate-abort"]
[package]
name = "windmill-parser-wasm"
version.workspace = true
edition.workspace = true
authors.workspace = true
[lib]
crate-type = ["cdylib"]
name = "windmill_parser_wasm"
path = "./src/lib.rs"
[dev-dependencies]
wasm-bindgen-test.workspace = true
windmill-parser-ts.workspace = true
windmill-parser-bash.workspace = true
[profile.release]
panic = "immediate-abort"
[unstable]
build-std = ["std", "panic_abort"]
[features]
default = []
go-parser = [ "dep:windmill-parser-go"]
bash-parser = [ "dep:windmill-parser-bash"]
sql-parser = [ "dep:windmill-parser-sql"]
py-parser = [ "dep:windmill-parser-py"]
ts-parser = [ "dep:windmill-parser-ts"]
php-parser = [ "dep:windmill-parser-php"]
rust-parser = [ "dep:windmill-parser-rust"]
graphql-parser = [ "dep:windmill-parser-graphql"]
ansible-parser = [ "dep:windmill-parser-yaml"]
csharp-parser = [ "dep:windmill-parser-csharp"]
nu-parser = [ "dep:windmill-parser-nu"]
java-parser = [ "dep:windmill-parser-java"]
ruby-parser = [ "dep:windmill-parser-ruby"]
r-parser = [ "dep:windmill-parser-r"]
wac-parser = [ "dep:windmill-parser-wac"]
asset-parser = [ "dep:windmill-parser-ts-asset", "dep:windmill-parser-py-asset", "dep:windmill-parser-sql-asset"]
py-imports-parser = [ "dep:windmill-parser-py-imports"]
[dependencies]
anyhow.workspace = true
windmill-parser.workspace = true
windmill-parser-go = { workspace = true, optional = true }
windmill-parser-bash = { workspace = true, optional = true }
windmill-parser-sql = { workspace = true, optional = true }
windmill-parser-py = { workspace = true, optional = true }
windmill-parser-ts = { workspace = true, optional = true }
windmill-parser-php = { workspace = true, optional = true }
windmill-parser-graphql = { workspace = true, optional = true }
windmill-parser-rust = { workspace = true, optional = true }
windmill-parser-yaml = { workspace = true, optional = true }
windmill-parser-csharp = { workspace = true, optional = true }
windmill-parser-nu = { workspace = true, optional = true }
windmill-parser-java = { workspace = true, optional = true }
windmill-parser-ruby = { workspace = true, optional = true }
windmill-parser-r = { workspace = true, optional = true }
windmill-parser-wac = { workspace = true, optional = true }
windmill-parser-ts-asset = { workspace = true, optional = true }
windmill-parser-py-asset = { workspace = true, optional = true }
windmill-parser-sql-asset = { workspace = true, optional = true }
windmill-parser-py-imports = { workspace = true, optional = true }
wasm-bindgen.workspace = true
serde_json.workspace = true
getrandom = { workspace = true, features = ["js"] }
# getrandom 0.3 is pulled in transitively by rand 0.9 (via windmill-types).
# It requires the "wasm_js" feature to work on wasm32-unknown-unknown.
getrandom3 = { package = "getrandom", version = "0.3", features = ["wasm_js"] }