* fix(cli): only preserve case for raw-app runnableIds, not app/flow summaries
PR #8940 stopped lowercasing in sanitizeForFilesystem to fix#8939, where
a raw-app runnableId like CamelCaseTSRunnable produced a CamelCase YAML
metadata file but a lowercased code file, making them desync and
register as duplicate runnables on push.
That fix overshot. sanitizeForFilesystem is also reached by
newPathAssigner, which serves normal apps and flows where the input is
the script's human summary ("Get Users Data") rather than an identifier.
There the on-disk filename is the only artifact — there's no companion
YAML to keep in sync — so lowercasing was the right behavior. Removing
it changed both the on-disk filename and the !inline reference in
app.yaml / flow.yaml from get_users_data.inline_script.ts to
Get_Users_Data.inline_script.ts on the next pull, surfacing as
unwanted case churn for users updating to 1.693.x.
Add a preserveCase option to sanitizeForFilesystem (default false →
lowercase). newRawAppPathAssigner opts in; newPathAssigner stays on
the default. Update unit tests accordingly and add an end-to-end
raw-app round-trip in raw_app_sync.test.ts that pushes a CamelCase
backend runnable, pulls it back, and asserts both YAML and code file
preserve case with no lowercase orphan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(cli): use readdir for exact-case orphan check on Windows
The CamelCase round-trip test used fileExists("camelcasetsrunnable.ts")
to assert no lowercase orphan was produced, which false-positives on
Windows since the filesystem is case-insensitive and resolves the
lookup to the existing CamelCaseTSRunnable.ts. Switch to readdir +
toContain so the exact on-disk casing is compared identically on Linux
and Windows.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(cli): preserve case in raw-app runnable filenames
The path assigner lowercased filesystem-safe names, so a raw-app
runnable id like CamelCaseTSRunnable produced a YAML metadata file
keeping the original case but a code file lowercased to
camelcasetsrunnable.ts. On the next push, loadRunnablesFromBackend
paired the two by case-sensitive name match, failed, and registered
the lowercase code file as a separate empty runnable — surfacing as
duplicate runnables in the app editor.
Stop lowercasing in sanitizeForFilesystem and dedupe path assigners
case-insensitively so case-only collisions still get a counter on
case-insensitive filesystems. Also match content/lock files and the
processed-id set case-insensitively in loadRunnablesFromBackend so
repos already pulled by the buggy CLI can recover on the next push
without re-pulling.
Fixes#8939
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(cli): extract readSiblingLock helper, drop test #ref comments
Address review:
- Both call sites in loadRunnablesFromBackend now use the same
case-insensitive lock-file lookup, so a partial-legacy repo with a
mixed-case code file and lowercase lock (or vice versa) works in the
orphan-code branch too, not just the YAML branch.
- Remove `Regression for #8939 …` comments from the new tests; CLAUDE.md
bans referencing the current task/issue from source comments. Test
names already describe the behavior under test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(cli): update assigner-path assertions for case preservation
Three tests in inline_scripts_failure_preprocessor_unit.test.ts asserted
that the assigner produced lowercased filenames (get_users_data, step_b)
from mixed-case summaries — that was the buggy lowercasing behavior.
With case preserved end-to-end, the assigner now returns Get_Users_Data
and Step_B.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* 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>
* fix: sanitize flow step summaries for filesystem-safe names
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: bump windmill-utils-internal to 1.3.6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: handle Windows reserved device names in flow step sanitization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: collapse consecutive underscores in sanitized flow step names
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: bump windmill-utils-internal to 1.3.7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* bump
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>