mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-27 08:02:39 +00:00
feat: resolve relative imports from local content in script/flow preview (#9233)
* feat: thread temp_script_refs into preview jobs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: resolve python preview relative imports from temp script refs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: use local relative imports in wmill script preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: use local relative imports in wmill flow preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: add temp_script_refs to Preview and FlowPreview openapi schemas Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: pass temp_script_refs to bun lockfile gen for no-lock preview Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: route script preview through shared buildPreviewTempScriptRefs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: resolve local relative imports in wmill app dev inline scripts Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address cubic review — bundle cache key, preview-mode gate, error masking Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * perf: skip dep-tree build when previewed script has no relative imports; narrow old-backend classifier Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address review issues (preview-only gate, bundle preview, app dev cwd) Three P1s flagged in repeated codex/pi reviews on PR #9233: - Gate _TEMP_SCRIPT_REFS extraction on JobKind::Preview (bun + python executors) and propagation in worker_flow on JobKind::FlowPreview. job.args includes caller-controlled request args, so honoring this key on deployed runs would let a caller swap import resolution to local content uploaded via /raw_temp. - run_bundle_preview_script now injects temp_script_refs into PushArgs.extra, mirroring run_preview_script — closes the silent data drop for the bundle preview path. - wmill app dev chdirs to the wmill.yaml root before buildPreviewTempScriptRefs and restores after, so the `cd <app>__raw_app && wmill app dev` invocation (cwd is the raw_app folder, no app_folder arg) still walks sibling workspace scripts like f/lib.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 5b347d6 (handle_python_deps arity fix) Picks up the EE arity fix so cargo_test + check_ee_full compile cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 52e273d (agent-workers bundle path arity fix) Picks up windmill-ee-private 52e273d which adds the missing &None arg to compute_bundle_local_and_remote_path in windmill-api-agent-workers/src/ee.rs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ee): bump ee-repo-ref to 2d6ffd3 (EE main merged in) Previous bump pinned an older EE commit, missing the audit-log object-store export module (EE PR #579, commit ec3cd35) and other EE main updates. The CE backend's `crate::ee_oss::anchor_audit_logs_s3_checkpoint_env_var` and `export_audit_logs_to_object_store` references need the new EE definitions. Merged origin/main into the EE branch and pinned the merge commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to b0c87b1272c25dca4aa9148c87fb024a9d9ef322 This commit updates the EE repository reference after PR #583 was merged in windmill-ee-private. Previous ee-repo-ref: 2d6ffd32c99bd93e79cf78675cb89499a81b17e1 New ee-repo-ref: b0c87b1272c25dca4aa9148c87fb024a9d9ef322 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.7 (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:
co-authored by
Claude Opus 4.7
windmill-internal-app[bot]
parent
f6fcdb5599
commit
2a780ad87a
@@ -31,6 +31,7 @@ use windmill_common::{
|
||||
self,
|
||||
Error::{self},
|
||||
},
|
||||
jobs::JobKind,
|
||||
scripts::ScriptLang,
|
||||
utils::calculate_hash,
|
||||
worker::{
|
||||
@@ -119,6 +120,18 @@ const NSJAIL_CONFIG_DOWNLOAD_PY_CONTENT: &str = include_str!("../nsjail/download
|
||||
const NSJAIL_CONFIG_RUN_PYTHON3_CONTENT: &str = include_str!("../nsjail/run.python3.config.proto");
|
||||
pub const RELATIVE_PYTHON_LOADER: &str = include_str!("../loader.py");
|
||||
|
||||
/// Render loader.py with the TEMP_SCRIPT_REFS placeholder substituted by a
|
||||
/// Python dict literal. Preview jobs pass a path -> temp-hash map so relative
|
||||
/// imports resolve from not-yet-deployed local content; deployed runs pass
|
||||
/// `None` which renders an empty dict (deployed resolution unchanged).
|
||||
fn render_relative_python_loader(temp_script_refs: &Option<HashMap<String, String>>) -> String {
|
||||
let temp_refs_py = temp_script_refs
|
||||
.as_ref()
|
||||
.and_then(|m| serde_json::to_string(m).ok())
|
||||
.unwrap_or_else(|| "{}".to_string());
|
||||
RELATIVE_PYTHON_LOADER.replace("TEMP_SCRIPT_REFS_PLACEHOLDER", &temp_refs_py)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "private", test))]
|
||||
pub fn has_relative_imports(content: &str) -> bool {
|
||||
RELATIVE_IMPORT_REGEX.is_match(content)
|
||||
@@ -643,6 +656,21 @@ pub async fn handle_python_job(
|
||||
));
|
||||
}
|
||||
|
||||
// Preview jobs may carry _TEMP_SCRIPT_REFS so relative imports resolve from
|
||||
// not-yet-deployed local content uploaded to raw_script_temp. Gated on
|
||||
// JobKind::Preview because job.args includes caller-controlled request
|
||||
// args; honoring this key on deployed runs would let a caller swap import
|
||||
// resolution targets in deployed code.
|
||||
let temp_script_refs: Option<HashMap<String, String>> = if matches!(job.kind, JobKind::Preview)
|
||||
{
|
||||
job.args
|
||||
.as_ref()
|
||||
.and_then(|x| x.get("_TEMP_SCRIPT_REFS"))
|
||||
.and_then(|v| serde_json::from_str(v.get()).ok())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (py_version, mut additional_python_paths) = handle_python_deps(
|
||||
job_dir,
|
||||
requirements_o,
|
||||
@@ -658,6 +686,7 @@ pub async fn handle_python_job(
|
||||
&mut Some(occupancy_metrics),
|
||||
precomputed_agent_info,
|
||||
annotations.clone(),
|
||||
&temp_script_refs,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -709,6 +738,7 @@ pub async fn handle_python_job(
|
||||
job.script_entrypoint_override.as_deref(),
|
||||
inner_content,
|
||||
&script_path,
|
||||
&temp_script_refs,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -1532,6 +1562,7 @@ async fn prepare_wrapper(
|
||||
job_script_entrypoint_override: Option<&str>,
|
||||
inner_content: &str,
|
||||
script_path: &str,
|
||||
temp_script_refs: &Option<HashMap<String, String>>,
|
||||
) -> error::Result<(
|
||||
&'static str,
|
||||
&'static str,
|
||||
@@ -1571,7 +1602,11 @@ async fn prepare_wrapper(
|
||||
|
||||
let _ = write_file(&module_dir, &format!("{last}.py"), inner_content)?;
|
||||
if relative_imports {
|
||||
let _ = write_file(job_dir, "loader.py", RELATIVE_PYTHON_LOADER)?;
|
||||
let _ = write_file(
|
||||
job_dir,
|
||||
"loader.py",
|
||||
&render_relative_python_loader(temp_script_refs),
|
||||
)?;
|
||||
}
|
||||
|
||||
let sig = windmill_parser_py::parse_python_signature(
|
||||
@@ -1768,6 +1803,7 @@ pub(crate) async fn handle_python_deps(
|
||||
occupancy_metrics: &mut Option<&mut OccupancyMetrics>,
|
||||
precomputed_agent_info: Option<PrecomputedAgentInfo>,
|
||||
annotations: PythonAnnotations,
|
||||
temp_script_refs: &Option<HashMap<String, String>>,
|
||||
) -> error::Result<(PyV, Vec<String>)> {
|
||||
create_dependencies_dir(job_dir).await;
|
||||
|
||||
@@ -1796,7 +1832,7 @@ pub(crate) async fn handle_python_deps(
|
||||
&mut version_specifiers,
|
||||
&mut locked_v,
|
||||
&None,
|
||||
&None, // temp_script_refs: only used during CLI lock generation
|
||||
temp_script_refs,
|
||||
))
|
||||
.await?;
|
||||
|
||||
@@ -3042,7 +3078,8 @@ pub async fn start_worker(
|
||||
|
||||
let any_relative_imports = RELATIVE_IMPORT_REGEX.is_match(inner_content);
|
||||
if any_relative_imports {
|
||||
let _ = write_file(job_dir, "loader.py", RELATIVE_PYTHON_LOADER)?;
|
||||
// Dedicated worker runs deployed scripts only — no temp refs.
|
||||
let _ = write_file(job_dir, "loader.py", &render_relative_python_loader(&None))?;
|
||||
}
|
||||
|
||||
let mut mem_peak: i32 = 0;
|
||||
@@ -3087,6 +3124,7 @@ pub async fn start_worker(
|
||||
&mut None,
|
||||
None,
|
||||
annotations,
|
||||
&None, // dedicated worker runs deployed scripts only
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user