Merge branch 'main' into fr/xyflow

This commit is contained in:
Faton Ramadani
2024-08-14 13:34:59 +02:00
committed by GitHub
60 changed files with 441 additions and 241 deletions
+25
View File
@@ -1,5 +1,30 @@
# Changelog
## [1.379.3](https://github.com/windmill-labs/windmill/compare/v1.379.2...v1.379.3) (2024-08-13)
### Bug Fixes
* improve scrolling performance of the runs page ([0be8982](https://github.com/windmill-labs/windmill/commit/0be8982ddc263b76dab2c87cb6fa63e21effd58c))
## [1.379.2](https://github.com/windmill-labs/windmill/compare/v1.379.1...v1.379.2) (2024-08-13)
### Bug Fixes
* add fetch connection limits to bun type fetcher ([b9924d0](https://github.com/windmill-labs/windmill/commit/b9924d01d54f6dfaf5d719c13a38bb3dccbfe3b9))
* extend step_id being returned as part of the error of every languages ([bcc94ba](https://github.com/windmill-labs/windmill/commit/bcc94badbd848b6838dd0e353c3a30e7a1889ff8))
* **frontend:** date input is more flexible and accept default html format as a fallback ([b424c61](https://github.com/windmill-labs/windmill/commit/b424c61e95e3cc9213d4d3efbe4173857d4e80fd))
* improve logviewer behavior when job is loading ([7a68cc7](https://github.com/windmill-labs/windmill/commit/7a68cc76c2d5d7a66f080afdfcb6c5cd09fc25b5))
## [1.379.1](https://github.com/windmill-labs/windmill/compare/v1.379.0...v1.379.1) (2024-08-13)
### Bug Fixes
* add an option to disable bundling globally ([f00545f](https://github.com/windmill-labs/windmill/commit/f00545f1691c5107d1103f89bf68fdc3915ddd82))
* **apps:** improve tanstack table handling of objects ([1d0807f](https://github.com/windmill-labs/windmill/commit/1d0807f54238c8d8d242e3e5534c6d0868b3172b))
## [1.379.0](https://github.com/windmill-labs/windmill/compare/v1.378.0...v1.379.0) (2024-08-13)
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT coalesce(COUNT(*) FILTER(WHERE suspend = 0), 0) as \"database_length!\", coalesce(COUNT(*) FILTER(WHERE suspend > 0), 0) as \"suspended!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now() AND running = false",
"query": "SELECT coalesce(COUNT(*) FILTER(WHERE suspend = 0 AND running = false), 0) as \"database_length!\", coalesce(COUNT(*) FILTER(WHERE suspend > 0), 0) as \"suspended!\" FROM queue WHERE (workspace_id = $1 OR $2) AND scheduled_for <= now()",
"describe": {
"columns": [
{
@@ -25,5 +25,5 @@
null
]
},
"hash": "44d0c89afbc472165d80ca7a14b391bc2e5c44e0953103790dfe9375f605ee65"
"hash": "28a878c59b6d52f42d315eabb34c96133b69542b01232295c26cc9e093c372f9"
}
+61 -51
View File
@@ -377,7 +377,7 @@ dependencies = [
"arrow-schema",
"chrono",
"half",
"indexmap 2.3.0",
"indexmap 2.4.0",
"lexical-core",
"num",
"serde",
@@ -1105,7 +1105,7 @@ dependencies = [
"serde_urlencoded",
"sync_wrapper 1.0.1",
"tokio",
"tower",
"tower 0.4.13",
"tower-layer",
"tower-service",
"tracing",
@@ -2264,7 +2264,7 @@ dependencies = [
"glob",
"half",
"hashbrown 0.14.5",
"indexmap 2.3.0",
"indexmap 2.4.0",
"itertools 0.12.1",
"log",
"num_cpus",
@@ -2433,7 +2433,7 @@ dependencies = [
"datafusion-expr",
"datafusion-physical-expr",
"hashbrown 0.14.5",
"indexmap 2.3.0",
"indexmap 2.4.0",
"itertools 0.12.1",
"log",
"regex-syntax 0.8.4",
@@ -2462,7 +2462,7 @@ dependencies = [
"half",
"hashbrown 0.14.5",
"hex",
"indexmap 2.3.0",
"indexmap 2.4.0",
"itertools 0.12.1",
"log",
"paste",
@@ -2506,7 +2506,7 @@ dependencies = [
"futures",
"half",
"hashbrown 0.14.5",
"indexmap 2.3.0",
"indexmap 2.4.0",
"itertools 0.12.1",
"log",
"once_cell",
@@ -2664,7 +2664,7 @@ dependencies = [
"tokio-rustls 0.26.0",
"tokio-socks",
"tokio-util",
"tower",
"tower 0.4.13",
"tower-http",
"tower-service",
]
@@ -3884,7 +3884,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http 0.2.12",
"indexmap 2.3.0",
"indexmap 2.4.0",
"slab",
"tokio",
"tokio-util",
@@ -3903,7 +3903,7 @@ dependencies = [
"futures-core",
"futures-sink",
"http 1.1.0",
"indexmap 2.3.0",
"indexmap 2.4.0",
"slab",
"tokio",
"tokio-util",
@@ -4284,7 +4284,7 @@ dependencies = [
"pin-project-lite",
"socket2 0.5.7",
"tokio",
"tower",
"tower 0.4.13",
"tower-service",
"tracing",
]
@@ -4357,9 +4357,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.3.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
dependencies = [
"equivalent",
"hashbrown 0.14.5",
@@ -4539,7 +4539,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee7893dab2e44ae5f9d0173f26ff4aa327c10b01b06a72b52dd9405b628640d"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
]
[[package]]
@@ -5814,7 +5814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
dependencies = [
"fixedbitset",
"indexmap 2.3.0",
"indexmap 2.4.0",
]
[[package]]
@@ -7532,7 +7532,7 @@ version = "1.0.124"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"itoa",
"memchr",
"ryu",
@@ -7636,7 +7636,7 @@ dependencies = [
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.3.0",
"indexmap 2.4.0",
"serde",
"serde_derive",
"serde_json",
@@ -7662,7 +7662,7 @@ version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"itoa",
"ryu",
"serde",
@@ -8042,7 +8042,7 @@ dependencies = [
"hashbrown 0.14.5",
"hashlink",
"hex",
"indexmap 2.3.0",
"indexmap 2.4.0",
"log",
"memchr",
"once_cell",
@@ -8419,7 +8419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b67e115ab136fe0eb03558bb0508ca7782eeb446a96d165508c48617e3fd94"
dependencies = [
"anyhow",
"indexmap 2.3.0",
"indexmap 2.4.0",
"serde",
"serde_json",
"swc_cached",
@@ -8570,7 +8570,7 @@ checksum = "d37dc505c92af56d0f77cf6f31a6ccd37ac40cad1e01ff77277e0b1c70e8f8ff"
dependencies = [
"better_scoped_tls",
"bitflags 2.6.0",
"indexmap 2.3.0",
"indexmap 2.4.0",
"once_cell",
"phf",
"rustc-hash 1.1.0",
@@ -8639,7 +8639,7 @@ checksum = "446da32cac8299973aaf1d37496562bfd0c1e4f3c3ab5d0af6f07f42e8184102"
dependencies = [
"base64 0.21.7",
"dashmap",
"indexmap 2.3.0",
"indexmap 2.4.0",
"once_cell",
"serde",
"sha1",
@@ -8678,7 +8678,7 @@ version = "0.130.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e62b199454a576c5fdbd7e1bef8ab88a395427456d8a713d994b7d469833aa"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"num_cpus",
"once_cell",
"rustc-hash 1.1.0",
@@ -9437,7 +9437,7 @@ version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -9450,7 +9450,7 @@ version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"toml_datetime",
"winnow 0.5.40",
]
@@ -9461,7 +9461,7 @@ version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [
"indexmap 2.3.0",
"indexmap 2.4.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -9497,6 +9497,16 @@ dependencies = [
"tracing",
]
[[package]]
name = "tower"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7"
dependencies = [
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-cookies"
version = "0.10.0"
@@ -9537,15 +9547,15 @@ dependencies = [
[[package]]
name = "tower-layer"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
@@ -10398,7 +10408,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windmill"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"axum",
@@ -10438,7 +10448,7 @@ dependencies = [
[[package]]
name = "windmill-api"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"argon2",
@@ -10501,7 +10511,7 @@ dependencies = [
"tokio-native-tls",
"tokio-tar",
"tokio-util",
"tower",
"tower 0.5.0",
"tower-cookies",
"tower-http",
"tracing",
@@ -10522,7 +10532,7 @@ dependencies = [
[[package]]
name = "windmill-api-client"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"base64 0.21.7",
"chrono",
@@ -10540,7 +10550,7 @@ dependencies = [
[[package]]
name = "windmill-audit"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"chrono",
"serde",
@@ -10553,7 +10563,7 @@ dependencies = [
[[package]]
name = "windmill-common"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"async-stream",
@@ -10568,7 +10578,7 @@ dependencies = [
"hex",
"hmac",
"hyper 1.4.1",
"indexmap 2.3.0",
"indexmap 2.4.0",
"itertools 0.13.0",
"lazy_static",
"magic-crypt",
@@ -10594,7 +10604,7 @@ dependencies = [
[[package]]
name = "windmill-git-sync"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"regex",
"rsmq_async",
@@ -10609,7 +10619,7 @@ dependencies = [
[[package]]
name = "windmill-indexer"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"bytes",
@@ -10630,7 +10640,7 @@ dependencies = [
[[package]]
name = "windmill-parser"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"serde",
"serde_json",
@@ -10638,7 +10648,7 @@ dependencies = [
[[package]]
name = "windmill-parser-bash"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"lazy_static",
@@ -10649,7 +10659,7 @@ dependencies = [
[[package]]
name = "windmill-parser-go"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"gosyn",
@@ -10661,7 +10671,7 @@ dependencies = [
[[package]]
name = "windmill-parser-graphql"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"lazy_static",
@@ -10672,7 +10682,7 @@ dependencies = [
[[package]]
name = "windmill-parser-php"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -10686,7 +10696,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"itertools 0.13.0",
@@ -10697,7 +10707,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py-imports"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"async-recursion",
@@ -10714,7 +10724,7 @@ dependencies = [
[[package]]
name = "windmill-parser-sql"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"lazy_static",
@@ -10725,7 +10735,7 @@ dependencies = [
[[package]]
name = "windmill-parser-ts"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -10744,7 +10754,7 @@ dependencies = [
[[package]]
name = "windmill-parser-wasm"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"getrandom 0.2.15",
@@ -10763,7 +10773,7 @@ dependencies = [
[[package]]
name = "windmill-queue"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"async-recursion",
@@ -10796,7 +10806,7 @@ dependencies = [
[[package]]
name = "windmill-sql-datatype-parser-wasm"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"wasm-bindgen",
"wasm-bindgen-test",
@@ -10806,7 +10816,7 @@ dependencies = [
[[package]]
name = "windmill-worker"
version = "1.379.0"
version = "1.379.3"
dependencies = [
"anyhow",
"async-recursion",
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.379.0"
version = "1.379.3"
authors.workspace = true
edition.workspace = true
@@ -25,7 +25,7 @@ members = [
]
[workspace.package]
version = "1.379.0"
version = "1.379.3"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
+1 -1
View File
@@ -1 +1 @@
80d9e507977b55d0b76272905c969c3d6e830083
c654f4b6406e5d2608446cb644fb23ac1c7287a8
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.379.0
version: 1.379.3
title: Windmill API
contact:
+31 -11
View File
@@ -21,6 +21,9 @@ use axum::{
Json, Router,
};
#[cfg(feature = "enterprise")]
use axum::extract::Query;
use serde::Deserialize;
use windmill_common::{
error::{self, JsonResult, Result},
@@ -237,12 +240,12 @@ pub async fn set_global_setting_internal(
}
v => {
sqlx::query!(
"INSERT INTO global_settings (name, value) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET value = $2, updated_at = now()",
key,
v
)
.execute(db)
.await?;
"INSERT INTO global_settings (name, value) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET value = $2, updated_at = now()",
key,
v
)
.execute(db)
.await?;
tracing::info!("Set global setting {} to {}", key, v);
}
};
@@ -339,6 +342,12 @@ pub async fn get_latest_key_renewal_attempt(
}
}
#[cfg(feature = "enterprise")]
#[derive(Deserialize)]
pub struct LicenseQuery {
license_key: Option<String>,
}
#[cfg(not(feature = "enterprise"))]
pub async fn renew_license_key() -> Result<String> {
return Err(error::Error::BadRequest(
@@ -347,15 +356,23 @@ pub async fn renew_license_key() -> Result<String> {
}
#[cfg(feature = "enterprise")]
pub async fn renew_license_key(Extension(db): Extension<DB>, authed: ApiAuthed) -> Result<String> {
pub async fn renew_license_key(
Extension(db): Extension<DB>,
Query(LicenseQuery { license_key }): Query<LicenseQuery>,
authed: ApiAuthed,
) -> Result<String> {
require_super_admin(&db, &authed.email).await?;
windmill_common::stats_ee::send_stats(&"manual".to_string(), &HTTP_CLIENT, &db).await?;
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, None).await;
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, license_key).await;
if result != "success" {
return Err(error::Error::BadRequest(format!(
"Failed to renew license key: {}",
result
if result == "Unauthorized" {
"Invalid key".to_string()
} else {
result
}
)));
} else {
return Ok("Renewed license key".to_string());
@@ -370,8 +387,11 @@ pub async fn create_customer_portal_session() -> Result<String> {
}
#[cfg(feature = "enterprise")]
pub async fn create_customer_portal_session() -> Result<String> {
let url = windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, None).await?;
pub async fn create_customer_portal_session(
Query(LicenseQuery { license_key }): Query<LicenseQuery>,
) -> Result<String> {
let url =
windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, license_key).await?;
return Ok(url);
}
@@ -30,7 +30,7 @@ pub const DEV_INSTANCE_SETTING: &str = "dev_instance";
pub const JWT_SECRET_SETTING: &str = "jwt_secret";
pub const EMAIL_DOMAIN_SETTING: &str = "email_domain";
pub const ENV_SETTINGS: [&str; 50] = [
pub const ENV_SETTINGS: [&str; 51] = [
"DISABLE_NSJAIL",
"MODE",
"NUM_WORKERS",
@@ -81,4 +81,5 @@ pub const ENV_SETTINGS: [&str; 50] = [
"MAX_WAIT_FOR_SIGTERM",
"WORKER_GROUP",
"SAML_METADATA",
"INSTANCE_IS_DEV",
];
+7 -1
View File
@@ -78,6 +78,11 @@ lazy_static::lazy_static! {
static ref CUSTOM_TAG_REGEX: Regex = Regex::new(r"^(\w+)\(((?:\w+)\+?)+\)$").unwrap();
pub static ref DISABLE_BUNDLING: bool = std::env::var("DISABLE_BUNDLING")
.ok()
.and_then(|x| x.parse::<bool>().ok())
.unwrap_or(false);
}
pub async fn make_suspended_pull_query(wc: &WorkerConfig) {
@@ -232,7 +237,8 @@ pub fn get_annotation(inner_content: &str) -> Annotations {
let native_mode: bool = annotations.contains(&"native".to_string());
//TODO: remove || npm_mode when bun build is more powerful
let nobundling: bool = annotations.contains(&"nobundling".to_string()) || nodejs_mode;
let nobundling: bool =
annotations.contains(&"nobundling".to_string()) || nodejs_mode || *DISABLE_BUNDLING;
Annotations { npm_mode, nodejs_mode, native_mode, nobundling }
}
@@ -561,6 +561,9 @@ pub fn pg_cell_to_json_value(
Type::TIME => get_basic(row, column, column_i, |a: chrono::NaiveTime| {
Ok(JSONValue::String(a.to_string()))
})?,
Type::TIMETZ => get_basic(row, column, column_i, |a: TimeTZStr| {
Ok(JSONValue::String(a.0))
})?,
Type::TIMESTAMPTZ => get_basic(row, column, column_i, |a: chrono::DateTime<Utc>| {
Ok(JSONValue::String(a.to_string()))
})?,
@@ -633,6 +636,9 @@ pub fn pg_cell_to_json_value(
Type::TIME_ARRAY => get_array(row, column, column_i, |a: chrono::NaiveTime| {
Ok(JSONValue::String(a.to_string()))
})?,
Type::TIMETZ_ARRAY => get_array(row, column, column_i, |a: TimeTZStr| {
Ok(JSONValue::String(a.0))
})?,
Type::TIMESTAMPTZ_ARRAY => get_array(row, column, column_i, |a: chrono::DateTime<Utc>| {
Ok(JSONValue::String(a.to_string()))
})?,
@@ -699,6 +705,28 @@ impl<'a> FromSql<'a> for IntervalStr {
}
}
struct TimeTZStr(String);
impl<'a> FromSql<'a> for TimeTZStr {
fn from_sql(
_: &Type,
mut raw: &'a [u8],
) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
let microsecond = raw.get_i64();
let offset = raw.get_i32();
let utc_sec = (microsecond / 1_000_000) + offset as i64;
let utc = chrono::NaiveTime::from_num_seconds_from_midnight_opt(
((utc_sec + 3600 * 24) % (3600 * 24)) as u32,
((microsecond % 1_000_000) * 1_000) as u32,
)
.ok_or_else(|| anyhow::anyhow!("Invalid time value"))?;
Ok(TimeTZStr(format!("{:?} UTC", utc)))
}
fn accepts(ty: &Type) -> bool {
matches!(ty, &Type::TIMETZ)
}
}
fn get_array<'a, T: FromSql<'a>>(
row: &'a Row,
column: &Column,
+19 -4
View File
@@ -2170,9 +2170,20 @@ pub async fn handle_job_error<R: rsmq_async::RsmqConnection + Send + Sync + Clon
tracing::error!(job_id = %job.id, "error handling job: {err:?} {} {} {}", job.id, job.workspace_id, job.created_by);
}
fn extract_error_value(log_lines: &str, i: i32) -> Box<RawValue> {
#[derive(Debug, Serialize)]
struct SerializedError {
message: String,
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
step_id: Option<String>,
}
fn extract_error_value(log_lines: &str, i: i32, step_id: Option<String>) -> Box<RawValue> {
return to_raw_value(
&json!({"message": format!("ExitCode: {i}, last log lines:\n{}", ANSI_ESCAPE_RE.replace_all(log_lines.trim(), "").to_string()), "name": "ExecutionErr"}),
&SerializedError {
message: format!("ExitCode: {i}, last log lines:\n{}", ANSI_ESCAPE_RE.replace_all(log_lines.trim(), "").to_string()),
name: "ExecutionErr".to_string(),
step_id,
},
);
}
@@ -2640,11 +2651,15 @@ async fn process_result(
.last()
.unwrap_or(&last_10_log_lines);
extract_error_value(log_lines, i)
extract_error_value(log_lines, i, job.flow_step_id.clone())
}
}
err @ _ => to_raw_value(
&json!({"message": format!("error during execution of the script:\n{}", err), "name": "ExecutionErr"}),
&SerializedError {
message: format!("error during execution of the script:\n{}", err),
name: "ExecutionErr".to_string(),
step_id: job.flow_step_id.clone(),
},
),
};
+1 -1
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.379.0";
export const VERSION = "v1.379.3";
export async function login(email: string, password: string): Promise<string> {
return await windmill.UserService.login({
+1 -1
View File
@@ -34,7 +34,7 @@ addEventListener("error", (event) => {
}
});
export const VERSION = "v1.379.0";
export const VERSION = "v1.379.3";
let command: any = new Command()
.name("wmill")
+43 -13
View File
@@ -1,12 +1,12 @@
{
"name": "windmill-components",
"version": "1.379.0",
"version": "1.379.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "windmill-components",
"version": "1.379.0",
"version": "1.379.3",
"license": "AGPL-3.0",
"dependencies": {
"@aws-crypto/sha256-js": "^4.0.0",
@@ -41,6 +41,7 @@
"monaco-languageclient": "~7.0.1",
"ol": "^7.4.0",
"openai": "^4.47.1",
"p-limit": "^6.1.0",
"pdfjs-dist": "^3.8.162",
"quill": "^1.3.7",
"rfc4648": "^1.5.3",
@@ -7595,15 +7596,15 @@
}
},
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz",
"integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==",
"license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
"yocto-queue": "^1.1.1"
},
"engines": {
"node": ">=10"
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -7624,6 +7625,35 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate/node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate/node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
@@ -10927,12 +10957,12 @@
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz",
"integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==",
"license": "MIT",
"engines": {
"node": ">=10"
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "windmill-components",
"version": "1.379.0",
"version": "1.379.3",
"scripts": {
"dev": "vite dev",
"build": "vite build",
@@ -122,6 +122,7 @@
"monaco-languageclient": "~7.0.1",
"ol": "^7.4.0",
"openai": "^4.47.1",
"p-limit": "^6.1.0",
"pdfjs-dist": "^3.8.162",
"quill": "^1.3.7",
"rfc4648": "^1.5.3",
+18 -12
View File
@@ -1,5 +1,7 @@
// https://github.com/jsdelivr/data.jsdelivr.com
import pLimit from 'p-limit'
export const getNPMVersionsForModule = (moduleName: string, resLimit: ResLimit) => {
const url = `https://data.jsdelivr.com/v1/package/npm/${moduleName}`
return api<{ tags: Record<string, string>; versions: string[] }>(url, resLimit, {
@@ -51,7 +53,7 @@ export const getDTSFileForModuleWithVersion = async (
) => {
// file comes with a prefix /
const url = `https://cdn.jsdelivr.net/npm/${moduleName}@${version}${file}`
const res = await fetch(url)
const res = await limit(() => fetch(url))
if (res.ok) {
return res.text()
} else {
@@ -67,6 +69,8 @@ export function isOverlimit(resLimit: ResLimit) {
return resLimit.usage > 5000000
}
export const limit = pLimit(6)
function api<T>(url: string, resLimit: ResLimit, init?: RequestInit): Promise<T | Error> {
if (isOverlimit(resLimit)) {
console.warn(
@@ -75,16 +79,18 @@ function api<T>(url: string, resLimit: ResLimit, init?: RequestInit): Promise<T
return new Promise(() => new Error('Exceeded limit of 100MB of data downloaded.'))
}
return fetch(url, init).then((res) => {
if (res.ok) {
return res.text().then((text) => {
resLimit.usage += text.length
console.log('resLimit', url, resLimit.usage)
return limit(() =>
fetch(url, init).then((res) => {
if (res.ok) {
return res.text().then((text) => {
resLimit.usage += text.length
console.log('resLimit', url, resLimit.usage)
return JSON.parse(text) as T
}) as Promise<T | Error>
} else {
return new Error('OK')
}
})
return JSON.parse(text) as T
}) as Promise<T | Error>
} else {
return new Error('OK')
}
})
)
}
+2
View File
@@ -4,6 +4,7 @@ import {
getNPMVersionForModuleReference,
getNPMVersionsForModule,
isOverlimit,
limit,
type NPMTreeMeta,
type ResLimit
} from './apis'
@@ -49,6 +50,7 @@ export const setupTypeAcquisition = (config: ATABootstrapConfig) => {
const moduleMap = new Map<string, ModuleMeta>()
const fsMap = new Map<string, string>()
limit.clearQueue()
let estimatedToDownload = 0
let estimatedDownloaded = 0
+22 -5
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { format, isValid, parse } from 'date-fns'
import { sendUserToast } from '$lib/toast'
export let value: string | undefined = undefined
export let autofocus: boolean | null = false
@@ -12,13 +13,29 @@
const dispatch = createEventDispatcher()
const defaultDateFormat = 'dd-MM-yyyy'
const defaultHtmlDateFormat = 'yyyy-MM-dd'
function computeDate(value: string | undefined) {
if (dateFormat === undefined) {
dateFormat = 'dd-MM-yyyy'
dateFormat = defaultDateFormat
}
if (value) {
const res = format(parse(value, dateFormat, new Date()), 'yyyy-MM-dd')
return res
if (value && value.length > 0) {
try {
let date = parse(value, dateFormat, new Date())
if (date.toString() === 'Invalid Date') {
console.debug('falling back to default html date format')
date = parse(value, defaultHtmlDateFormat, new Date())
}
const res = format(date, defaultHtmlDateFormat)
return res
} catch (error) {
sendUserToast(
`Failed to parse date: ${value} with format ${dateFormat} and ${defaultHtmlDateFormat}`,
true
)
console.error(`Failed to parse date: ${value}`, error)
return undefined
}
} else {
return undefined
}
@@ -27,7 +44,7 @@
function updateValue(newDate: string | undefined) {
if (newDate && isValid(new Date(newDate))) {
if (dateFormat === undefined) {
dateFormat = 'dd-MM-yyyy'
dateFormat = defaultDateFormat
}
try {
@@ -45,6 +45,7 @@
export let noControls: boolean = false
export let drawerOpen = false
export let nodeId: string | undefined = undefined
export let language: string | undefined = undefined
const IMG_MAX_SIZE = 10000000
const TABLE_MAX_SIZE = 5000000
@@ -378,17 +379,14 @@
/>
{/each}</div
>
{:else}
<div
{:else}<div
class="inline-highlight relative grow {['plain', 'markdown'].includes(resultKind ?? '')
? ''
: 'min-h-[200px]'}"
>
{#if result != undefined && length != undefined && largeObject != undefined}
<div class="flex justify-between items-center w-full">
<div class="text-tertiary text-sm">
{#if !hideAsJson && !['json', 's3object'].includes(resultKind ?? '') && typeof result === 'object'}
<ToggleButtonGroup
>{#if result != undefined && length != undefined && largeObject != undefined}<div
class="flex justify-between items-center w-full"
><div class="text-tertiary text-sm">
{#if !hideAsJson && !['json', 's3object'].includes(resultKind ?? '') && typeof result === 'object'}<ToggleButtonGroup
class="h-6"
selected={forceJson ? 'json' : resultKind?.startsWith('table-') ? 'table' : 'pretty'}
on:selected={(ev) => {
@@ -538,13 +536,24 @@
</div>
{:else if !forceJson && resultKind == 'error' && result?.error}
<div class="flex flex-col items-start">
<span class="text-red-500 font-semibold text-sm whitespace-pre-wrap"
<span class="text-red-500 pt-2 font-semibold !text-xs whitespace-pre-wrap"
>{#if result.error.name || result.error.message}{result.error.name}: {result.error
.message}{:else}{JSON.stringify(result.error, null, 4)}{/if}</span
>
<pre class="text-sm whitespace-pre-wrap text-primary">{result.error.stack ?? ''}</pre>
<pre class="text-xs pt-2 whitespace-pre-wrap text-primary"
>{result.error.stack ?? ''}</pre
>
<slot />
</div>
{#if language == 'bun'}
<div class="pt-20" />
<Alert size="xs" type="info" title="Seeing an odd error?">
Bun script are bundled for performance reasons. If you see an odd error that doesn't
appear when testing (which doesn't use bundling), try putting <code>//nobundling</code
> at the top of your script to disable bundling and feel free to mention it to the Windmill's
team.
</Alert>
{/if}
{:else if !forceJson && resultKind == 'approval'}<div class="flex flex-col gap-3 mt-2 mx-4">
<Button
color="green"
@@ -11,6 +11,7 @@
export let workspaceId: string | undefined = undefined
export let flowStateStore: Writable<FlowState> = writable({})
export let selectedJobStep: string | undefined = undefined
export let hideFlowResult = false
export let isOwner = false
export let wideResults = false
@@ -45,6 +46,7 @@
</script>
<FlowStatusViewerInner
{hideFlowResult}
on:jobsLoaded={({ detail }) => {
let { job } = detail
if (job.script_path != lastScriptPath && job.script_path) {
@@ -65,6 +65,7 @@
export let reducedPolling = false
export let wideResults = false
export let hideFlowResult = false
let jobResults: any[] =
flowJobIds?.flowJobs?.map((x, id) => `iter #${id + 1} not loaded by frontend yet`) ?? []
@@ -639,16 +640,18 @@
<Loader2 class="animate-spin" />
</div>
{:else if `result` in job}
<div class="w-full h-full">
<FlowJobResult
workspaceId={job?.workspace_id}
jobId={job?.id}
loading={job['running'] == true}
result={job.result}
logs={job.logs}
durationStates={localDurationStatuses}
/>
</div>
{#if !hideFlowResult}
<div class="w-full h-full">
<FlowJobResult
workspaceId={job?.workspace_id}
jobId={job?.id}
loading={job['running'] == true}
result={job.result}
logs={job.logs}
durationStates={localDurationStatuses}
/>
</div>
{/if}
{:else if job.flow_status?.modules?.[job?.flow_status?.step]?.type === 'WaitingForEvents'}
<FlowStatusWaitingForEvents {workspaceId} {job} {isOwner} />
{:else if $suspendStatus && Object.keys($suspendStatus).length > 0}
@@ -718,6 +718,7 @@
/>
{:else if setting.fieldType == 'password'}
<input
autocomplete="new-password"
type="password"
placeholder={setting.placeholder}
bind:value={values[setting.key]}
@@ -96,10 +96,6 @@
return content
}
$: if (content != undefined && isLoading) {
isLoading = false
}
$: truncatedContent && scrollToBottom()
$: html = ansi_up.ansi_to_html(
@@ -138,7 +138,7 @@
duration={testJob?.['duration_ms']}
mem={testJob?.['mem_peak']}
content={testJob?.logs}
isLoading={testIsLoading}
isLoading={testIsLoading && testJob?.['running'] == false}
tag={testJob?.tag}
/>
</Pane>
@@ -148,7 +148,7 @@
<span class="text-tertiary text-2xs"
>If left empty, will be derived automatically from $AWS_SECRET_KEY, pod or ec2 profile</span
>
<input type="password" bind:value={bucket_config.secret_key} />
<input type="password" autocomplete="new-password" bind:value={bucket_config.secret_key} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Endpoint</span>
@@ -174,7 +174,7 @@
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Access Key</span>
<input type="password" bind:value={bucket_config.accessKey} />
<input type="password" autocomplete="new-password" bind:value={bucket_config.accessKey} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm"
+1 -1
View File
@@ -48,7 +48,7 @@
type="password"
bind:value={password}
on:keydown
autocomplete="off"
autocomplete="new-password"
{placeholder}
{disabled}
/>
@@ -98,7 +98,7 @@
duration={testJob?.['duration_ms']}
mem={testJob?.['mem_peak']}
content={testJob?.logs}
isLoading={testIsLoading}
isLoading={testIsLoading && testJob?.['running'] == false}
tag={testJob?.tag}
/>
</div>
@@ -80,7 +80,11 @@
{:else}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div on:dblclick={toggleEdit}>
{value}
{#if typeof value == 'object'}
{JSON.stringify(value)}
{:else}
{value}
{/if}
</div>
{/if}
</td>
@@ -28,8 +28,11 @@
for (let i = 0; i < objArray.length; i++) {
let line = ''
for (let j = 0; j < headers.length; j++) {
const value = objArray[i][headers[j]]
let value = objArray[i][headers[j]]
line += j ? ',' : ''
if (typeof value != 'string') {
value = JSON.stringify(value)
}
line += /[\",\n]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value
}
str += line + '\r\n'
@@ -173,6 +173,7 @@
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
on:keydown|stopPropagation
type="password"
autocomplete="new-password"
bind:value
placeholder={resolvedConfig.placeholder}
disabled={resolvedConfig.disabled}
@@ -938,17 +938,19 @@
<h2>Public URL</h2>
<div class="mt-4" />
<Toggle
options={{
left: `Require login and read-access`,
right: `No login required`
}}
checked={policy.execution_mode == 'anonymous'}
on:change={(e) => {
policy.execution_mode = e.detail ? 'anonymous' : 'publisher'
setPublishState()
}}
/>
<div class="flex gap-2 items-center">
<Toggle
options={{
left: `Require login and read-access`,
right: `No login required`
}}
checked={policy.execution_mode == 'anonymous'}
on:change={(e) => {
policy.execution_mode = e.detail ? 'anonymous' : 'publisher'
setPublishState()
}}
/>
</div>
<div class="my-6 box">
Public url:
@@ -979,8 +981,10 @@
You will still need to deploy the app to make visible the latest changes
</Alert>
<a href="https://www.windmill.dev/docs/advanced/external_auth_with_jwt#embed-public-apps-using-your-own-authentification" class="mt-4 text-2xs">Embed this app in your own product to be used by your own users</a>
<a
href="https://www.windmill.dev/docs/advanced/external_auth_with_jwt#embed-public-apps-using-your-own-authentification"
class="mt-4 text-2xs">Embed this app in your own product to be used by your own users</a
>
{/if}
</DrawerContent>
</Drawer>
@@ -1149,14 +1153,14 @@
duration={job?.['duration_ms']}
jobId={job?.id}
content={job?.logs}
isLoading={testIsLoading}
isLoading={testIsLoading && job?.['running'] == false}
tag={job?.tag}
/>
</Pane>
<Pane size={50} minSize={10} class="text-sm text-secondary">
{#if job != undefined && 'result' in job && job.result != undefined}
<div class="relative h-full px-2">
<DisplayResult
{#if job != undefined && 'result' in job && job.result != undefined}<div
class="relative h-full px-2"
><DisplayResult
workspaceId={$workspaceStore}
jobId={selectedJobId}
result={job.result}
@@ -70,27 +70,27 @@
duration={testJob?.['duration_ms']}
mem={testJob?.['mem_peak']}
content={testJob?.logs}
isLoading={testIsLoading}
isLoading={testIsLoading && testJob?.['running'] == false}
tag={testJob?.tag}
/>
{/if}
</Pane>
<Pane size={frontendJob ? 70 : 50} minSize={10} class="text-sm text-tertiary">
{#if frontendJob}
<pre class="overflow-x-auto break-words relative h-full px-2 pt-2"
><DisplayResult bind:drawerOpen={resultDrawerOpen} result={frontendJob} /></pre
>
<div class="break-words relative h-full px-1">
<DisplayResult bind:drawerOpen={resultDrawerOpen} result={frontendJob} />
</div>
{:else if testJob != undefined && 'result' in testJob && testJob.result != undefined}
<pre class="overflow-x-auto break-words relative h-full px-2 pt-2"
><DisplayResult
<div class="break-words relative h-full px-1">
<DisplayResult
bind:drawerOpen={resultDrawerOpen}
workspaceId={testJob?.workspace_id}
jobId={testJob?.id}
result={testJob.result}
/></pre
/></div
>
{:else}
<div class="p-2">
<div class="px-1 pt-1">
{#if testIsLoading}
<Loader2 class="animate-spin" />
{:else}
@@ -33,9 +33,10 @@
import { goto as gotoUrl } from '$app/navigation'
import { page } from '$app/stores'
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
import { DELETE, copyToClipboard, isDeployable } from '$lib/utils'
import { DELETE, copyToClipboard } from '$lib/utils'
import AppDeploymentHistory from '$lib/components/apps/editor/AppDeploymentHistory.svelte'
import AppJsonEditor from '$lib/components/apps/editor/AppJsonEditor.svelte'
import { isDeployable } from '$lib/utils_deployable'
export let app: ListableApp & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
export let marked: string | undefined
@@ -14,7 +14,9 @@
import Row from './Row.svelte'
import DraftBadge from '$lib/components/DraftBadge.svelte'
import { sendUserToast } from '$lib/toast'
import { DELETE, copyToClipboard, isDeployable, isOwner } from '$lib/utils'
import { DELETE, copyToClipboard, isOwner } from '$lib/utils'
import { isDeployable } from '$lib/utils_deployable'
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
import {
Pen,
@@ -15,7 +15,7 @@
import { goto } from '$lib/navigation'
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
import { FileUp, Globe, Pen, Share, Trash } from 'lucide-svelte'
import { isDeployable } from '$lib/utils'
import { isDeployable } from '$lib/utils_deployable'
export let app: ListableRawApp & { canWrite: boolean }
export let marked: string | undefined
@@ -21,7 +21,9 @@
import Row from './Row.svelte'
import DraftBadge from '$lib/components/DraftBadge.svelte'
import { sendUserToast } from '$lib/toast'
import { copyToClipboard, DELETE, isDeployable, isOwner } from '$lib/utils'
import { copyToClipboard, DELETE, isOwner } from '$lib/utils'
import { isDeployable } from '$lib/utils_deployable'
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
import { LanguageIcon } from '../languageIcons'
import {
@@ -155,6 +155,7 @@ declare const error: {
message: string
name: string
stack: string
step_id: string
}
/**
+1 -1
View File
@@ -12,7 +12,7 @@
import { ArrowBigUp } from 'lucide-svelte'
import { enterpriseLicense, workspaceStore } from '$lib/stores'
import { WorkspaceService, type WorkspaceDeployUISettings } from '$lib/gen'
import { ALL_DEPLOYABLE } from '$lib/utils'
import { ALL_DEPLOYABLE } from '$lib/utils_deployable'
export let item
export let depth: number = 0
@@ -144,7 +144,7 @@
duration={job?.['duration_ms']}
mem={job?.['mem_peak']}
content={job?.logs}
isLoading
isLoading={job?.['running'] == false}
tag={job?.tag}
/>
{/if}
@@ -113,7 +113,8 @@
error: {
message: 'The error message',
name: 'The error name',
stack: 'The error stack'
stack: 'The error stack',
step_id: 'The step id'
}
}}
on:select
@@ -185,7 +185,7 @@
jobId={job.id}
duration={job?.['duration_ms']}
mem={job?.['mem_peak']}
isLoading={!(job && 'logs' in job && job.logs)}
isLoading={job?.['running'] == false}
content={job?.logs}
tag={job?.tag}
/>
@@ -226,7 +226,7 @@
duration={job?.['duration_ms']}
mem={job?.['mem_peak']}
content={job?.logs}
isLoading
isLoading={job?.['running'] == false}
tag={job?.tag}
/>
{/if}
@@ -39,8 +39,6 @@
$: isExternal = job && job.id === '-'
let triggeredByWidth: number = 0
function isJobCancelable(j: Job): boolean {
return j.type === 'QueuedJob' && !j.schedule_path
}
@@ -240,7 +238,7 @@
{/if}
</div>
{/if}
<div class="w-3/12 flex justify-start" bind:clientWidth={triggeredByWidth}>
<div class="w-3/12 flex justify-start">
{#if job && job.schedule_path}
<div class="flex flex-row items-center gap-1">
<Calendar size={14} />
@@ -250,11 +248,8 @@
btnClasses="font-normal"
on:click={() => scheduleEditor?.openEdit(job.schedule_path ?? '', job.job_kind == 'flow')}
>
<div
class="truncate text-ellipsis text-left"
style="max-width: {triggeredByWidth - 48}px"
>
{job.schedule_path}
<div class="truncate text-ellipsis text-left">
{truncateRev(job.schedule_path, 20)}
</div>
</Button>
<Button
@@ -113,7 +113,7 @@
duration={previewJob?.['duration_ms']}
mem={previewJob?.['mem_peak']}
content={previewJob?.logs}
isLoading={previewIsLoading}
isLoading={previewJob?.['running'] == false && previewIsLoading}
tag={previewJob?.tag}
/>
</Pane>
+8 -4
View File
@@ -1,6 +1,7 @@
import { get } from 'svelte/store'
import { dbClockDrift } from './stores'
import { JobService } from './gen'
import pLimit from 'p-limit'
function subtractSeconds(date: Date, seconds: number): Date {
date.setSeconds(date.getSeconds() - seconds)
@@ -12,19 +13,22 @@ function adjustDate(drift: number): Date {
}
export async function computeDrift() {
const now = Date.now()
const dbClock = await JobService.getDbClock()
dbClockDrift.set(dbClock - now)
if (get(dbClockDrift) == undefined) {
const now = Date.now()
const dbClock = await JobService.getDbClock()
dbClockDrift.set(dbClock - now)
}
}
export function forLater(scheduledString: string): boolean {
return getDbClockNow() < subtractSeconds(new Date(scheduledString), 5)
}
const limit = pLimit(1)
export function getDbClockNow() {
let drift = get(dbClockDrift)
if (drift == undefined) {
computeDrift()
limit(() => computeDrift())
drift = 0
}
return adjustDate(drift)
-32
View File
@@ -14,7 +14,6 @@ import { sendUserToast } from './toast'
import type { Script, WorkspaceDeployUISettings } from './gen'
import type { EnumType, SchemaProperty } from './common'
import type { Schema } from './common'
import { minimatch } from 'minimatch'
export { sendUserToast }
export function validateUsername(username: string): string {
@@ -941,34 +940,3 @@ export function getSchemaFromProperties(properties: { [name: string]: SchemaProp
order: Object.keys(properties).filter((k) => k !== 'label')
}
}
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret'
export function isDeployable(
type: DeployUIType,
path: string,
deployUiSettings: WorkspaceDeployUISettings | undefined
) {
if (deployUiSettings == undefined) {
return false
}
if (deployUiSettings.include_type != undefined && !deployUiSettings.include_type.includes(type)) {
return false
}
if (
deployUiSettings.include_path != undefined &&
deployUiSettings.include_path.length != 0 &&
deployUiSettings.include_path.every((x) => !minimatch(path, x))
) {
return false
}
return true
}
export const ALL_DEPLOYABLE: WorkspaceDeployUISettings = {
include_path: [],
include_type: ['script', 'flow', 'app', 'resource', 'variable', 'secret']
}
+33
View File
@@ -0,0 +1,33 @@
import { minimatch } from 'minimatch'
import type { WorkspaceDeployUISettings } from './gen'
type DeployUIType = 'script' | 'flow' | 'app' | 'resource' | 'variable' | 'secret'
export function isDeployable(
type: DeployUIType,
path: string,
deployUiSettings: WorkspaceDeployUISettings | undefined
) {
if (deployUiSettings == undefined) {
return false
}
if (deployUiSettings.include_type != undefined && !deployUiSettings.include_type.includes(type)) {
return false
}
if (
deployUiSettings.include_path != undefined &&
deployUiSettings.include_path.length != 0 &&
deployUiSettings.include_path.every((x) => !minimatch(path, x))
) {
return false
}
return true
}
export const ALL_DEPLOYABLE: WorkspaceDeployUISettings = {
include_path: [],
include_type: ['script', 'flow', 'app', 'resource', 'variable', 'secret']
}
@@ -8,7 +8,8 @@
type FlowModule,
type WorkspaceDeployUISettings
} from '$lib/gen'
import { ALL_DEPLOYABLE, canWrite, defaultIfEmptyString, emptyString, isDeployable } from '$lib/utils'
import { canWrite, defaultIfEmptyString, emptyString } from '$lib/utils'
import { isDeployable, ALL_DEPLOYABLE } from '$lib/utils_deployable'
import DetailPageLayout from '$lib/components/details/DetailPageLayout.svelte'
import { goto } from '$lib/navigation'
@@ -31,7 +31,9 @@
import { OauthService, ResourceService, WorkspaceService, type ListableResource } from '$lib/gen'
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
import { sendUserToast } from '$lib/toast'
import { ALL_DEPLOYABLE, canWrite, classNames, emptySchema, isDeployable, removeMarkdown, truncate } from '$lib/utils'
import { canWrite, classNames, emptySchema, removeMarkdown, truncate } from '$lib/utils'
import { isDeployable, ALL_DEPLOYABLE } from '$lib/utils_deployable'
import { convert } from '@redocly/json-to-json-schema'
import {
Braces,
@@ -751,7 +751,7 @@
jobId={job.id}
duration={job?.['duration_ms']}
mem={job?.['mem_peak']}
isLoading={!(job && 'logs' in job && job.logs)}
isLoading={job?.['running'] == false}
content={job?.logs}
tag={job?.tag}
/>
@@ -775,6 +775,7 @@
workspaceId={job?.workspace_id}
jobId={job?.id}
result={job.result}
language={job.language}
/>
{:else if job}
No output is available yet
@@ -1,20 +1,19 @@
<script lang="ts">
import { page } from '$app/stores'
import { base } from '$lib/base'
import { JobService, ScriptService, WorkspaceService, type Script, type WorkspaceDeployUISettings } from '$lib/gen'
import {
defaultIfEmptyString,
emptyString,
canWrite,
truncateHash,
isDeployable,
ALL_DEPLOYABLE
} from '$lib/utils'
JobService,
ScriptService,
WorkspaceService,
type Script,
type WorkspaceDeployUISettings
} from '$lib/gen'
import { defaultIfEmptyString, emptyString, canWrite, truncateHash } from '$lib/utils'
import Tooltip from '$lib/components/Tooltip.svelte'
import ShareModal from '$lib/components/ShareModal.svelte'
import { enterpriseLicense, hubBaseUrlStore, userStore, workspaceStore } from '$lib/stores'
import { isDeployable, ALL_DEPLOYABLE } from '$lib/utils_deployable'
import SchemaViewer from '$lib/components/SchemaViewer.svelte'
import { onDestroy } from 'svelte'
import HighlightCode from '$lib/components/HighlightCode.svelte'
@@ -203,7 +203,12 @@
<span class="text-2xs text-tertiary ml-2">(optional but recommended)</span>
</span>
<div class="flex flex-row gap-1">
<input type="password" bind:value={openAiKey} on:keyup={handleKeyUp} />
<input
type="password"
autocomplete="new-password"
bind:value={openAiKey}
on:keyup={handleKeyUp}
/>
<TestOpenaiKey apiKey={openAiKey} disabled={!openAiKey} />
</div>
{#if openAiKey}
@@ -22,7 +22,8 @@
import { OauthService, VariableService, WorkspaceService } from '$lib/gen'
import { enterpriseLicense, userStore, workspaceStore } from '$lib/stores'
import { sendUserToast } from '$lib/toast'
import { ALL_DEPLOYABLE, canWrite, isDeployable, isOwner, truncate } from '$lib/utils'
import { canWrite, isOwner, truncate } from '$lib/utils'
import { isDeployable, ALL_DEPLOYABLE } from '$lib/utils_deployable'
import {
Plus,
FileUp,
+2 -2
View File
@@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi"
[packages]
wmill = ">=1.379.0"
wmill_pg = ">=1.379.0"
wmill = ">=1.379.3"
wmill_pg = ">=1.379.3"
sendgrid = "*"
mysql-connector-python = "*"
pymongo = "*"
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.379.0
version: 1.379.3
title: OpenFlow Spec
contact:
name: Ruben Fiszel
@@ -12,7 +12,7 @@
RootModule = 'WindmillClient.psm1'
# Version number of this module.
ModuleVersion = '1.379.0'
ModuleVersion = '1.379.3'
# Supported PSEditions
# CompatiblePSEditions = @()
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill"
version = "1.379.0"
version = "1.379.3"
description = "A client library for accessing Windmill server wrapping the Windmill client API"
license = "Apache-2.0"
homepage = "https://windmill.dev"
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill-pg"
version = "1.379.0"
version = "1.379.3"
description = "An extension client for the wmill client library focused on pg"
license = "Apache-2.0"
homepage = "https://windmill.dev"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@windmill/windmill",
"version": "1.379.0",
"version": "1.379.3",
"exports": "./src/index.ts",
"publish": {
"exclude": ["!src", "./s3Types.ts", "./client.ts"]
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "windmill-client",
"description": "Windmill SDK client for browsers and Node.js",
"version": "1.379.0",
"version": "1.379.3",
"author": "Ruben Fiszel",
"license": "Apache 2.0",
"devDependencies": {
+1 -1
View File
@@ -1 +1 @@
1.379.0
1.379.3