mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 16:05:43 +00:00
* fix: keep pinned import versions of imported scripts in bun lockfiles Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: guard pinned imports through an unlocked multi-file bun run Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
217 lines
6.2 KiB
Rust
217 lines
6.2 KiB
Rust
use serde_json::json;
|
|
use sqlx::postgres::Postgres;
|
|
use sqlx::Pool;
|
|
use std::collections::HashMap;
|
|
use windmill_common::jobs::{JobPayload, RawCode};
|
|
use windmill_common::scripts::{ScriptLang, ScriptModule};
|
|
use windmill_test_utils::*;
|
|
|
|
// ============================================================================
|
|
// Python: script with inline module via relative import
|
|
// ============================================================================
|
|
|
|
#[cfg(feature = "python")]
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_python_script_with_module(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
initialize_tracing().await;
|
|
let server = ApiServer::start(db.clone()).await?;
|
|
let port = server.addr.port();
|
|
|
|
let main_content = r#"
|
|
from .helper import greet
|
|
|
|
def main(name: str):
|
|
return greet(name)
|
|
"#
|
|
.to_owned();
|
|
|
|
let mut modules = HashMap::new();
|
|
modules.insert(
|
|
"helper.py".to_string(),
|
|
ScriptModule {
|
|
content: "def greet(name):\n return f\"hello {name}\"\n".to_string(),
|
|
language: ScriptLang::Python3,
|
|
lock: None,
|
|
},
|
|
);
|
|
|
|
let job = JobPayload::Code(RawCode {
|
|
content: main_content,
|
|
path: Some("f/test/my_script".to_string()),
|
|
language: ScriptLang::Python3,
|
|
modules: Some(modules),
|
|
tag: None,
|
|
..RawCode::default()
|
|
});
|
|
|
|
let result = RunJob::from(job)
|
|
.arg("name", json!("world"))
|
|
.run_until_complete(&db, false, port)
|
|
.await
|
|
.json_result()
|
|
.unwrap();
|
|
|
|
assert_eq!(result, json!("hello world"));
|
|
Ok(())
|
|
}
|
|
|
|
// ============================================================================
|
|
// Python: nested module path (subdirectory)
|
|
// ============================================================================
|
|
|
|
#[cfg(feature = "python")]
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_python_script_with_nested_module(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
initialize_tracing().await;
|
|
let server = ApiServer::start(db.clone()).await?;
|
|
let port = server.addr.port();
|
|
|
|
let main_content = r#"
|
|
from .utils.math import add
|
|
|
|
def main(a: int, b: int):
|
|
return add(a, b)
|
|
"#
|
|
.to_owned();
|
|
|
|
let mut modules = HashMap::new();
|
|
modules.insert(
|
|
"utils/__init__.py".to_string(),
|
|
ScriptModule { content: "".to_string(), language: ScriptLang::Python3, lock: None },
|
|
);
|
|
modules.insert(
|
|
"utils/math.py".to_string(),
|
|
ScriptModule {
|
|
content: "def add(a, b):\n return a + b\n".to_string(),
|
|
language: ScriptLang::Python3,
|
|
lock: None,
|
|
},
|
|
);
|
|
|
|
let job = JobPayload::Code(RawCode {
|
|
content: main_content,
|
|
path: Some("f/test/my_script".to_string()),
|
|
language: ScriptLang::Python3,
|
|
modules: Some(modules),
|
|
tag: None,
|
|
..RawCode::default()
|
|
});
|
|
|
|
let result = RunJob::from(job)
|
|
.arg("a", json!(3))
|
|
.arg("b", json!(4))
|
|
.run_until_complete(&db, false, port)
|
|
.await
|
|
.json_result()
|
|
.unwrap();
|
|
|
|
assert_eq!(result, json!(7));
|
|
Ok(())
|
|
}
|
|
|
|
// ============================================================================
|
|
// Bun: script with inline module via relative import
|
|
// ============================================================================
|
|
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_bun_script_with_module(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
initialize_tracing().await;
|
|
let server = ApiServer::start(db.clone()).await?;
|
|
let port = server.addr.port();
|
|
|
|
let main_content = r#"
|
|
import { greet } from "./helper.ts";
|
|
|
|
export function main(name: string) {
|
|
return greet(name);
|
|
}
|
|
"#
|
|
.to_owned();
|
|
|
|
let mut modules = HashMap::new();
|
|
modules.insert(
|
|
"helper.ts".to_string(),
|
|
ScriptModule {
|
|
content:
|
|
"export function greet(name: string): string {\n return `hello ${name}`;\n}\n"
|
|
.to_string(),
|
|
language: ScriptLang::Bun,
|
|
lock: None,
|
|
},
|
|
);
|
|
|
|
let job = JobPayload::Code(RawCode {
|
|
content: main_content,
|
|
path: Some("f/test/my_script".to_string()),
|
|
language: ScriptLang::Bun,
|
|
modules: Some(modules),
|
|
tag: None,
|
|
..RawCode::default()
|
|
});
|
|
|
|
let result = RunJob::from(job)
|
|
.arg("name", json!("world"))
|
|
.run_until_complete(&db, false, port)
|
|
.await
|
|
.json_result()
|
|
.unwrap();
|
|
|
|
assert_eq!(result, json!("hello world"));
|
|
Ok(())
|
|
}
|
|
|
|
/// A multi-file script run without a lock is bundled by the lockfile build. A pinned import in
|
|
/// a workspace script it imports must be installed at that version and still resolve at run time.
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn test_bun_module_imports_pinned_workspace_script(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
initialize_tracing().await;
|
|
let server = ApiServer::start(db.clone()).await?;
|
|
let port = server.addr.port();
|
|
|
|
sqlx::query(
|
|
"INSERT INTO script (workspace_id, created_by, content, schema, summary, description, path, hash, language, lock)
|
|
VALUES ('test-workspace', 'test-user', $1, '{}', '', '', 'f/system/pinned_module', 12350, 'bun', '')",
|
|
)
|
|
.bind(
|
|
r#"
|
|
import _ from "lodash@4.17.20";
|
|
export function lodashVersion() { return _.VERSION; }
|
|
"#,
|
|
)
|
|
.execute(&db)
|
|
.await?;
|
|
|
|
let mut modules = HashMap::new();
|
|
modules.insert(
|
|
"helper.ts".to_string(),
|
|
ScriptModule {
|
|
content: "export function label(v: string) { return v; }\n".to_string(),
|
|
language: ScriptLang::Bun,
|
|
lock: None,
|
|
},
|
|
);
|
|
|
|
let job = JobPayload::Code(RawCode {
|
|
content: r#"
|
|
import { lodashVersion } from "/f/system/pinned_module";
|
|
import { label } from "./helper.ts";
|
|
export function main() { return label(lodashVersion()); }
|
|
"#
|
|
.to_owned(),
|
|
path: Some("f/system/my_script".to_string()),
|
|
language: ScriptLang::Bun,
|
|
modules: Some(modules),
|
|
tag: None,
|
|
..RawCode::default()
|
|
});
|
|
|
|
let result = RunJob::from(job)
|
|
.run_until_complete(&db, false, port)
|
|
.await
|
|
.json_result()
|
|
.unwrap();
|
|
|
|
assert_eq!(result, json!("4.17.20"));
|
|
Ok(())
|
|
}
|