Compare commits

..

10 Commits

Author SHA1 Message Date
centdix
78bc6b498c feat: add workspace script search tools to script mode
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:31:38 +00:00
Luigi
8e19f9652d Added serpapi import handling (#7871)
Added the handling for serpapi import. The name of the Python library to be installed is google-search-results.

Source: https://pypi.org/project/google-search-results/
2026-02-10 09:59:35 +00:00
Ruben Fiszel
45980f0220 resolve Windows build warnings treated as errors (#7870)
* fix: resolve Windows build warnings treated as errors

- Gate UV_PATH import behind #[cfg(unix)] in python_versions.rs
- Remove unused tokio::time::sleep import in worker.rs (use fully qualified path)
- Fix unused `file` variable warnings in ansible_executor.rs on Windows

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

* ci: add Windows cargo check workflow

Runs cargo check with ee_windows features on push to backend/**
using the blacksmith-16vcpu-windows-2025 runner.

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

* ci: add cargo check step to Windows build, remove separate check workflow

Add a cargo check step with -D warnings before the full build to fail
fast on any warnings. Remove the separate windows-check.yml workflow.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:58:56 +00:00
hugocasa
8363ff1eee feat: download encrypted usage (#7804) 2026-02-10 09:50:24 +00:00
Ruben Fiszel
cf596f370a fix: gate Permissions import behind #[cfg(unix)] for Windows build
Move `use std::fs::Permissions` and `use std::os::unix::fs::PermissionsExt`
inside the #[cfg(unix)] block to avoid unused import error on Windows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:02:09 +00:00
Ruben Fiszel
b12304d834 chore(main): release 1.629.1 (#7862)
* chore(main): release 1.629.1

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>
2026-02-10 08:44:44 +00:00
Ruben Fiszel
b5f8d931bd ci: add libcurl4-openssl-dev to backend-test workflow
Required by rdkafka-sys 4.10.0 which unconditionally includes curl/curl.h.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 08:39:45 +00:00
Ruben Fiszel
f927c673b5 ci: improve Windows builds with faster runner, caching, and 3h timeout
- Switch to blacksmith-16vcpu-windows-2025 runner
- Replace deprecated actions-rs/toolchain with actions-rust-lang/setup-rust-toolchain with cargo caching
- Increase build timeout from 90min to 180min

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 08:31:27 +00:00
Ruben Fiszel
4f653ca957 adapt to libkafka-changes 2026-02-10 08:06:06 +00:00
Ruben Fiszel
08031640a0 fix: remove unecessary drop index on labeled_jobs_on_jobs 2026-02-10 08:02:38 +00:00
41 changed files with 368 additions and 173 deletions

View File

@@ -39,7 +39,7 @@ jobs:
- name: install xmlsec1 and gssapi
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev mold clang
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev libcurl4-openssl-dev mold clang
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
@@ -109,7 +109,7 @@ jobs:
- name: install xmlsec1 and gssapi
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev mold clang
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev libcurl4-openssl-dev mold clang
- name: Substitute EE code (EE logic is behind feature flag)
run: |

View File

@@ -72,7 +72,7 @@ jobs:
bundler-cache: false
- name: Install PowerShell, mold and clang
run: |
sudo apt-get update && sudo apt-get install -y powershell mold clang
sudo apt-get update && sudo apt-get install -y powershell mold clang libcurl4-openssl-dev
working-directory: /
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:

View File

@@ -11,7 +11,7 @@ env:
jobs:
cargo_build_windows:
runs-on: windows-latest
runs-on: blacksmith-16vcpu-windows-2025
steps:
- uses: actions/checkout@v4
@@ -30,33 +30,40 @@ jobs:
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
fetch-depth: 0
- name: Setup Rust
uses: actions-rs/toolchain@v1
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: backend
toolchain: 1.90.0
override: true
- name: Substitute EE code
shell: bash
run: |
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
- name: Cargo check (fail fast on warnings)
timeout-minutes: 60
env:
RUSTFLAGS: "-D warnings"
run: |
mkdir frontend/build && cd backend
New-Item -Path . -Name "windmill-api/openapi-deref.yaml" -ItemType "File" -Force
cargo check --features=ee_windows
- name: Cargo build dynamic libraries windows
timeout-minutes: 90
timeout-minutes: 180
run: |
cd backend/windmill-duckdb-ffi-internal
cargo build --release -p windmill_duckdb_ffi_internal
- name: Cargo build binary windows
timeout-minutes: 90
timeout-minutes: 180
run: |
vcpkg.exe install openssl-windows:x64-windows
vcpkg.exe install openssl:x64-windows-static
vcpkg.exe integrate install
$env:VCPKGRS_DYNAMIC=1
$env:OPENSSL_DIR="${Env:VCPKG_INSTALLATION_ROOT}\installed\x64-windows-static"
mkdir frontend/build && cd backend
New-Item -Path . -Name "windmill-api/openapi-deref.yaml" -ItemType "File" -Force
cd backend
cargo build --release --features=ee_windows
- name: Rename binary with corresponding architecture
run: |

View File

@@ -78,7 +78,7 @@ jobs:
- name: install xmlsec1 and gssapi
run: |
sudo apt-get update
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev
sudo apt-get install -y libxml2-dev libxmlsec1-dev libkrb5-dev libsasl2-dev libcurl4-openssl-dev
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:

View File

@@ -13,7 +13,7 @@ env:
jobs:
cargo_build_windows:
runs-on: windows-latest
runs-on: blacksmith-16vcpu-windows-2025
steps:
- uses: actions/checkout@v4
@@ -32,11 +32,10 @@ jobs:
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
fetch-depth: 0
- name: Setup Rust
uses: actions-rs/toolchain@v1
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: backend
toolchain: 1.90.0
override: true
- name: Substitute EE code
shell: bash
@@ -44,13 +43,13 @@ jobs:
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
- name: Cargo build dynamic libraries windows
timeout-minutes: 90
timeout-minutes: 180
run: |
cd backend/windmill-duckdb-ffi-internal
cargo build --release -p windmill_duckdb_ffi_internal
- name: Cargo build windows
timeout-minutes: 90
timeout-minutes: 180
run: |
vcpkg.exe install openssl-windows:x64-windows
vcpkg.exe install openssl:x64-windows-static

View File

@@ -1,5 +1,12 @@
# Changelog
## [1.629.1](https://github.com/windmill-labs/windmill/compare/v1.629.0...v1.629.1) (2026-02-10)
### Bug Fixes
* remove unecessary drop index on labeled_jobs_on_jobs ([0803164](https://github.com/windmill-labs/windmill/commit/08031640a02ebd5971793942e8534d69f4f71d28))
## [1.629.0](https://github.com/windmill-labs/windmill/compare/v1.628.3...v1.629.0) (2026-02-09)

View File

@@ -97,7 +97,7 @@ ARG features=""
COPY --from=planner /windmill/recipe.json recipe.json
RUN apt-get update && apt-get install -y libxml2-dev=2.9.* libxmlsec1-dev=1.2.* libkrb5-dev libsasl2-dev clang=1:14.0-55.* libclang-dev=1:14.0-55.* cmake=3.25.* && \
RUN apt-get update && apt-get install -y libxml2-dev=2.9.* libxmlsec1-dev=1.2.* libkrb5-dev libsasl2-dev libcurl4-openssl-dev clang=1:14.0-55.* libclang-dev=1:14.0-55.* cmake=3.25.* && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

106
backend/Cargo.lock generated
View File

@@ -15725,7 +15725,7 @@ dependencies = [
[[package]]
name = "windmill"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-nats",
@@ -15783,7 +15783,7 @@ dependencies = [
[[package]]
name = "windmill-api"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"argon2",
@@ -15907,7 +15907,7 @@ dependencies = [
[[package]]
name = "windmill-api-auth"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"axum 0.7.9",
@@ -15933,7 +15933,7 @@ dependencies = [
[[package]]
name = "windmill-api-client"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"reqwest 0.12.28",
"serde",
@@ -15943,7 +15943,7 @@ dependencies = [
[[package]]
name = "windmill-api-embeddings"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"axum 0.7.9",
@@ -15966,7 +15966,7 @@ dependencies = [
[[package]]
name = "windmill-api-groups"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -15986,7 +15986,7 @@ dependencies = [
[[package]]
name = "windmill-api-jobs"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"axum 0.7.9",
@@ -16011,7 +16011,7 @@ dependencies = [
[[package]]
name = "windmill-api-scripts"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -16040,7 +16040,7 @@ dependencies = [
[[package]]
name = "windmill-api-sse"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"lazy_static",
"serde",
@@ -16052,7 +16052,7 @@ dependencies = [
[[package]]
name = "windmill-api-users"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"argon2",
"axum 0.7.9",
@@ -16075,7 +16075,7 @@ dependencies = [
[[package]]
name = "windmill-api-workspaces"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -16103,7 +16103,7 @@ dependencies = [
[[package]]
name = "windmill-audit"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"chrono",
"lazy_static",
@@ -16117,7 +16117,7 @@ dependencies = [
[[package]]
name = "windmill-autoscaling"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"axum 0.7.9",
@@ -16136,7 +16136,7 @@ dependencies = [
[[package]]
name = "windmill-common"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"aes-gcm",
"anyhow",
@@ -16235,7 +16235,7 @@ dependencies = [
[[package]]
name = "windmill-dep-map"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"chrono",
"itertools 0.14.0",
@@ -16254,7 +16254,7 @@ dependencies = [
[[package]]
name = "windmill-git-sync"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"regex",
"serde",
@@ -16269,7 +16269,7 @@ dependencies = [
[[package]]
name = "windmill-indexer"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"astral-tokio-tar",
@@ -16293,7 +16293,7 @@ dependencies = [
[[package]]
name = "windmill-jseval"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"futures",
@@ -16310,7 +16310,7 @@ dependencies = [
[[package]]
name = "windmill-macros"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"itertools 0.14.0",
"lazy_static",
@@ -16326,7 +16326,7 @@ dependencies = [
[[package]]
name = "windmill-mcp"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16347,7 +16347,7 @@ dependencies = [
[[package]]
name = "windmill-native-triggers"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16378,7 +16378,7 @@ dependencies = [
[[package]]
name = "windmill-oauth"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-oauth2",
@@ -16402,7 +16402,7 @@ dependencies = [
[[package]]
name = "windmill-parser"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"convert_case 0.6.0",
"serde",
@@ -16411,7 +16411,7 @@ dependencies = [
[[package]]
name = "windmill-parser-bash"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"lazy_static",
@@ -16423,7 +16423,7 @@ dependencies = [
[[package]]
name = "windmill-parser-csharp"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"serde_json",
@@ -16435,7 +16435,7 @@ dependencies = [
[[package]]
name = "windmill-parser-go"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"gosyn",
@@ -16447,7 +16447,7 @@ dependencies = [
[[package]]
name = "windmill-parser-graphql"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"lazy_static",
@@ -16459,7 +16459,7 @@ dependencies = [
[[package]]
name = "windmill-parser-java"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"serde_json",
@@ -16471,7 +16471,7 @@ dependencies = [
[[package]]
name = "windmill-parser-nu"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"nu-parser",
@@ -16482,7 +16482,7 @@ dependencies = [
[[package]]
name = "windmill-parser-php"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"itertools 0.14.0",
@@ -16493,7 +16493,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"itertools 0.14.0",
@@ -16506,7 +16506,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py-imports"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-recursion",
@@ -16530,7 +16530,7 @@ dependencies = [
[[package]]
name = "windmill-parser-ruby"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"lazy_static",
@@ -16544,7 +16544,7 @@ dependencies = [
[[package]]
name = "windmill-parser-rust"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -16561,7 +16561,7 @@ dependencies = [
[[package]]
name = "windmill-parser-sql"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"lazy_static",
@@ -16575,7 +16575,7 @@ dependencies = [
[[package]]
name = "windmill-parser-ts"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"lazy_static",
@@ -16594,7 +16594,7 @@ dependencies = [
[[package]]
name = "windmill-parser-yaml"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"serde",
@@ -16605,7 +16605,7 @@ dependencies = [
[[package]]
name = "windmill-queue"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-recursion",
@@ -16642,7 +16642,7 @@ dependencies = [
[[package]]
name = "windmill-runtime-nativets"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"const_format",
@@ -16680,7 +16680,7 @@ dependencies = [
[[package]]
name = "windmill-sql-datatype-parser-wasm"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"wasm-bindgen",
"wasm-bindgen-test",
@@ -16690,7 +16690,7 @@ dependencies = [
[[package]]
name = "windmill-store"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-recursion",
@@ -16719,7 +16719,7 @@ dependencies = [
[[package]]
name = "windmill-trigger"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16752,7 +16752,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-email"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16772,7 +16772,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-gcp"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16806,7 +16806,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-http"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16840,7 +16840,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-kafka"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16863,7 +16863,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-mqtt"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16887,7 +16887,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-nats"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-nats",
@@ -16911,7 +16911,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-postgres"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16946,7 +16946,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-sqs"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16974,7 +16974,7 @@ dependencies = [
[[package]]
name = "windmill-trigger-websocket"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-trait",
@@ -16997,7 +16997,7 @@ dependencies = [
[[package]]
name = "windmill-types"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"chrono",
@@ -17014,7 +17014,7 @@ dependencies = [
[[package]]
name = "windmill-worker"
version = "1.629.0"
version = "1.629.1"
dependencies = [
"anyhow",
"async-once-cell",

View File

@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.629.0"
version = "1.629.1"
authors.workspace = true
edition.workspace = true
@@ -59,7 +59,7 @@ members = [
exclude = ["./windmill-duckdb-ffi-internal"]
[workspace.package]
version = "1.629.0"
version = "1.629.1"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
@@ -419,7 +419,7 @@ const_format = { version = "0.2.35", features = ["rust_1_64", "rust_1_51"] }
const-str = "0.5"
constant_time_eq = "0.3.1"
rsa = "^0"
aes-gcm = "^0"
aes-gcm = "0.10.3"
async_zip = { version = "0.0.17", features = ["tokio", "tokio-fs", "deflate", "chrono"] }
once_cell = "1.17.1"
dashmap = "6.1.0"

View File

@@ -1 +1 @@
7596cefdba81482c0b0c0b61be26369f112d8009
7596cefdba81482c0b0c0b61be26369f112d8009

View File

@@ -0,0 +1 @@
-- No-op: cannot restore deleted telemetry data

View File

@@ -0,0 +1,2 @@
-- Delete all saved telemetry data from metrics table
DELETE FROM metrics WHERE id = 'telemetry';

View File

@@ -381,5 +381,6 @@ pub static SHORT_IMPORTS_MAP: PyMap = phf_map! {
"docx" => "python-docx",
"vt" => "vt-py",
"grpc" => "grpcio",
"serpapi" => "google-search-results",
// Add new entry here ^
};

View File

@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.629.0
version: 1.629.1
title: Windmill API
contact:
@@ -1310,6 +1310,20 @@ paths:
schema:
type: string
/settings/get_stats:
get:
summary: get encrypted telemetry stats (EE only)
operationId: getStats
tags:
- setting
responses:
"200":
description: base64-encoded encrypted telemetry blob
content:
text/plain:
schema:
type: string
/settings/latest_key_renewal_attempt:
get:
summary: get latest key renewal attempt

View File

@@ -68,7 +68,7 @@ lazy_static::lazy_static! {
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),
(20260207000002, include_str!(
"../../migrations/20260207000002_concurrent_indexes_v2_job_completed.up.sql"
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY").replace("DROP INDEX CONCURRENTLY IF EXISTS labeled_jobs_on_jobs;", "")),
(20260207000003, include_str!(
"../../migrations/20260207000003_concurrent_indexes_v2_job_queue.up.sql"
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),

View File

@@ -58,6 +58,7 @@ pub fn global_service() -> Router {
.route("/test_smtp", post(test_email))
.route("/test_license_key", post(test_license_key))
.route("/send_stats", post(send_stats))
.route("/get_stats", get(get_stats))
.route(
"/latest_key_renewal_attempt",
get(get_latest_key_renewal_attempt),
@@ -434,6 +435,25 @@ pub async fn send_stats(Extension(db): Extension<DB>, authed: ApiAuthed) -> Resu
Ok("Sent stats".to_string())
}
#[cfg(feature = "enterprise")]
pub async fn get_stats(Extension(db): Extension<DB>, authed: ApiAuthed) -> Result<String> {
require_super_admin(&db, &authed.email).await?;
let stats = windmill_common::stats_oss::get_stats_payload(
&db,
&windmill_common::stats_oss::SendStatsReason::Manual,
)
.await?;
let encrypted = windmill_common::stats_oss::encrypt_stats(&stats)?;
Ok(encrypted)
}
#[cfg(not(feature = "enterprise"))]
pub async fn get_stats() -> Result<String> {
Err(error::Error::BadRequest(
"Downloading telemetry is only available on enterprise edition".to_string(),
))
}
#[derive(serde::Serialize)]
pub struct KeyRenewalAttempt {
result: String,

View File

@@ -50,3 +50,19 @@ pub async fn get_user_usage<'c, E: sqlx::Executor<'c, Database = Postgres>>(
let usage = ActiveUserUsage { author_count: None, operator_count: None };
Ok(usage)
}
#[cfg(not(feature = "private"))]
#[derive(serde::Serialize)]
pub struct Stats {}
#[cfg(not(feature = "private"))]
pub async fn get_stats_payload(_db: &DB, _reason: &SendStatsReason) -> Result<Stats> {
// stats details are closed source
Ok(Stats {})
}
#[cfg(not(feature = "private"))]
pub fn encrypt_stats(_stats: &Stats) -> Result<String> {
// stats details are closed source
Ok(String::new())
}

View File

@@ -1045,16 +1045,17 @@ pub async fn extract_tar(tar: bytes::Bytes, folder: &str) -> error::Result<()> {
}
#[cfg(all(feature = "enterprise", feature = "parquet"))]
fn write_binary_file(main_path: &str, byts: &mut bytes::Bytes) -> error::Result<()> {
use std::fs::{File, Permissions};
use std::fs::File;
use std::io::Write;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
let mut file = File::create(main_path)?;
file.write_all(byts)?;
#[cfg(unix)]
file.set_permissions(Permissions::from_mode(0o755))?;
{
use std::fs::Permissions;
use std::os::unix::fs::PermissionsExt;
file.set_permissions(Permissions::from_mode(0o755))?;
}
file.flush()?;
Ok(())
}

View File

@@ -752,10 +752,12 @@ pub async fn get_git_ssh_cmd(
})?;
content.push_str("\n");
let file = write_file(job_dir, &id_file_name, &content)?;
#[cfg(not(unix))]
let _ = write_file(job_dir, &id_file_name, &content)?;
#[cfg(unix)]
{
let file = write_file(job_dir, &id_file_name, &content)?;
let perm = std::os::unix::fs::PermissionsExt::from_mode(0o600);
file.set_permissions(perm)?;
}
@@ -1218,10 +1220,10 @@ fi
ANSIBLE_PLAYBOOK_PATH.as_str()
);
let file = write_file(job_dir, "wrapper.sh", &wrapper)?;
let _file = write_file(job_dir, "wrapper.sh", &wrapper)?;
#[cfg(unix)]
file.metadata()?.permissions().set_mode(0o777);
_file.metadata()?.permissions().set_mode(0o777);
// let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str());
let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str());
nsjail_cmd

View File

@@ -21,10 +21,12 @@ use windmill_queue::append_logs;
use crate::{
common::{start_child_process, OccupancyMetrics},
handle_child::handle_child,
python_executor::{INDEX_CERT, NATIVE_CERT, PYTHON_PATH, UV_PATH},
python_executor::{INDEX_CERT, NATIVE_CERT, PYTHON_PATH},
HOME_ENV, INSTANCE_PYTHON_VERSION, PATH_ENV, PROXY_ENVS, PY_INSTALL_DIR, UV_CACHE_DIR,
WIN_ENVS,
};
#[cfg(unix)]
use crate::python_executor::UV_PATH;
impl From<PyV> for PyVAlias {
fn from(value: PyV) -> Self {

View File

@@ -12,7 +12,6 @@
use anyhow::anyhow;
use futures::TryFutureExt;
use tokio::sync::Mutex;
use tokio::time::sleep;
use tokio::time::timeout;
use windmill_common::client::AuthedClient;
use windmill_common::jobs::WorkerInternalServerInlineUtils;
@@ -3064,7 +3063,7 @@ pub async fn handle_queued_job(
.flatten()
{
tracing::debug!("Debug: {} going to sleep for {}", job.id, dbg_djob_sleep);
sleep(std::time::Duration::from_secs(dbg_djob_sleep as u64)).await;
tokio::time::sleep(std::time::Duration::from_secs(dbg_djob_sleep as u64)).await;
}
tracing::debug!(

View File

@@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts";
import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts";
import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts";
export const VERSION = "v1.629.0";
export const VERSION = "v1.629.1";
export async function login(email: string, password: string): Promise<string> {
return await windmill.UserService.login({

View File

@@ -77,7 +77,7 @@ export {
// }
// });
export const VERSION = "1.629.0";
export const VERSION = "1.629.1";
// Re-exported from constants.ts to maintain backwards compatibility
export { WM_FORK_PREFIX } from "./core/constants.ts";

View File

@@ -64,7 +64,7 @@ RUN --mount=type=secret,id=rh_username \
RUN subscription-manager repos --enable codeready-builder-for-rhel-8-$(arch)-rpms
RUN yum update -y && \
yum install -y perl-interpreter perl-IPC-Cmd perl-Time-Piece libxml2-devel xmlsec1-devel xmlsec1-openssl-devel krb5-devel cyrus-sasl-devel cyrus-sasl-gssapi clang llvm-devel cmake libtool-ltdl-devel
yum install -y perl-interpreter perl-IPC-Cmd perl-Time-Piece libxml2-devel xmlsec1-devel xmlsec1-openssl-devel krb5-devel cyrus-sasl-devel cyrus-sasl-gssapi libcurl-devel clang llvm-devel cmake libtool-ltdl-devel
# RUN --mount=type=cache,target=/usr/local/cargo/registry \
# CARGO_NET_GIT_FETCH_WITH_CLI=true RUST_BACKTRACE=1 cargo chef cook --release --features "$features" --recipe-path recipe.json

View File

@@ -64,7 +64,7 @@ RUN --mount=type=secret,id=rh_username \
RUN subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
RUN yum update -y && \
yum install -y perl-FindBin perl-IPC-Cmd perl-Time-Piece libxml2-devel xmlsec1-devel xmlsec1-openssl-devel krb5-devel cyrus-sasl-devel cyrus-sasl-gssapi clang llvm-devel cmake libtool-ltdl-devel
yum install -y perl-FindBin perl-IPC-Cmd perl-Time-Piece libxml2-devel xmlsec1-devel xmlsec1-openssl-devel krb5-devel cyrus-sasl-devel cyrus-sasl-gssapi libcurl-devel clang llvm-devel cmake libtool-ltdl-devel
# RUN --mount=type=cache,target=/usr/local/cargo/registry \
# CARGO_NET_GIT_FETCH_WITH_CLI=true RUST_BACKTRACE=1 cargo chef cook --release --features "$features" --recipe-path recipe.json

View File

@@ -1,12 +1,12 @@
{
"name": "windmill-components",
"version": "1.629.0",
"version": "1.629.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "windmill-components",
"version": "1.629.0",
"version": "1.629.1",
"hasInstallScript": true,
"license": "AGPL-3.0",
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "windmill-components",
"version": "1.629.0",
"version": "1.629.1",
"scripts": {
"dev": "vite dev",
"build": "vite build",

View File

@@ -177,7 +177,7 @@
{/snippet}
<!-- {JSON.stringify($values, null, 2)} -->
{#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, $values) && !(setting.hiddenIfNull && $values[setting.key] == null) && !(setting.hiddenIfEmpty && !$values[setting.key])}
{#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, $values) && !(setting.hiddenIfNull && $values[setting.key] == null) && !(setting.hiddenIfEmpty && !$values[setting.key]) && !(setting.hiddenInEe && $enterpriseLicense)}
{#if setting.fieldType == 'select'}
<div>
{@render LabelSnippet()}

View File

@@ -231,6 +231,28 @@
}
}
let downloadingStats = $state(false)
async function downloadStats() {
try {
downloadingStats = true
const encryptedData = await SettingService.getStats()
const blob = new Blob([encryptedData], { type: 'application/octet-stream' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `windmill-telemetry-${new Date().toISOString().split('T')[0]}.enc`
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
sendUserToast('Telemetry data downloaded')
} catch (err) {
throw err
} finally {
downloadingStats = false
}
}
function isValidTeamsChannel(value: any): value is TeamsChannel {
return (
typeof value === 'object' &&
@@ -341,18 +363,29 @@
<div class="text-primary pb-4 text-xs">
On Enterprise Edition, you must send data to check that usage is in line with the
terms of the subscription. You can either enable telemetry or regularly send usage
data by clicking the button below.
data by clicking the button below. For air-gapped instances, you can download the
telemetry data and send it manually.
</div>
<div class="flex gap-2 mb-4">
<Button
on:click={sendStats}
variant="default"
btnClasses="w-auto"
loading={sendingStats}
size="xs"
>
Send usage
</Button>
<Button
on:click={downloadStats}
variant="default"
btnClasses="w-auto"
loading={downloadingStats}
size="xs"
>
Download usage
</Button>
</div>
<Button
on:click={sendStats}
variant="default"
btnClasses="w-auto"
wrapperClasses="mb-4"
loading={sendingStats}
size="xs"
>
Send usage
</Button>
{/if}
{:else if category == 'Auth/OAuth/SAML'}
<AuthSettings

View File

@@ -3,7 +3,6 @@ import {
type FlowModule,
type InputTransform,
type RawScript,
type Script,
JobService
} from '$lib/gen'
import type {
@@ -11,8 +10,6 @@ import type {
ChatCompletionUserMessageParam
} from 'openai/resources/chat/completions.mjs'
import { z } from 'zod'
import uFuzzy from '@leeoniya/ufuzzy'
import { emptyString } from '$lib/utils'
import {
createDbSchemaTool,
getFormattedResourceTypes,
@@ -31,7 +28,8 @@ import {
findModuleById,
SPECIAL_MODULE_IDS,
formatScriptLintResult,
type ScriptLintResult
type ScriptLintResult,
WorkspaceScriptsSearch
} from '../shared'
import type { ContextElement } from '../context'
import type { ExtendedOpenFlow } from '$lib/components/flows/types'
@@ -208,10 +206,7 @@ function getExpectedFormat(schema: z.ZodType): string | null {
let current = schema
// Unwrap optional/nullable to get inner type
while (
(current as any)._def.type === 'optional' ||
(current as any)._def.type === 'nullable'
) {
while ((current as any)._def.type === 'optional' || (current as any)._def.type === 'nullable') {
current = (current as any)._def.innerType
if (!current || !(current as any)._def) break
}
@@ -337,47 +332,6 @@ const setFlowJsonToolDef = createToolDef(
{ strict: false }
)
class WorkspaceScriptsSearch {
private uf: uFuzzy
private workspace: string | undefined = undefined
private scripts: Script[] | undefined = undefined
constructor() {
this.uf = new uFuzzy()
}
private async init(workspace: string) {
this.scripts = await ScriptService.listScripts({
workspace
})
this.workspace = workspace
}
async search(query: string, workspace: string) {
if (this.scripts === undefined || this.workspace !== workspace) {
await this.init(workspace)
}
const scripts = this.scripts
if (!scripts) {
throw new Error('Failed to load scripts')
}
const results = this.uf.search(
scripts.map((s) => (emptyString(s.summary) ? s.path : s.summary + ' (' + s.path + ')')),
query.trim()
)
const scriptResults =
results[2]?.map((id) => ({
path: scripts[id].path,
summary: scripts[id].summary
})) ?? []
return scriptResults
}
}
// Will be overridden by setSchema
const testRunFlowSchema = z.object({
args: z
@@ -748,8 +702,7 @@ export const flowTools: Tool<FlowAIChatHelpers>[] = [
const path = e.path
// Try to find module id for better context
const moduleIndex = typeof path[0] === 'number' ? path[0] : undefined
const moduleId =
moduleIndex !== undefined ? parsedModules[moduleIndex]?.id : undefined
const moduleId = moduleIndex !== undefined ? parsedModules[moduleIndex]?.id : undefined
const fieldPath = path.slice(1).join('.')
let message = e.message

View File

@@ -1,4 +1,4 @@
import { ResourceService, JobService } from '$lib/gen/services.gen'
import { ResourceService, JobService, ScriptService } from '$lib/gen/services.gen'
import type { AIProvider, AIProviderModel, ResourceType, ScriptLang } from '$lib/gen/types.gen'
import { capitalize, isObject, toCamel } from '$lib/utils'
import { get } from 'svelte/store'
@@ -17,7 +17,8 @@ import {
buildTestRunArgs,
buildContextString,
type ScriptLintResult,
formatScriptLintResult
formatScriptLintResult,
WorkspaceScriptsSearch
} from '../shared'
import { setupTypeAcquisition, type DepsToGet } from '$lib/ata'
import { getModelContextWindow } from '../../lib'
@@ -177,7 +178,8 @@ function buildChatSystemPrompt(currentModel: AIProviderModel) {
- The user can ask you questions about a list of \`DATABASES\` that are available in the user's workspace. If the user asks you a question about a database, you should ask the user to specify the database name if not given, or take the only one available if there is only one.
- You can also receive a \`DIFF\` of the changes that have been made to the code. You should use this diff to give better answers.
- Before giving your answer, check again that you carefully followed these instructions.
- When asked to create a script that communicates with an external service, you can use the \`search_hub_scripts\` tool to search for relevant scripts in the hub. Make sure the language is the same as what the user is coding in. If you do not find any relevant scripts, you can use the \`search_npm_packages\` tool to search for relevant packages and their documentation. Always give a link to the documentation in your answer if possible.
- If the user mentions a specific script or wants to find existing scripts in the workspace, use the \`search_workspace_scripts\` tool. You can then use \`get_script_details\` to read the script's code and understand its inputs.
- When asked to create a script that communicates with an external service, first check if a workspace script already exists with \`search_workspace_scripts\`, then use \`search_hub_scripts\` to search for relevant scripts in the hub. Make sure the language is the same as what the user is coding in. If you do not find any relevant scripts, you can use the \`search_npm_packages\` tool to search for relevant packages and their documentation. Always give a link to the documentation in your answer if possible.
- After applying code changes with the \`${editToolName}\` tool, ALWAYS use the \`get_lint_errors\` tool to check for lint errors. If there are errors, fix them before proceeding. Then use the \`test_run_script\` tool to test the code, and iterate on the code until it works as expected (MAX 3 times). If the user cancels the test run, do not try again and wait for the next user instruction.
Important:
@@ -311,6 +313,8 @@ export function prepareScriptTools(
context: ContextElement[]
): Tool<ScriptChatHelpers>[] {
const tools: Tool<ScriptChatHelpers>[] = []
tools.push(searchWorkspaceScriptsTool)
tools.push(getScriptDetailsTool)
if (['python3', 'php', 'bun', 'deno', 'nativets', 'bunnative'].includes(language)) {
tools.push(resourceTypeTool)
}
@@ -570,6 +574,89 @@ export const searchNpmPackagesTool: Tool<ScriptChatHelpers> = {
}
}
const SEARCH_WORKSPACE_SCRIPTS_TOOL: ChatCompletionFunctionTool = {
type: 'function',
function: {
name: 'search_workspace_scripts',
description:
'Search for scripts in the workspace by query. Use this when the user mentions a specific script, wants to find existing scripts, or wants to reuse code from another script.',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'The search query (e.g. script name, functionality like "send email")'
}
},
required: ['query']
}
}
}
const GET_SCRIPT_DETAILS_TOOL: ChatCompletionFunctionTool = {
type: 'function',
function: {
name: 'get_script_details',
description:
'Get the full details of a workspace script including its code, inputs schema, and description. Use after search_workspace_scripts to inspect a specific script.',
parameters: {
type: 'object',
properties: {
path: {
type: 'string',
description: 'The path of the script (e.g. "f/marketing/send_email")'
}
},
required: ['path']
}
}
}
const workspaceScriptsSearch = new WorkspaceScriptsSearch()
export const searchWorkspaceScriptsTool: Tool<ScriptChatHelpers> = {
def: SEARCH_WORKSPACE_SCRIPTS_TOOL,
fn: async ({ args, workspace, toolId, toolCallbacks }) => {
toolCallbacks.setToolStatus(toolId, {
content: 'Searching for workspace scripts related to "' + args.query + '"...'
})
const scriptResults = await workspaceScriptsSearch.search(args.query, workspace)
toolCallbacks.setToolStatus(toolId, {
content:
'Found ' +
scriptResults.length +
' scripts in the workspace related to "' +
args.query +
'"'
})
return JSON.stringify(scriptResults)
}
}
export const getScriptDetailsTool: Tool<ScriptChatHelpers> = {
def: GET_SCRIPT_DETAILS_TOOL,
fn: async ({ args, workspace, toolId, toolCallbacks }) => {
toolCallbacks.setToolStatus(toolId, {
content: 'Getting details for script "' + args.path + '"...'
})
const script = await ScriptService.getScriptByPath({
workspace,
path: args.path
})
toolCallbacks.setToolStatus(toolId, {
content: 'Retrieved details for "' + args.path + '"'
})
return JSON.stringify({
path: script.path,
summary: script.summary,
description: script.description,
language: script.language,
schema: script.schema,
content: script.content
})
}
}
export async function fetchNpmPackageTypes(
packageName: string,
version: string = 'latest'

View File

@@ -21,7 +21,15 @@ import { workspaceStore } from '$lib/stores'
import type { ExtendedOpenFlow } from '$lib/components/flows/types'
import type { FunctionParameters } from 'openai/resources/shared.mjs'
import { z } from 'zod'
import { ScriptService, JobService, type CompletedJob, type FlowModule } from '$lib/gen'
import {
ScriptService,
JobService,
type CompletedJob,
type FlowModule,
type Script
} from '$lib/gen'
import uFuzzy from '@leeoniya/ufuzzy'
import { emptyString } from '$lib/utils'
import { scriptLangToEditorLang } from '$lib/scripts'
import { getCurrentModel } from '$lib/aiStore'
import { type editor as meditor } from 'monaco-editor'
@@ -526,6 +534,47 @@ export function createToolDef(
}
}
export class WorkspaceScriptsSearch {
private uf: uFuzzy
private workspace: string | undefined = undefined
private scripts: Script[] | undefined = undefined
constructor() {
this.uf = new uFuzzy()
}
private async init(workspace: string) {
this.scripts = await ScriptService.listScripts({
workspace
})
this.workspace = workspace
}
async search(query: string, workspace: string) {
if (this.scripts === undefined || this.workspace !== workspace) {
await this.init(workspace)
}
const scripts = this.scripts
if (!scripts) {
throw new Error('Failed to load scripts')
}
const results = this.uf.search(
scripts.map((s) => (emptyString(s.summary) ? s.path : s.summary + ' (' + s.path + ')')),
query.trim()
)
const scriptResults =
results[2]?.map((id) => ({
path: scripts[id].path,
summary: scripts[id].summary
})) ?? []
return scriptResults
}
}
const searchHubScriptsSchema = z.object({
query: z
.string()

View File

@@ -58,6 +58,7 @@ export interface Setting {
}
hiddenIfNull?: boolean
hiddenIfEmpty?: boolean
hiddenInEe?: boolean
requiresReloadOnChange?: boolean
isValid?: (value: any) => boolean
error?: string
@@ -497,7 +498,8 @@ export const settings: Record<string, Setting[]> = {
label: 'Disable telemetry',
key: 'disable_stats',
fieldType: 'boolean',
storage: 'setting'
storage: 'setting',
hiddenInEe: true
}
],
'Secret Storage': [

View File

@@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi"
[packages]
wmill = ">=1.629.0"
wmill_pg = ">=1.629.0"
wmill = ">=1.629.1"
wmill_pg = ">=1.629.1"
sendgrid = "*"
mysql-connector-python = "*"
pymongo = "*"

View File

@@ -1,7 +1,7 @@
openapi: '3.0.3'
info:
version: 1.629.0
version: 1.629.1
title: OpenFlow Spec
contact:
name: Ruben Fiszel

View File

@@ -12,7 +12,7 @@
RootModule = 'WindmillClient.psm1'
# Version number of this module.
ModuleVersion = '1.629.0'
ModuleVersion = '1.629.1'
# Supported PSEditions
# CompatiblePSEditions = @()

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill"
version = "1.629.0"
version = "1.629.1"
description = "A client library for accessing Windmill server wrapping the Windmill client API"
license = "Apache-2.0"
homepage = "https://windmill.dev"

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill-pg"
version = "1.629.0"
version = "1.629.1"
description = "An extension client for the wmill client library focused on pg"
license = "Apache-2.0"
homepage = "https://windmill.dev"

View File

@@ -1,6 +1,6 @@
{
"name": "@windmill/windmill",
"version": "1.629.0",
"version": "1.629.1",
"exports": "./src/index.ts",
"publish": {
"exclude": ["!src", "./s3Types.ts", "./sqlUtils.ts", "./client.ts"]

View File

@@ -1,7 +1,7 @@
{
"name": "windmill-client",
"description": "Windmill SDK client for browsers and Node.js",
"version": "1.629.0",
"version": "1.629.1",
"author": "Ruben Fiszel",
"license": "Apache 2.0",
"sideEffects": false,

View File

@@ -1 +1 @@
1.629.0
1.629.1