fix: improve windows compatibility

* ci: add Windows backend integration test workflow

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

* ci: temporarily add push trigger for testing

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

* ci: add --no-fail-fast to run all test binaries

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

* fix: Windows path handling for backend integration tests

- WINDMILL_DIR: use std::env::temp_dir() on Windows instead of /tmp/windmill
- HOME_ENV: fall back to USERPROFILE on Windows when HOME is not set
- loader.bun.js: normalize paths to forward slashes for consistent
  comparison with Bun's resolver output on Windows
- bun_executor.rs: convert job_dir to forward slashes in JS template
  strings to avoid backslash escape issues (\t -> tab, etc.)
- go_executor.rs: fix windows_gopath() double backslash bug (r"\\" -> "\\")
- bash_executor.rs: default to "bash" (in PATH) on Windows instead of /bin/bash

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

* fix: improve Windows diagnostics and fix onLoad handler

- Include path in create_directory_async/sync panic messages
- Add WINDMILL_DIR initialization debug output
- Fix loader.bun.js onLoad: use properly escaped regex instead of
  returning undefined (Bun requires onLoad to return an object)
- Add env var debug output to CI workflow

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

* fix: sanitize Windows-invalid characters in test worker names and fix cargo path

- Replace :: with __ in worker names (colons illegal in Windows dir names)
- Fix HOME_DIR to fall back to USERPROFILE on Windows
- Add PATH fallback for cargo discovery on Windows
- Add debug logging to bun loader for fetch errors

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

* fix: handle single colons in worker names, pass MSVC linker env vars, revert bun debug

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

* fix: use .exe binary name on Windows and normalize bun import URL paths

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

* fix: use absolute path for rust binary, normalize bun resolve paths

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

* fix: use .wurl extension instead of .url for bun import resolution on Windows

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

* fix: use custom namespace for bun plugin to bypass default file resolution

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

* fix: use virtual namespace for bun import resolution to avoid Windows path issues

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

* fix: handle Windows 8.3 paths and namespace-prefixed importers in bun loader

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

* fix: strip namespace prefix from args.path and handle absolute imports without leading slash in bun loader

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

* refactor: simplify bun loader and remove redundant cargo path lookups

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

* fix: use platform-specific cargo binary path with .exe on Windows

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

* refactor: replace HOME_DIR with HOME_ENV in rust_executor to remove duplication

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

* refactor: keep original bun loader on linux, use virtual namespace loader only on windows

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-03-04 20:20:18 +00:00
committed by GitHub
parent 26f5cd6b8e
commit ac71232b95
10 changed files with 371 additions and 34 deletions
+165
View File
@@ -0,0 +1,165 @@
name: Backend integration tests (Windows)
on:
workflow_dispatch:
push:
branches:
- "ci-windows-tests"
env:
CARGO_INCREMENTAL: 0
SQLX_OFFLINE: true
DISABLE_EMBEDDING: true
jobs:
cargo_test_windows:
runs-on: blacksmith-16vcpu-windows-2025
steps:
- uses: actions/checkout@v4
- name: Read EE repo commit hash
shell: pwsh
run: |
$ee_repo_ref = Get-Content .\backend\ee-repo-ref.txt
echo "ee_repo_ref=$ee_repo_ref" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Checkout windmill-ee-private repository
uses: actions/checkout@v4
with:
repository: windmill-labs/windmill-ee-private
path: ./windmill-ee-private
ref: ${{ env.ee_repo_ref }}
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
fetch-depth: 0
- name: Substitute EE code
shell: bash
run: |
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
- name: Setup PostgreSQL
uses: ikalnytskyi/action-setup-postgres@v6
with:
username: postgres
password: changeme
database: windmill
port: 5432
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: backend
toolchain: 1.93.0
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.x"
- uses: denoland/setup-deno@v2
with:
deno-version: v2.x
- uses: actions/setup-go@v2
with:
go-version: 1.21.5
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.10
- uses: actions/setup-node@v4
with:
node-version: "20"
- uses: astral-sh/setup-uv@v6.2.1
with:
version: "0.9.24"
- uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
tools: composer
- name: Install windmill CLI
shell: bash
run: |
cd cli
bash gen_wm_client.sh
bun install
mkdir -p "$HOME/.local/bin"
printf '#!/bin/sh\nexec bun run "%s/cli/src/main.ts" "$@"\n' "$GITHUB_WORKSPACE" > "$HOME/.local/bin/wmill"
chmod +x "$HOME/.local/bin/wmill"
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install OpenSSL via vcpkg
run: |
vcpkg.exe install openssl-windows:x64-windows
vcpkg.exe install openssl:x64-windows-static
vcpkg.exe integrate install
- name: Get runtime paths
id: runtime-paths
shell: pwsh
run: |
echo "DENO_PATH=$($(Get-Command deno).Source)" >> $env:GITHUB_OUTPUT
echo "BUN_PATH=$($(Get-Command bun).Source)" >> $env:GITHUB_OUTPUT
echo "NODE_BIN_PATH=$($(Get-Command node).Source)" >> $env:GITHUB_OUTPUT
echo "GO_PATH=$($(Get-Command go).Source)" >> $env:GITHUB_OUTPUT
echo "UV_PATH=$($(Get-Command uv).Source)" >> $env:GITHUB_OUTPUT
echo "PHP_PATH=$($(Get-Command php).Source)" >> $env:GITHUB_OUTPUT
echo "COMPOSER_PATH=$($(Get-Command composer).Source)" >> $env:GITHUB_OUTPUT
echo "POWERSHELL_PATH=$($(Get-Command pwsh).Source)" >> $env:GITHUB_OUTPUT
echo "DOTNET_PATH=$($(Get-Command dotnet).Source)" >> $env:GITHUB_OUTPUT
- name: Build DuckDB FFI module
working-directory: backend/windmill-duckdb-ffi-internal
timeout-minutes: 30
run: |
cargo build --release -p windmill_duckdb_ffi_internal
New-Item -ItemType Directory -Path ..\target\debug -Force
Copy-Item target\release\windmill_duckdb_ffi_internal.dll ..\target\debug\
- name: Print runtime versions and env
shell: pwsh
run: |
deno --version
bun -v
node --version
go version
python3 --version
php --version
pwsh --version
dotnet --version
echo "TEMP=$env:TEMP"
echo "TMP=$env:TMP"
echo "USERPROFILE=$env:USERPROFILE"
echo "HOME=$env:HOME"
- name: cargo test
working-directory: backend
timeout-minutes: 60
env:
DATABASE_URL: postgres://postgres:changeme@localhost:5432/windmill
RUST_LOG: "off"
RUST_LOG_STYLE: never
CARGO_NET_GIT_FETCH_WITH_CLI: true
CARGO_BUILD_JOBS: 12
VCPKGRS_DYNAMIC: 1
OPENSSL_DIR: ${{ env.VCPKG_INSTALLATION_ROOT }}\installed\x64-windows-static
DENO_PATH: ${{ steps.runtime-paths.outputs.DENO_PATH }}
BUN_PATH: ${{ steps.runtime-paths.outputs.BUN_PATH }}
NODE_BIN_PATH: ${{ steps.runtime-paths.outputs.NODE_BIN_PATH }}
GO_PATH: ${{ steps.runtime-paths.outputs.GO_PATH }}
UV_PATH: ${{ steps.runtime-paths.outputs.UV_PATH }}
PHP_PATH: ${{ steps.runtime-paths.outputs.PHP_PATH }}
COMPOSER_PATH: ${{ steps.runtime-paths.outputs.COMPOSER_PATH }}
POWERSHELL_PATH: ${{ steps.runtime-paths.outputs.POWERSHELL_PATH }}
DOTNET_PATH: ${{ steps.runtime-paths.outputs.DOTNET_PATH }}
WMDEBUG_FORCE_V0_WORKSPACE_DEPENDENCIES: 1
WMDEBUG_FORCE_RUNNABLE_SETTINGS_V0: 1
WMDEBUG_FORCE_NO_LEGACY_DEBOUNCING_COMPAT: 1
run: >
cargo test
--no-fail-fast
--features enterprise,deno_core,duckdb,license,python,rust,scoped_cache,parquet,private,csharp,php,quickjs,mcp,run_inline
--all
-- --nocapture --test-threads=10
+2 -2
View File
@@ -314,14 +314,14 @@ pub async fn create_directory_async(directory_path: &str) {
.recursive(true)
.create(directory_path)
.await
.expect("could not create dir");
.unwrap_or_else(|e| panic!("could not create dir '{}': {}", directory_path, e));
}
pub fn create_directory_sync(directory_path: &str) {
SyncDirBuilder::new()
.recursive(true)
.create(directory_path)
.expect("could not create dir");
.unwrap_or_else(|e| panic!("could not create dir '{}': {}", directory_path, e));
}
#[track_caller]
+11 -1
View File
@@ -494,7 +494,17 @@ pub async fn store_pull_query(wc: &WorkerConfig) {
lazy_static::lazy_static! {
pub static ref WINDMILL_DIR: String = {
let dir = std::env::var("WINDMILL_DIR")
.unwrap_or_else(|_| "/tmp/windmill".to_string());
.unwrap_or_else(|_| {
#[cfg(not(windows))]
{ "/tmp/windmill".to_string() }
#[cfg(windows)]
{
let temp = std::env::temp_dir();
let temp_str = temp.to_string_lossy();
let normalized = temp_str.trim_end_matches(&['/', '\\'][..]).replace('\\', "/");
format!("{}/windmill", normalized)
}
});
if dir.is_empty() {
panic!("WINDMILL_DIR must not be empty");
}
+2
View File
@@ -66,6 +66,8 @@ fn next_worker_name() -> String {
.unwrap_or(s)
})
.unwrap_or("no thread name");
// Replace colons because they are illegal in Windows directory names
let thread_name = thread_name.replace(':', "_");
format!("{id}/worker-{thread_name}")
}
@@ -0,0 +1,123 @@
// Windows-specific bun loader that uses a virtual "windmill-url" namespace instead
// of writing .url files to disk. This avoids Windows path issues (backslashes in
// resolve(), 8.3 short filenames, drive letter prefixes). The virtual namespace
// approach is likely better on all fronts but we keep the original .url-file loader
// on Linux to avoid breaking back-compat.
const p = {
name: "windmill-relative-resolver",
async setup(build) {
const { readFileSync } = await import("fs");
const { resolve } = await import("node:path");
const base_internal_url = "BASE_INTERNAL_URL".replace(
"localhost",
"127.0.0.1"
);
const w_id = "W_ID";
const current_path = "CURRENT_PATH";
const token = "TOKEN";
const cdir = resolve("./");
const cdirNoPrivate = cdir.replace(/^\/private/, ""); // for macos
// Normalize path to forward slashes to match Bun's resolver output on Windows
const cdirFwd = cdir.replace(/\\/g, "/");
const cdirPosix = cdirFwd.replace(/^[a-zA-Z]:/, "");
const filterResolve = new RegExp(
`^(?!\\.\/main\\.ts)(?!${cdirFwd}\/main\\.ts)(?!${cdirPosix}\/main\\.ts)(?!(?:/private)?${cdirNoPrivate}\/wrapper\\.mjs).*\\.ts$`
);
let cdirNodeModules = `${cdirFwd}/node_modules/`;
const filterLoad = new RegExp(`^${cdir}\/main\\.ts$`);
const transpiler = new Bun.Transpiler({
loader: "ts",
});
function replaceRelativeImports(code) {
const imports = transpiler.scanImports(code);
for (const imp of imports) {
if (imp.kind == "import-statement") {
if (
(imp.path.startsWith(".") ||
imp.path.startsWith("/u/") ||
imp.path.startsWith("/f/")) &&
!imp.path.endsWith(".ts")
) {
code = code.replaceAll(imp.path, imp.path + ".ts");
}
}
}
return {
contents: code,
};
}
function normalizePath(rawPath) {
return rawPath.split("/").reduce((acc, seg) => {
if (seg === "..") acc.pop();
else if (seg !== "." && seg !== "") acc.push(seg);
return acc;
}, []).join("/");
}
// Resolve a windmill script import path relative to an importer path.
// Bun on Windows may prefix args with "windmill-url:" or strip leading "/".
function resolveWindmillImport(importerPath, importPath) {
const path = importPath.replace(/^windmill-url:/, "").replace(/^\//, "");
const isAbsolute = path.startsWith("f/") || path.startsWith("u/");
const endExt = path.endsWith(".ts") ? "" : ".ts";
const rawScriptPath = isAbsolute
? `${path}${endExt}`
: `${importerPath}/../${path}${endExt}`;
return { path: normalizePath(rawScriptPath), namespace: "windmill-url" };
}
build.onLoad({ filter: filterLoad }, async (args) => {
const code = readFileSync(args.path, "utf8");
return replaceRelativeImports(code);
});
// Load windmill scripts by fetching from the API
build.onLoad({ filter: /.*/, namespace: "windmill-url" }, async (args) => {
const path = args.path.replace(/^windmill-url:/, "");
const url = `${base_internal_url}/api/w/${w_id}/scripts/RAW_GET_ENDPOINT/p/${path}`;
const req = await fetch(url, {
method: "GET",
headers: {
Authorization: "Bearer " + token,
},
});
if (!req.ok) {
throw new Error(
`Failed to find relative import at ${url} (status ${req.status})`
);
}
const contents = await req.text();
return {
contents: replaceRelativeImports(contents).contents,
loader: "tsx",
};
});
// Resolve windmill script imports from the file namespace (e.g. from main.ts)
build.onResolve({ filter: filterResolve }, (args) => {
const importerFwd = args.importer?.replace(/\\/g, "/") ?? "";
if (importerFwd.startsWith(cdirNodeModules)) {
return undefined;
}
const isMainTs =
args.importer == "./main.ts" || importerFwd.endsWith("/main.ts");
const file_path = isMainTs
? current_path
: importerFwd.replace(cdirFwd + "/", "");
return resolveWindmillImport(file_path, args.path);
});
// Resolve nested imports from within windmill-url modules
build.onResolve({ filter: /\.ts$/, namespace: "windmill-url" }, (args) => {
const importer = args.importer.replace(/^windmill-url:/, "");
return resolveWindmillImport(importer, args.path);
});
},
};
+6 -1
View File
@@ -26,7 +26,12 @@ use windmill_queue::{
};
lazy_static::lazy_static! {
pub static ref BIN_BASH: String = std::env::var("BASH_PATH").unwrap_or_else(|_| "/bin/bash".to_string());
pub static ref BIN_BASH: String = std::env::var("BASH_PATH").unwrap_or_else(|_| {
#[cfg(not(windows))]
{ "/bin/bash".to_string() }
#[cfg(windows)]
{ "bash".to_string() }
});
}
const NSJAIL_CONFIG_RUN_BASH_CONTENT: &str = include_str!("../nsjail/run.bash.config.proto");
+12 -3
View File
@@ -53,7 +53,14 @@ use windmill_object_store::attempt_fetch_bytes;
use windmill_parser::Typ;
// The Windows loader uses a virtual "windmill-url" namespace instead of writing .url
// files to disk, which avoids Windows path issues. The virtual namespace approach is
// likely better on all fronts but we keep the original .url-file loader on Linux to
// avoid breaking back-compat.
#[cfg(not(windows))]
pub const RELATIVE_BUN_LOADER: &str = include_str!("../loader.bun.js");
#[cfg(windows)]
pub const RELATIVE_BUN_LOADER: &str = include_str!("../loader.bun.windows.js");
pub const RELATIVE_BUN_BUILDER: &str = include_str!("../loader_builder.bun.js");
@@ -527,6 +534,8 @@ pub async fn build_loader(
current_path: &str,
mode: LoaderMode,
) -> Result<()> {
// Use forward slashes in JS strings to avoid backslash escape issues on Windows
let job_dir_js = job_dir.replace('\\', "/");
let loader = RELATIVE_BUN_LOADER
.replace("W_ID", w_id)
.replace("BASE_INTERNAL_URL", base_internal_url)
@@ -549,13 +558,13 @@ import {{ readdir }} from "node:fs/promises";
let fileNames = []
try {{
fileNames = await readdir("{job_dir}/node_modules")
fileNames = await readdir("{job_dir_js}/node_modules")
}} catch (e) {{
}}
try {{
await Bun.build({{
entrypoints: ["{job_dir}/wrapper.mjs"],
entrypoints: ["{job_dir_js}/wrapper.mjs"],
outdir: "./",
target: "node",
plugins: [p],
@@ -597,7 +606,7 @@ plugin(p)
try {{
await Bun.build({{
entrypoints: ["{job_dir}/main.ts"],
entrypoints: ["{job_dir_js}/main.ts"],
outdir: "./",
target: "{}",
plugins: [p],
+1 -2
View File
@@ -53,8 +53,7 @@ fn get_windows_program_files() -> String {
#[cfg(windows)]
fn windows_gopath() -> String {
let tmp_dir = get_windows_tmp_dir();
GO_CACHE_DIR.replace("/tmp", &tmp_dir).replace("/", r"\\")
GO_CACHE_DIR.replace('/', "\\")
}
#[cfg(windows)]
+39 -24
View File
@@ -41,20 +41,30 @@ const NSJAIL_CONFIG_RUN_RUST_CONTENT: &str = include_str!("../nsjail/run.rust.co
const NSJAIL_CONFIG_COMPILE_RUST_CONTENT: &str =
include_str!("../nsjail/download.rust.config.proto");
#[cfg(windows)]
const RUST_BIN_NAME: &str = "main.exe";
#[cfg(not(windows))]
const RUST_BIN_NAME: &str = "main";
fn find_cargo_path() -> String {
if let Ok(p) = std::env::var("CARGO_PATH") {
return p;
}
let from_home = format!("{}/bin/cargo", CARGO_HOME.as_str());
if std::path::Path::new(&from_home).exists() {
return from_home;
}
for p in ["/usr/local/cargo/bin/cargo", "/usr/bin/cargo"] {
let candidates = if cfg!(windows) {
vec![format!("{}\\bin\\cargo.exe", CARGO_HOME.as_str())]
} else {
vec![
format!("{}/bin/cargo", CARGO_HOME.as_str()),
"/usr/local/cargo/bin/cargo".to_string(),
"/usr/bin/cargo".to_string(),
]
};
for p in &candidates {
if std::path::Path::new(p).exists() {
return p.to_string();
return p.clone();
}
}
from_home
candidates.into_iter().next().unwrap()
}
#[cfg(not(windows))]
@@ -71,7 +81,6 @@ fn find_preinstalled_dir(env_var: &str, candidates: &[&str]) -> String {
}
lazy_static::lazy_static! {
static ref HOME_DIR: String = std::env::var("HOME").expect("Could not find the HOME environment variable");
static ref CARGO_HOME: String = std::env::var("CARGO_HOME").unwrap_or_else(|_| { CARGO_HOME_DEFAULT.clone() });
static ref RUSTUP_HOME: String = std::env::var("RUSTUP_HOME").unwrap_or_else(|_| { RUSTUP_HOME_DEFAULT.clone() });
static ref CARGO_PATH: String = find_cargo_path();
@@ -81,14 +90,14 @@ lazy_static::lazy_static! {
#[cfg(windows)]
lazy_static::lazy_static! {
static ref CARGO_HOME_DEFAULT: String = format!("{}\\.cargo", *HOME_DIR);
static ref RUSTUP_HOME_DEFAULT: String = format!("{}\\.rustup", *HOME_DIR);
static ref CARGO_HOME_DEFAULT: String = format!("{}\\.cargo", HOME_ENV.as_str());
static ref RUSTUP_HOME_DEFAULT: String = format!("{}\\.rustup", HOME_ENV.as_str());
}
#[cfg(not(windows))]
lazy_static::lazy_static! {
static ref CARGO_HOME_DEFAULT: String = format!("{}/.cargo", *HOME_DIR);
static ref RUSTUP_HOME_DEFAULT: String = format!("{}/.rustup", *HOME_DIR);
static ref CARGO_HOME_DEFAULT: String = format!("{}/.cargo", HOME_ENV.as_str());
static ref RUSTUP_HOME_DEFAULT: String = format!("{}/.rustup", HOME_ENV.as_str());
}
const RUST_OBJECT_STORE_PREFIX: &str = "rustbin/";
@@ -97,11 +106,11 @@ const RUST_OBJECT_STORE_PREFIX: &str = "rustbin/";
lazy_static::lazy_static! {
static ref PREINSTALLED_CARGO: String = find_preinstalled_dir(
"CARGO_PREINSTALL_DIR",
&["/usr/local/cargo", &format!("{}/.cargo", *HOME_DIR)],
&["/usr/local/cargo", &format!("{}/.cargo", HOME_ENV.as_str())],
);
static ref PREINSTALLED_RUSTUP: String = find_preinstalled_dir(
"RUSTUP_PREINSTALL_DIR",
&["/usr/local/rustup", &format!("{}/.rustup", *HOME_DIR)],
&["/usr/local/rustup", &format!("{}/.rustup", HOME_ENV.as_str())],
);
}
@@ -521,6 +530,13 @@ pub async fn build_rust_crate(
std::env::var("TMP").unwrap_or_else(|_| "C:\\tmp".to_string()),
);
build_rust_cmd.env("USERPROFILE", crate::USERPROFILE_ENV.as_str());
// MSVC linker needs LIB and INCLUDE to find kernel32.lib etc.
if let Ok(lib) = std::env::var("LIB") {
build_rust_cmd.env("LIB", lib);
}
if let Ok(include) = std::env::var("INCLUDE") {
build_rust_cmd.env("INCLUDE", include);
}
}
start_child_process(build_rust_cmd, CARGO_PATH.as_str(), false).await?
};
@@ -545,30 +561,29 @@ pub async fn build_rust_crate(
tokio::fs::copy(
&format!(
"{build_dir}/target/{}/main",
"{build_dir}/target/{}/{RUST_BIN_NAME}",
if is_preview { "debug" } else { "release" },
),
format! {"{job_dir}/main"},
format!("{job_dir}/{RUST_BIN_NAME}"),
)
.await
.map_err(|e| {
Error::ExecutionErr(format!(
"could not copy built binary from [...]/target/.../main to {job_dir}/main: {e:?}"
"could not copy built binary from [...]/target/.../{RUST_BIN_NAME} to {job_dir}/{RUST_BIN_NAME}: {e:?}"
))
})?;
match save_cache(
&bin_path,
&format!("{RUST_OBJECT_STORE_PREFIX}{hash}"),
&format!("{job_dir}/main"),
&format!("{job_dir}/{RUST_BIN_NAME}"),
false,
)
.await
{
Err(e) => {
let em = format!(
"could not save {bin_path} to {} to rust cache: {e:?}",
format!("{job_dir}/main"),
"could not save {bin_path} to {job_dir}/{RUST_BIN_NAME} to rust cache: {e:?}",
);
tracing::error!(em);
Ok(em)
@@ -618,16 +633,16 @@ pub async fn handle_rust_job(
let (cache, cache_logs) = crate::global_cache::load_cache(&bin_path, &remote_path, false).await;
let cache_logs = if cache {
let target = format!("{job_dir}/main");
let target = format!("{job_dir}/{RUST_BIN_NAME}");
#[cfg(unix)]
let symlink = std::os::unix::fs::symlink(&bin_path, &target);
#[cfg(windows)]
let symlink = std::os::windows::fs::symlink_dir(&bin_path, &target);
let symlink = std::os::windows::fs::symlink_file(&bin_path, &target);
symlink.map_err(|e| {
Error::ExecutionErr(format!(
"could not copy cached binary from {bin_path} to {job_dir}/main: {e:?}"
"could not copy cached binary from {bin_path} to {target}: {e:?}"
))
})?;
@@ -694,7 +709,7 @@ pub async fn handle_rust_job(
.stderr(Stdio::piped());
start_child_process(nsjail_cmd, NSJAIL_PATH.as_str(), false).await?
} else {
let compiled_executable_name = "./main";
let compiled_executable_name = &format!("{job_dir}/{RUST_BIN_NAME}");
let mut run_rust = build_command_with_isolation(compiled_executable_name, &[]);
run_rust
.current_dir(job_dir)
+10 -1
View File
@@ -563,7 +563,16 @@ lazy_static::lazy_static! {
pub static ref DOTNET_PATH: String = std::env::var("DOTNET_PATH").unwrap_or_else(|_| DOTNET_DEFAULT_PATH.to_string());
pub static ref NSJAIL_PATH: String = std::env::var("NSJAIL_PATH").unwrap_or_else(|_| "nsjail".to_string());
pub static ref PATH_ENV: String = std::env::var("PATH").unwrap_or_else(|_| String::new());
pub static ref HOME_ENV: String = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
pub static ref HOME_ENV: String = {
#[cfg(not(windows))]
{ std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string()) }
#[cfg(windows)]
{
std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.unwrap_or_else(|_| std::env::temp_dir().to_string_lossy().to_string())
}
};
pub static ref GIT_PATH: String = std::env::var("GIT_PATH").unwrap_or_else(|_| "/usr/bin/git".to_string());
pub static ref NODE_PATH: Option<String> = std::env::var("NODE_PATH").ok();