fix: keep workflow-as-code scripts off dedicated workers (#10805)

* fix: keep workflow-as-code scripts off dedicated workers

A dedicated subprocess calls the script's `main`. A workflow-as-code v2
entrypoint exports none, so a WAC script configured as a dedicated worker
failed every run with `entry.module.main is not a function`, and its
checkpoint/dispatch round-trip never ran at all.

Leave such a script unregistered in the dedicated worker map instead. The
worker still holds the script's dedicated tag, so the job falls through to
the regular executor on the same worker and runs correctly; rejecting it at
push time would strand it, since nothing else pulls that tag.

`is_wac_v2` covers only the languages whose executor actually routes a
workflow through the WAC runner: Deno runs a WAC-shaped script as a plain
`main`, so claiming it is WAC would deny it a path it uses correctly today.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VMNiDoBuUY9jzqcuFLT2wU

* chore: update ee-repo-ref to ac02c4696ea0be6a8b8ae154ddd7521bc1c3bbc0

This commit updates the EE repository reference after PR #740 was merged in windmill-ee-private.

Previous ee-repo-ref: bf742f6ea4d435bd47c9ee0ac5ad800925d79672

New ee-repo-ref: ac02c4696ea0be6a8b8ae154ddd7521bc1c3bbc0

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
Ruben Fiszel
2026-08-22 10:57:16 +02:00
committed by GitHub
co-authored by Claude Opus 5 windmill-internal-app[bot]
parent 1a506b8f22
commit 01891cd732
2 changed files with 42 additions and 1 deletions
+1 -1
View File
@@ -1 +1 @@
54bf630681000c8ed87a7067e357118e015123b1
ac02c4696ea0be6a8b8ae154ddd7521bc1c3bbc0
@@ -4,6 +4,7 @@ use serde_json::Value;
use uuid::Uuid;
use windmill_common::error::{self, Error};
use windmill_common::scripts::ScriptLang;
use windmill_common::DB;
// Checkpoint model + persistence primitives live in windmill-common so the
@@ -346,3 +347,43 @@ pub fn is_wac_v2_py(code: &str) -> bool {
}
has_wmill_import && has_workflow_decorator
}
/// Whether `content` is a workflow-as-code v2 entrypoint, for the languages whose
/// executor routes it through the WAC runner.
///
/// Mirrors exactly what `handle_bun_job` / `handle_python_job` test: a language
/// missing here (Deno) runs a WAC-shaped script as a plain `main`, so claiming it
/// is WAC would deny it paths it uses correctly today.
pub fn is_wac_v2(lang: Option<ScriptLang>, content: &str) -> bool {
match lang {
Some(ScriptLang::Bun) | Some(ScriptLang::Bunnative) => is_wac_v2_ts(content),
Some(ScriptLang::Python3) => is_wac_v2_py(content),
_ => false,
}
}
#[cfg(test)]
mod tests {
use super::*;
const WAC_TS: &str = r#"import { task, workflow } from "windmill-client";
export default workflow(async function main(x: number) { return x; });"#;
const WAC_PY: &str = "import wmill\n@workflow\ndef main(x: int):\n return x\n";
/// Callers use this to decide whether a script may run somewhere that only knows how
/// to call `main`. Widening it to a language whose executor ignores WAC (Deno) would
/// take that path away from scripts that use it correctly, and narrowing it would let
/// a workflow reach a runner that cannot run it.
#[test]
fn only_the_languages_whose_executor_runs_wac_report_it() {
assert!(is_wac_v2(Some(ScriptLang::Bun), WAC_TS));
assert!(is_wac_v2(Some(ScriptLang::Bunnative), WAC_TS));
assert!(is_wac_v2(Some(ScriptLang::Python3), WAC_PY));
assert!(!is_wac_v2(Some(ScriptLang::Deno), WAC_TS));
assert!(!is_wac_v2(None, WAC_TS));
assert!(!is_wac_v2(
Some(ScriptLang::Bun),
"export async function main() {}"
));
}
}