fix(frontend): wip

This commit is contained in:
Faton Ramadani
2024-08-05 10:38:54 +02:00
54 changed files with 630 additions and 313 deletions
@@ -0,0 +1,45 @@
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/caddy-l4
name: Build caddy-l4
on:
workflow_dispatch:
permissions: write-all
jobs:
build_ee:
runs-on: ubicloud
steps:
- uses: actions/checkout@v4
- uses: depot/setup-action@v1
- name: Docker meta
id: meta-ee-public
uses: docker/metadata-action@v4
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Login to registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push publicly
uses: depot/build-push-action@v1
with:
context: ./docker
file: ./docker/DockerfileCaddyL4
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ steps.meta-ee-public.outputs.tags }}
labels: |
${{ steps.meta-ee-public.outputs.labels }}
+21
View File
@@ -1,5 +1,26 @@
# Changelog
## [1.374.0](https://github.com/windmill-labs/windmill/compare/v1.373.1...v1.374.0) (2024-08-04)
### Features
* add support for assets using tar for codebase deploy ([3508b6d](https://github.com/windmill-labs/windmill/commit/3508b6d793b0ce21c0c264a50bb000cd61c21920))
* caddy with l4 image ([#4178](https://github.com/windmill-labs/windmill/issues/4178)) ([811de58](https://github.com/windmill-labs/windmill/commit/811de58712f619045a3653fe5b98ff0c7599f392))
### Bug Fixes
* fix delete job ([86e23f2](https://github.com/windmill-labs/windmill/commit/86e23f2aed234a64fce46e1b6253f788546876af))
## [1.373.1](https://github.com/windmill-labs/windmill/compare/v1.373.0...v1.373.1) (2024-08-02)
### Bug Fixes
* fix run_flow_async from call ([63abd5b](https://github.com/windmill-labs/windmill/commit/63abd5b14606869eafbd25d8469638b85b96e199))
* **frontend:** Add support for array of objects in th UI ([#4170](https://github.com/windmill-labs/windmill/issues/4170)) ([91e364b](https://github.com/windmill-labs/windmill/commit/91e364bde5459447945d7dae65c1cab2858c69ac))
## [1.373.0](https://github.com/windmill-labs/windmill/compare/v1.372.0...v1.373.0) (2024-08-01)
+86 -88
View File
@@ -72,7 +72,7 @@ dependencies = [
"getrandom 0.2.15",
"once_cell",
"version_check",
"zerocopy 0.7.35",
"zerocopy",
]
[[package]]
@@ -518,7 +518,7 @@ dependencies = [
"tokio",
"xz2",
"zstd 0.13.2",
"zstd-safe 7.2.0",
"zstd-safe 7.2.1",
]
[[package]]
@@ -1256,7 +1256,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"rustc-hash 1.1.0",
"shlex",
"syn 2.0.72",
"which 4.4.2",
@@ -1503,9 +1503,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9"
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "bytes-utils"
@@ -2684,7 +2684,7 @@ dependencies = [
"dlopen2_derive",
"once_cell",
"rustls-native-certs 0.7.1",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
]
[[package]]
@@ -2766,7 +2766,7 @@ dependencies = [
"deno_core",
"deno_native_certs",
"rustls 0.23.12",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"rustls-tokio-stream",
"rustls-webpki 0.102.6",
"serde",
@@ -3026,7 +3026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b909f9f9b22a6265839887544dce97b0b8e2b2635abf622f45613deb3de63e0"
dependencies = [
"num-bigint",
"rustc-hash",
"rustc-hash 1.1.0",
"swc_atoms",
"swc_common 0.34.4",
"swc_ecma_ast 0.115.1",
@@ -3307,9 +3307,9 @@ dependencies = [
[[package]]
name = "flate2"
version = "1.0.30"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920"
dependencies = [
"crc32fast",
"libz-sys",
@@ -4050,7 +4050,7 @@ dependencies = [
"new_debug_unreachable",
"once_cell",
"phf",
"rustc-hash",
"rustc-hash 1.1.0",
"triomphe",
]
@@ -6072,11 +6072,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.18"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy 0.6.6",
"zerocopy",
]
[[package]]
@@ -6384,16 +6384,17 @@ dependencies = [
[[package]]
name = "quinn"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad"
checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156"
dependencies = [
"bytes",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustc-hash 2.0.0",
"rustls 0.23.12",
"socket2 0.5.7",
"thiserror",
"tokio",
"tracing",
@@ -6401,14 +6402,14 @@ dependencies = [
[[package]]
name = "quinn-proto"
version = "0.11.3"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe"
checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd"
dependencies = [
"bytes",
"rand 0.8.5",
"ring 0.17.8",
"rustc-hash",
"rustc-hash 2.0.0",
"rustls 0.23.12",
"slab",
"thiserror",
@@ -6425,6 +6426,7 @@ dependencies = [
"libc",
"once_cell",
"socket2 0.5.7",
"tracing",
"windows-sys 0.52.0",
]
@@ -6638,9 +6640,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.10.5"
version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick",
"memchr",
@@ -6787,7 +6789,7 @@ dependencies = [
"quinn",
"rustls 0.23.12",
"rustls-native-certs 0.7.1",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"rustls-pki-types",
"serde",
"serde_json",
@@ -7021,6 +7023,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hash"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustc_version"
version = "0.2.3"
@@ -7125,7 +7133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
dependencies = [
"openssl-probe",
"rustls-pemfile 2.1.2",
"rustls-pemfile 2.1.3",
"rustls-pki-types",
"schannel",
"security-framework",
@@ -7142,9 +7150,9 @@ dependencies = [
[[package]]
name = "rustls-pemfile"
version = "2.1.2"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
dependencies = [
"base64 0.22.1",
"rustls-pki-types",
@@ -7214,7 +7222,7 @@ dependencies = [
"num-traits",
"phf",
"phf_codegen",
"rustc-hash",
"rustc-hash 1.1.0",
"rustpython-ast",
"rustpython-parser-core",
"tiny-keccak",
@@ -7507,9 +7515,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.121"
version = "1.0.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
dependencies = [
"indexmap 2.3.0",
"itoa",
@@ -7889,7 +7897,7 @@ dependencies = [
"data-encoding",
"debugid",
"if_chain",
"rustc-hash",
"rustc-hash 1.1.0",
"rustc_version 0.2.3",
"serde",
"serde_json",
@@ -8322,7 +8330,7 @@ checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125"
dependencies = [
"hstr",
"once_cell",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
]
@@ -8354,7 +8362,7 @@ dependencies = [
"new_debug_unreachable",
"num-bigint",
"once_cell",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"siphasher",
"swc_atoms",
@@ -8379,7 +8387,7 @@ dependencies = [
"new_debug_unreachable",
"num-bigint",
"once_cell",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"siphasher",
"sourcemap",
@@ -8461,7 +8469,7 @@ dependencies = [
"memchr",
"num-bigint",
"once_cell",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"sourcemap",
"swc_atoms",
@@ -8552,7 +8560,7 @@ dependencies = [
"indexmap 2.3.0",
"once_cell",
"phf",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"smallvec",
"swc_atoms",
@@ -8597,7 +8605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6df8aa6752cc2fcf3d78ac67827542fb666e52283f2b26802aa058906bb750d3"
dependencies = [
"either",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"smallvec",
"swc_atoms",
@@ -8660,7 +8668,7 @@ dependencies = [
"indexmap 2.3.0",
"num_cpus",
"once_cell",
"rustc-hash",
"rustc-hash 1.1.0",
"ryu-js",
"swc_atoms",
"swc_common 0.34.4",
@@ -8867,7 +8875,7 @@ dependencies = [
"rayon",
"regex",
"rust-stemmers",
"rustc-hash",
"rustc-hash 1.1.0",
"serde",
"serde_json",
"sketches-ddsketch",
@@ -8995,12 +9003,13 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.10.1"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
dependencies = [
"cfg-if",
"fastrand 2.1.0",
"once_cell",
"rustix 0.38.34",
"windows-sys 0.52.0",
]
@@ -10359,11 +10368,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -10374,7 +10383,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windmill"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"axum",
@@ -10414,7 +10423,7 @@ dependencies = [
[[package]]
name = "windmill-api"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"argon2",
@@ -10493,7 +10502,7 @@ dependencies = [
[[package]]
name = "windmill-api-client"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"base64 0.21.7",
"chrono",
@@ -10511,7 +10520,7 @@ dependencies = [
[[package]]
name = "windmill-audit"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"chrono",
"serde",
@@ -10524,7 +10533,7 @@ dependencies = [
[[package]]
name = "windmill-common"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"async-stream",
@@ -10565,7 +10574,7 @@ dependencies = [
[[package]]
name = "windmill-git-sync"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"regex",
"rsmq_async",
@@ -10580,7 +10589,7 @@ dependencies = [
[[package]]
name = "windmill-indexer"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"bytes",
@@ -10601,7 +10610,7 @@ dependencies = [
[[package]]
name = "windmill-parser"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"serde",
"serde_json",
@@ -10609,7 +10618,7 @@ dependencies = [
[[package]]
name = "windmill-parser-bash"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10620,7 +10629,7 @@ dependencies = [
[[package]]
name = "windmill-parser-go"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"gosyn",
@@ -10632,7 +10641,7 @@ dependencies = [
[[package]]
name = "windmill-parser-graphql"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10643,7 +10652,7 @@ dependencies = [
[[package]]
name = "windmill-parser-php"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -10657,7 +10666,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"itertools 0.13.0",
@@ -10668,7 +10677,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py-imports"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"async-recursion",
@@ -10685,7 +10694,7 @@ dependencies = [
[[package]]
name = "windmill-parser-sql"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10696,7 +10705,7 @@ dependencies = [
[[package]]
name = "windmill-parser-ts"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -10715,7 +10724,7 @@ dependencies = [
[[package]]
name = "windmill-parser-wasm"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"getrandom 0.2.15",
@@ -10734,7 +10743,7 @@ dependencies = [
[[package]]
name = "windmill-queue"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"async-recursion",
@@ -10767,7 +10776,7 @@ dependencies = [
[[package]]
name = "windmill-sql-datatype-parser-wasm"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"wasm-bindgen",
"wasm-bindgen-test",
@@ -10777,7 +10786,7 @@ dependencies = [
[[package]]
name = "windmill-worker"
version = "1.373.0"
version = "1.374.0"
dependencies = [
"anyhow",
"async-recursion",
@@ -10875,6 +10884,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
@@ -11105,34 +11123,14 @@ dependencies = [
"synstructure",
]
[[package]]
name = "zerocopy"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [
"byteorder",
"zerocopy-derive 0.6.6",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy-derive"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.72",
"byteorder",
"zerocopy-derive",
]
[[package]]
@@ -11217,7 +11215,7 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
dependencies = [
"zstd-safe 7.2.0",
"zstd-safe 7.2.1",
]
[[package]]
@@ -11242,9 +11240,9 @@ dependencies = [
[[package]]
name = "zstd-safe"
version = "7.2.0"
version = "7.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa"
checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
dependencies = [
"zstd-sys",
]
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.373.0"
version = "1.374.0"
authors.workspace = true
edition.workspace = true
@@ -25,7 +25,7 @@ members = [
]
[workspace.package]
version = "1.373.0"
version = "1.374.0"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.373.0
version: 1.374.0
title: Windmill API
contact:
+1 -1
View File
@@ -5003,7 +5003,7 @@ async fn delete_completed_job<'a>(
require_admin(authed.is_admin, &authed.username)?;
let job_o = sqlx::query_as::<_, CompletedJob>(
"UPDATE completed_job SET args = null, logs = '', result = null, deleted = true WHERE id = $1 AND workspace_id = $2 \
RETURNING *",
RETURNING *, null as labels",
)
.bind(id)
.bind(&w_id)
+11 -5
View File
@@ -352,13 +352,16 @@ async fn create_snapshot_script(
let mut script_hash = None;
let mut tx = None;
let mut uploaded = false;
while let Some(field) = multipart.next_field().await.unwrap() {
let name = field.name().unwrap().to_string();
let data = field.bytes().await.unwrap();
if name == "script" {
let ns = Some(serde_json::from_slice(&data).map_err(to_anyhow)?);
let ns: NewScript = Some(serde_json::from_slice(&data).map_err(to_anyhow)?).unwrap();
let is_tar = ns.codebase.as_ref().is_some_and(|x| x.ends_with(".tar"));
let (new_hash, ntx) = create_script_internal(
ns.unwrap(),
ns,
w_id.clone(),
authed.clone(),
db.clone(),
@@ -367,7 +370,8 @@ async fn create_snapshot_script(
webhook.clone(),
)
.await?;
script_hash = Some(new_hash.to_string());
let nh = new_hash.to_string();
script_hash = Some(if is_tar { format!("{nh}.tar") } else { nh });
tx = Some(ntx);
}
if name == "file" {
@@ -567,19 +571,21 @@ async fn create_script_internal<'c>(
.as_ref()
.map(|v| v.perms.clone())
.unwrap_or(json!({}));
let lock = if !(ns.language == ScriptLang::Python3
let lock = if ns.codebase.is_some() {
Some(String::new())
} else if !(ns.language == ScriptLang::Python3
|| ns.language == ScriptLang::Go
|| ns.language == ScriptLang::Bun
|| ns.language == ScriptLang::Bunnative
|| ns.language == ScriptLang::Deno
|| ns.language == ScriptLang::Php)
|| ns.codebase.is_some()
{
Some(String::new())
} else {
ns.lock
.and_then(|e| if e.is_empty() { None } else { Some(e) })
};
let needs_lock_gen = lock.is_none() && codebase.is_none();
let envs = ns.envs.as_ref().map(|x| x.as_slice());
let envs = if ns.envs.is_none() || ns.envs.as_ref().unwrap().is_empty() {
+1
View File
@@ -150,6 +150,7 @@ pub struct Script {
pub deleted: bool,
pub is_template: bool,
pub extra_perms: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub lock: Option<String>,
pub lock_error_logs: Option<String>,
pub language: ScriptLang,
+18 -6
View File
@@ -501,24 +501,36 @@ pub async fn generate_bun_bundle(
#[cfg(all(feature = "enterprise", feature = "parquet"))]
pub async fn pull_codebase(w_id: &str, id: &str, job_dir: &str) -> Result<()> {
use crate::global_cache::extract_tar;
let path = windmill_common::s3_helpers::bundle(&w_id, &id);
let bun_cache_path = format!("{}/{}", BUN_CACHE_DIR, path);
let dst = format!("{job_dir}/main.js");
let bun_cache_path = format!("{}/{}", crate::ROOT_CACHE_NOMOUNT_DIR, path);
let is_tar = id.ends_with(".tar");
let dst = format!(
"{job_dir}/{}",
if is_tar { "codebase.tar" } else { "main.js" }
);
let dirs_splitted = bun_cache_path.split("/").collect_vec();
tokio::fs::create_dir_all(dirs_splitted[..dirs_splitted.len() - 1].join("/")).await?;
if tokio::fs::metadata(&bun_cache_path).await.is_ok() {
tracing::info!("loading {bun_cache_path} from cache");
tokio::fs::symlink(&bun_cache_path, dst).await?;
if is_tar {
extract_tar(fs::read(bun_cache_path)?.into(), job_dir).await?;
} else {
tokio::fs::symlink(&bun_cache_path, dst).await?;
}
} else if let Some(os) = windmill_common::s3_helpers::OBJECT_STORE_CACHE_SETTINGS
.read()
.await
.clone()
{
let bytes = attempt_fetch_bytes(os, &path).await?;
if *windmill_common::worker::CLOUD_HOSTED {
tokio::fs::write(dst, &bytes).await?;
tokio::fs::write(&bun_cache_path, &bytes).await?;
if is_tar {
extract_tar(bytes, job_dir).await?;
} else {
tokio::fs::write(&bun_cache_path, &bytes).await?;
tokio::fs::symlink(bun_cache_path, dst).await?;
}
+10 -4
View File
@@ -2743,10 +2743,10 @@ pub async fn get_script_content_by_hash(
Option<String>,
Option<ScriptLang>,
Option<Vec<String>>,
bool,
Option<bool>,
),
>(
"SELECT content, lock, language, envs, codebase IS NOT NULL FROM script WHERE hash = $1 AND workspace_id = $2",
"SELECT content, lock, language, envs, codebase LIKE '%.tar' as codebase FROM script WHERE hash = $1 AND workspace_id = $2",
)
.bind(script_hash.0)
.bind(w_id)
@@ -2758,8 +2758,14 @@ pub async fn get_script_content_by_hash(
lockfile: r.1,
language: r.2,
envs: r.3,
codebase: if r.4 {
Some(script_hash.to_string())
codebase: if r.4.is_some() {
let b = r.4.unwrap();
let sh = script_hash.to_string();
if b {
Some(format!("{sh}.tar"))
} else {
Some(sh)
}
} else {
None
},
+16 -14
View File
@@ -952,21 +952,23 @@ pub async fn update_flow_status_after_job_completion_internal<
let _ = tokio::fs::remove_dir_all(format!("{worker_dir}/{}", flow_job.id)).await;
}
if let Some(parent_job) = flow_job.parent_job {
tracing::info!(subflow_id = %flow_job.id, parent_id = %parent_job, "subflow is finished, updating parent flow status");
if flow_job.is_flow_step {
if let Some(parent_job) = flow_job.parent_job {
tracing::info!(subflow_id = %flow_job.id, parent_id = %parent_job, "subflow is finished, updating parent flow status");
return Ok(Some(RecUpdateFlowStatusAfterJobCompletion {
flow: parent_job,
job_id_for_status: flow,
success: success && !is_failure_step,
result: nresult.clone(),
stop_early_override: if stop_early {
Some(skip_if_stop_early)
} else {
None
},
skip_error_handler: skip_error_handler || is_failure_step,
}));
return Ok(Some(RecUpdateFlowStatusAfterJobCompletion {
flow: parent_job,
job_id_for_status: flow,
success: success && !is_failure_step,
result: nresult.clone(),
stop_early_override: if stop_early {
Some(skip_if_stop_early)
} else {
None
},
skip_error_handler: skip_error_handler || is_failure_step,
}));
}
}
Ok(None)
} else {
+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.373.0";
export const VERSION = "v1.374.0";
export async function login(email: string, password: string): Promise<string> {
return await windmill.UserService.login({
+7 -1
View File
@@ -12,7 +12,13 @@ export async function listSyncCodebases(
log.info(`Found ${nb_codebase} codebases:`);
}
for (const codebase of options?.codebases ?? []) {
const digest = await digestDir(codebase.relative_path);
let digest = await digestDir(
codebase.relative_path,
JSON.stringify(codebase)
);
if (Array.isArray(codebase.assets) && codebase.assets.length > 0) {
digest += ".tar";
}
log.info(`Codebase ${codebase.relative_path}, digest: ${digest}`);
res.push({ ...codebase, digest });
}
+4
View File
@@ -28,6 +28,10 @@ export interface Codebase {
relative_path: string;
includes?: string[];
excludes?: string[];
assets?: {
from: string;
to: string;
}[];
}
export async function readConfigFile(): Promise<SyncOptions> {
+1 -1
View File
@@ -34,7 +34,7 @@ addEventListener("error", (event) => {
}
});
export const VERSION = "v1.373.0";
export const VERSION = "v1.374.0";
let command: any = new Command()
.name("wmill")
+34 -8
View File
@@ -164,7 +164,7 @@ export async function generateFlowLockInternal(
hashes = await generateFlowHash(folder);
for (const [path, hash] of Object.entries(hashes)) {
await updateMetadataLock(folder, hash, path);
await updateMetadataGlobalLock(folder, hash, path);
}
log.info(colors.green(`Flow ${remote_path} lockfiles updated`));
}
@@ -210,8 +210,15 @@ export async function generateScriptMetadataInternal(
// read script content
const scriptContent = await Deno.readTextFile(scriptPath);
const metadataContent = await Deno.readTextFile(metadataWithType.path);
let metadataContent = await Deno.readTextFile(metadataWithType.path);
const c = findCodebase(scriptPath, codebases);
if (c) {
metadataContent += c.digest ?? "";
}
let hash = await generateScriptHash(rawReqs, scriptContent, metadataContent);
if (await checkifMetadataUptodate(remotePath, hash, undefined)) {
if (!noStaleMessage) {
log.info(
@@ -242,7 +249,6 @@ export async function generateScriptMetadataInternal(
}
if (!opts.schemaOnly && !justUpdateMetadataLock) {
const c = findCodebase(scriptPath, codebases);
if (!c) {
await updateScriptLock(
workspace,
@@ -252,7 +258,9 @@ export async function generateScriptMetadataInternal(
metadataParsedContent,
rawReqs
);
metadataParsedContent.codebase = undefined;
} else {
metadataParsedContent.codebase = c.digest;
metadataParsedContent.lock = "";
}
} else {
@@ -266,8 +274,17 @@ export async function generateScriptMetadataInternal(
metaPath = remotePath + ".script.json";
newMetadataContent = JSON.stringify(metadataParsedContent);
}
hash = await generateScriptHash(rawReqs, scriptContent, metadataContent);
await updateMetadataLock(remotePath, hash);
let metadataContentUsedForHash = newMetadataContent;
if (c) {
metadataContentUsedForHash += c.digest ?? "";
}
hash = await generateScriptHash(
rawReqs,
scriptContent,
metadataContentUsedForHash
);
await updateMetadataGlobalLock(remotePath, hash);
if (!justUpdateMetadataLock) {
await Deno.writeTextFile(metaPath, newMetadataContent);
}
@@ -347,8 +364,17 @@ async function updateScriptLock(
);
}
const lockPath = remotePath + ".script.lock";
await Deno.writeTextFile(lockPath, lock);
metadataContent.lock = "!inline " + lockPath.replaceAll(SEP, "/");
if (lock != "") {
await Deno.writeTextFile(lockPath, lock);
metadataContent.lock = "!inline " + lockPath.replaceAll(SEP, "/");
} else {
try {
if (await Deno.stat(lockPath)) {
await Deno.remove(lockPath);
}
} catch {}
metadataContent.lock = "";
}
} catch (e) {
throw new Error(
`Failed to generate lockfile. Status was: ${rawResponse.statusText}, ${responseText}, ${e}`
@@ -821,7 +847,7 @@ export async function generateScriptHash(
);
}
export async function updateMetadataLock(
export async function updateMetadataGlobalLock(
path: string,
hash: string,
subpath?: string
+57 -5
View File
@@ -46,6 +46,8 @@ import {
readConfigFile,
} from "./conf.ts";
import { SyncCodebase, listSyncCodebases } from "./codebase.ts";
import fs from "node:fs";
import { Tarball } from "npm:@ayonli/jsext/archive";
export interface ScriptFile {
parent_hash?: string;
@@ -150,10 +152,11 @@ export async function handleFile(
const codebase =
language == "bun" ? findCodebase(path, codebases) : undefined;
let bundleContent: string | undefined = undefined;
let bundleContent: string | Tarball | undefined = undefined;
if (codebase) {
const esbuild = await import("npm:esbuild");
log.info(`Starting building the bundle for ${path}`);
const out = await esbuild.build({
entryPoints: [path],
@@ -165,6 +168,26 @@ export async function handleFile(
target: "node20.15.1",
});
bundleContent = out.outputFiles[0].text;
if (Array.isArray(codebase.assets) && codebase.assets.length > 0) {
const archiveNpm = await import("npm:@ayonli/jsext/archive");
log.info(
`Using the following asset configuration: ${JSON.stringify(
codebase.assets
)}`
);
const tarball = new archiveNpm.Tarball();
tarball.append(
new File([bundleContent], "main.js", { type: "text/plain" })
);
for (const asset of codebase.assets) {
const data = fs.readFileSync(asset.from);
const blob = new Blob([data], { type: "text/plain" });
const file = new File([blob], asset.to);
tarball.append(file);
}
bundleContent = tarball;
}
log.info(`Finished building the bundle for ${path}`);
}
const typed = (
@@ -189,7 +212,7 @@ export async function handleFile(
try {
remote = await ScriptService.getScriptByPath({
workspace: workspaceId,
path: remotePath.replaceAll(SEP, "/"),
path: remotePath,
});
log.debug(`Script ${remotePath} exists on remote`);
} catch {
@@ -268,7 +291,8 @@ export async function handleFile(
typed.priority == Boolean(remote.priority) &&
typed.timeout == remote.timeout &&
//@ts-ignore
typed.concurrency_key == remote["concurrency_key"])
typed.concurrency_key == remote["concurrency_key"] &&
typed.codebase == remote.codebase)
) {
log.info(colors.green(`Script ${remotePath} is up to date`));
return true;
@@ -299,8 +323,31 @@ export async function handleFile(
return false;
}
async function streamToBlob(stream: ReadableStream<Uint8Array>): Promise<Blob> {
// Create a reader from the stream
const reader = stream.getReader();
const chunks = [];
// Read the data from the stream
while (true) {
const { done, value } = await reader.read();
if (done) {
// If stream is finished, break the loop
break;
}
// Push the chunk to the array
chunks.push(value);
}
// Create a Blob from the chunks
const blob = new Blob(chunks);
return blob;
}
async function createScript(
bundleContent: string | undefined,
bundleContent: string | Tarball | undefined,
workspaceId: string,
body: NewScript,
workspace: Workspace
@@ -314,7 +361,12 @@ async function createScript(
} else {
const form = new FormData();
form.append("script", JSON.stringify(body));
form.append("file", bundleContent);
form.append(
"file",
typeof bundleContent == "string"
? bundleContent
: await streamToBlob(bundleContent.stream())
);
const url =
workspace.remote +
+9 -1
View File
@@ -65,6 +65,9 @@ export function findCodebase(
path: string,
codebases: SyncCodebase[]
): SyncCodebase | undefined {
if (!path.endsWith(".ts")) {
return;
}
for (const c of codebases) {
let included = false;
let excluded = false;
@@ -95,6 +98,7 @@ export function findCodebase(
}
}
}
async function addCodebaseDigestIfRelevant(
path: string,
content: string,
@@ -163,7 +167,9 @@ export async function FSFSElement(
async getContentText(): Promise<string> {
const content = await Deno.readTextFile(localP);
return await addCodebaseDigestIfRelevant(localP, content, codebases);
const r = await addCodebaseDigestIfRelevant(localP, content, codebases);
// console.log(r);
return r;
},
};
}
@@ -441,6 +447,8 @@ function ZipFSElement(
"!inline " +
removeSuffix(p.replaceAll(SEP, "/"), ".json") +
".lock";
} else if (parsed["lock"] == "") {
parsed["lock"] = "";
} else {
parsed["lock"] = undefined;
}
+3 -3
View File
@@ -93,17 +93,17 @@ export function getHeaders(): Record<string, string> | undefined {
}
}
export async function digestDir(path: string) {
export async function digestDir(path: string, conf: string) {
const hashes: string = [];
for await (const e of Deno.readDir(path)) {
const npath = path + "/" + e.name;
if (e.isFile) {
hashes.push(await generateHashFromBuffer(await Deno.readFile(npath)));
} else if (e.isDirectory && !e.isSymlink) {
hashes.push(await digestDir(npath));
hashes.push(await digestDir(npath, ""));
}
}
return await generateHash(hashes.join(""));
return await generateHash(hashes.join("") + conf);
}
export async function generateHash(content: string): Promise<string> {
+10
View File
@@ -0,0 +1,10 @@
FROM caddy:2.8.4-builder-alpine AS builder
RUN xcaddy build \
--with github.com/mholt/caddy-l4@145ec36251a44286f05a10d231d8bfb3a8192e09 \
--with github.com/RussellLuo/caddy-ext/layer4@ab1e18cfe426012af351a68463937ae2e934a2a1
FROM caddy:2.8.4-alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "windmill-components",
"version": "1.373.0",
"version": "1.374.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "windmill-components",
"version": "1.373.0",
"version": "1.374.0",
"license": "AGPL-3.0",
"dependencies": {
"@aws-crypto/sha256-js": "^4.0.0",
+9 -1
View File
@@ -1,6 +1,6 @@
{
"name": "windmill-components",
"version": "1.373.0",
"version": "1.374.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",
@@ -221,6 +221,11 @@
"svelte": "./package/components/FlowViewer.svelte",
"default": "./package/components/FlowViewer.svelte"
},
"./components/FlowStatusViewer.svelte": {
"types": "./package/components/FlowStatusViewer.svelte.d.ts",
"svelte": "./package/components/FlowStatusViewer.svelte",
"default": "./package/components/FlowStatusViewer.svelte"
},
"./components/FlowBuilder.svelte": {
"types": "./package/components/FlowBuilder.svelte.d.ts",
"svelte": "./package/components/FlowBuilder.svelte",
@@ -381,6 +386,9 @@
"components/FlowViewer.svelte": [
"./package/components/FlowViewer.svelte.d.ts"
],
"components/FlowStatusViewer.svelte": [
"./package/components/FlowStatusViewer.svelte.d.ts"
],
"components/FlowBuilder.svelte": [
"./package/components/FlowBuilder.svelte.d.ts"
],
@@ -6,6 +6,8 @@
import ResourceTypePicker from './ResourceTypePicker.svelte'
import Badge from './common/badge/Badge.svelte'
import Alert from './common/alert/Alert.svelte'
import EditableSchemaDrawer from './schema/EditableSchemaDrawer.svelte'
import type { SchemaProperty } from '$lib/common'
export let canEditResourceType: boolean = false
export let itemsType:
@@ -14,6 +16,7 @@
contentEncoding?: 'base64'
enum?: string[]
resourceType?: string
properties?: { [name: string]: SchemaProperty }
}
| undefined
@@ -23,6 +26,20 @@
: Array.isArray(itemsType?.enum)
? 'enum'
: 'string'
let schema = {
properties: itemsType?.properties || {},
order: Object.keys(itemsType?.properties || {}),
required: Object.values(itemsType?.properties || {}).map((p) => p.required)
}
function updateItemsType() {
itemsType = {
...itemsType,
properties: schema.properties,
type: 'object'
}
}
</script>
{#if canEditResourceType}
@@ -37,7 +54,7 @@
} else if (selected == 'number') {
itemsType = { type: 'number' }
} else if (selected == 'object') {
itemsType = { type: 'object' }
itemsType = { ...itemsType, type: 'object' }
} else if (selected == 'bytes') {
itemsType = { type: 'string', contentEncoding: 'base64' }
} else if (selected == 'resource') {
@@ -131,3 +148,12 @@
</div>
</label>
{/if}
{#if selected === 'object'}
<EditableSchemaDrawer
bind:schema
on:change={() => {
updateItemsType()
}}
/>
{/if}
@@ -1,5 +1,5 @@
<script lang="ts">
import { WorkspaceService, type WorkspaceDefaultScripts } from '$lib/gen'
import { WorkspaceService, type Script, type WorkspaceDefaultScripts } from '$lib/gen'
import { defaultScripts, workspaceStore } from '$lib/stores'
import { flip } from 'svelte/animate'
import Toggle from './Toggle.svelte'
@@ -8,12 +8,12 @@
$: langs = computeLangs($defaultScripts)
function computeLangs(defaultScripts: WorkspaceDefaultScripts | undefined) {
const allLangs = Object.keys(defaultScriptLanguages)
function computeLangs(defaultScripts: WorkspaceDefaultScripts | undefined): Script['language'][] {
const allLangs = Object.keys(defaultScriptLanguages) as Script['language'][]
if (!defaultScripts || defaultScripts.order == undefined) return allLangs
return defaultScripts.order
?.concat(allLangs.filter((l) => !defaultScripts.order?.includes(l)))
.filter((x) => x != 'nativets')
.filter((x) => x != 'nativets') as Script['language'][]
}
async function changePosition(i: number, up: boolean) {
@@ -62,7 +62,10 @@
on:change={(e) => {
let toggled = e.detail
if (toggled) {
defaultScripts.update((s) => ({ ...(s ?? {}), hidden: [...(s?.hidden ?? []), lang] }))
defaultScripts.update((s) => ({
...(s ?? {}),
hidden: [...(s?.hidden ?? []), lang]
}))
} else {
defaultScripts.update((s) => ({
...(s ?? {}),
@@ -471,6 +471,7 @@
} else {
schema.required = schema.required?.filter((x) => x !== argName)
}
dispatch('change', schema)
}}
on:schemaChange={(e) => {
schema = schema
+132 -104
View File
@@ -80,6 +80,7 @@
import { twMerge } from 'tailwind-merge'
import CustomPopover from './CustomPopover.svelte'
import Summary from './Summary.svelte'
import type { WhitelabelCustomUi } from './custom_ui'
export let initialPath: string = ''
export let pathStoreInit: string | undefined = undefined
@@ -95,6 +96,9 @@
})
| undefined = undefined
export let diffDrawer: DiffDrawer | undefined = undefined
export let customUi: WhitelabelCustomUi = {}
$: setContext('customUi', customUi)
const dispatch = createEventDispatcher()
@@ -1010,26 +1014,40 @@
}
}
const moreItems: {
let moreItems: {
displayName: string
icon: ComponentType<Icon>
action: () => void
disabled?: boolean
}[] = [
{
displayName: 'Deployment History',
icon: HistoryIcon,
action: () => {
flowHistory?.open()
},
disabled: newFlow
},
{
displayName: 'Export',
icon: FileJson,
action: () => jsonViewerDrawer?.openDrawer()
}
]
}[] = []
$: onCustomUiChange(customUi)
function onCustomUiChange(customUi: WhitelabelCustomUi | undefined) {
moreItems = [
...(customUi?.topBar?.history != false
? [
{
displayName: 'Deployment History',
icon: HistoryIcon,
action: () => {
flowHistory?.open()
},
disabled: newFlow
}
]
: []),
...(customUi?.topBar?.history != false
? [
{
displayName: 'Export',
icon: FileJson,
action: () => jsonViewerDrawer?.openDrawer()
}
]
: [])
]
}
let deploymentMsg = ''
let msgInput: HTMLInputElement | undefined = undefined
@@ -1117,104 +1135,112 @@
{$scheduleStore.cron ?? ''}
</Button>
{/if}
<div class="flex justify-start w-full">
<div>
<button
on:click={async () => {
select('settings-metadata')
document.getElementById('path')?.focus()
}}
>
<Badge
color="gray"
class="center-center !bg-gray-300 !text-tertiary dark:!bg-gray-700 dark:!text-gray-300 !h-[28px] !w-[70px] rounded-r-none"
{#if customUi?.topBar?.path != false}
<div class="flex justify-start w-full">
<div>
<button
on:click={async () => {
select('settings-metadata')
document.getElementById('path')?.focus()
}}
>
<Pen size={12} class="mr-2" /> Path
</Badge>
</button>
<Badge
color="gray"
class="center-center !bg-gray-300 !text-tertiary dark:!bg-gray-700 dark:!text-gray-300 !h-[28px] !w-[70px] rounded-r-none"
>
<Pen size={12} class="mr-2" /> Path
</Badge>
</button>
</div>
<input
type="text"
readonly
value={$pathStore && $pathStore != '' ? $pathStore : 'Choose a path'}
class="font-mono !text-xs !min-w-[96px] !max-w-[300px] !w-full !h-[28px] !my-0 !py-0 !border-l-0 !rounded-l-none"
on:focus={({ currentTarget }) => {
currentTarget.select()
}}
/>
</div>
<input
type="text"
readonly
value={$pathStore && $pathStore != '' ? $pathStore : 'Choose a path'}
class="font-mono !text-xs !min-w-[96px] !max-w-[300px] !w-full !h-[28px] !my-0 !py-0 !border-l-0 !rounded-l-none"
on:focus={({ currentTarget }) => {
currentTarget.select()
}}
/>
</div>
{/if}
</div>
<div class="flex flex-row gap-2 items-center">
{#if $enterpriseLicense && !newFlow}
<Awareness />
{/if}
<div>
<ButtonDropdown hasPadding={false}>
<svelte:fragment slot="buttonReplacement">
<Button nonCaptureEvent size="xs" color="light">
<div class="flex flex-row items-center">
<MoreVertical size={14} />
</div>
</Button>
</svelte:fragment>
<svelte:fragment slot="items">
{#each moreItems as item}
<MenuItem
on:click={item.action}
disabled={item.disabled}
class={item.disabled ? 'opacity-50' : ''}
>
<div
class={twMerge(
'text-primary flex flex-row items-center text-left px-4 py-2 gap-2 cursor-pointer hover:bg-surface-hover !text-xs font-semibold'
)}
>
<svelte:component this={item.icon} size={14} />
{item.displayName}
{#if moreItems?.length > 0}
<ButtonDropdown hasPadding={false}>
<svelte:fragment slot="buttonReplacement">
<Button nonCaptureEvent size="xs" color="light">
<div class="flex flex-row items-center">
<MoreVertical size={14} />
</div>
</MenuItem>
{/each}
</svelte:fragment>
</ButtonDropdown>
</Button>
</svelte:fragment>
<svelte:fragment slot="items">
{#each moreItems as item}
<MenuItem
on:click={item.action}
disabled={item.disabled}
class={item.disabled ? 'opacity-50' : ''}
>
<div
class={twMerge(
'text-primary flex flex-row items-center text-left px-4 py-2 gap-2 cursor-pointer hover:bg-surface-hover !text-xs font-semibold'
)}
>
<svelte:component this={item.icon} size={14} />
{item.displayName}
</div>
</MenuItem>
{/each}
</svelte:fragment>
</ButtonDropdown>
{/if}
</div>
<FlowBuilderTutorials
on:reload={() => {
renderCount += 1
}}
/>
<Button
color="light"
variant="border"
size="xs"
on:click={() => {
if (!savedFlow) {
return
}
diffDrawer?.openDrawer()
diffDrawer?.setDiff({
mode: 'normal',
deployed: savedFlow,
draft: savedFlow['draft'],
current: { ...$flowStore, path: $pathStore }
})
}}
disabled={!savedFlow}
>
<div class="flex flex-row gap-2 items-center">
<DiffIcon size={14} />
Diff
</div>
</Button>
<FlowCopilotStatus
{copilotLoading}
bind:copilotStatus
{genFlow}
{finishCopilotFlowBuilder}
{abortController}
/>
{#if customUi?.topBar?.tutorials != false}
<FlowBuilderTutorials
on:reload={() => {
renderCount += 1
}}
/>
{/if}
{#if customUi?.topBar?.diff != false}
<Button
color="light"
variant="border"
size="xs"
on:click={() => {
if (!savedFlow) {
return
}
diffDrawer?.openDrawer()
diffDrawer?.setDiff({
mode: 'normal',
deployed: savedFlow,
draft: savedFlow['draft'],
current: { ...$flowStore, path: $pathStore }
})
}}
disabled={!savedFlow}
>
<div class="flex flex-row gap-2 items-center">
<DiffIcon size={14} />
Diff
</div>
</Button>
{/if}
{#if customUi?.topBar?.aiBuilder != false}
<FlowCopilotStatus
{copilotLoading}
bind:copilotStatus
{genFlow}
{finishCopilotFlowBuilder}
{abortController}
/>
{/if}
<FlowPreviewButtons />
<Button
loading={loadingDraft}
@@ -1270,6 +1296,8 @@
<!-- metadata -->
{#if $flowStateStore}
<FlowEditor
enableAi={customUi?.stepInputs?.ai != false}
disableSettings={customUi?.settingsPanel === false}
{loading}
on:reload={() => {
renderCount += 1
@@ -1,6 +1,4 @@
<script lang="ts">
import { FlowGraph } from './graph'
import type { FlowModule, FlowValue } from '$lib/gen'
import { createEventDispatcher } from 'svelte'
@@ -73,7 +73,7 @@
on:close
>
<aside
class="drawer {$$props.class ?? ''} {$$props.positionClass ?? ''}"
class="drawer windmill-drawer {$$props.class ?? ''} {$$props.positionClass ?? ''}"
class:open
class:close={!open && timeout}
style={`${style}; --zIndex: ${zIndex};`}
+21
View File
@@ -0,0 +1,21 @@
import type { SupportedLanguage } from '$lib/common'
export type WhitelabelCustomUi = {
topBar?: {
path?: boolean
export?: boolean
history?: boolean
aiBuilder?: boolean
tutorials?: boolean
diff?: boolean
}
settingsPanel?: boolean
triggers?: boolean
flowNode?: boolean
hub?: boolean
graph?: { aiBuilder?: boolean; dataflow?: boolean }
stepInputs?: { ai?: boolean }
stepAdvancedSettings?: boolean
languages?: (SupportedLanguage | 'docker' | 'bunnative')[]
scriptFork?: boolean
}
@@ -12,6 +12,12 @@
const { flowStore } = getContext<FlowEditorContext>('FlowEditorContext')
export let loading: boolean
export let disableStaticInputs = false
export let disableTutorials = false
export let disableAi = false
export let disableSettings = false
export let smallErrorHandler = false
export let enableAi = true
let size = 40
@@ -35,7 +41,15 @@
{/each}
</div>
{:else if $flowStore.value.modules}
<FlowModuleSchemaMap bind:modules={$flowStore.value.modules} on:reload />
<FlowModuleSchemaMap
{disableStaticInputs}
{disableTutorials}
{disableAi}
{disableSettings}
{smallErrorHandler}
bind:modules={$flowStore.value.modules}
on:reload
/>
{/if}
</div>
</Pane>
@@ -47,7 +61,7 @@
</div>
</div>
{:else}
<FlowEditorPanel enableAi />
<FlowEditorPanel {enableAi} />
{/if}
</Pane>
</Splitpanes>
@@ -57,9 +57,8 @@
</PropPickerWrapper>
{:else}
<div class="flex justify-between gap-4 p-2">
<div><pre class="text-sm">{branch.expr}</pre></div><div
class="flex flex-row gap-2 items-center"
>
<div class="truncate"><pre class="text-sm truncate">{branch.expr}</pre></div>
<div class="flex flex-row gap-2 items-center">
{#if enableAi}
<PredicateGen
on:setExpr={(e) => {
@@ -3,7 +3,7 @@
import ToggleHubWorkspace from '$lib/components/ToggleHubWorkspace.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, getContext } from 'svelte'
import FlowScriptPicker from '../pickers/FlowScriptPicker.svelte'
import PickHubScript from '../pickers/PickHubScript.svelte'
import WorkspaceScriptPicker from '../pickers/WorkspaceScriptPicker.svelte'
@@ -17,6 +17,7 @@
import { defaultScriptLanguages, processLangs } from '$lib/scripts'
import type { SupportedLanguage } from '$lib/common'
import DefaultScripts from '$lib/components/DefaultScripts.svelte'
import type { WhitelabelCustomUi } from '$lib/components/custom_ui'
export let failureModule: boolean
export let shouldDisableTriggerScripts: boolean = false
@@ -53,6 +54,8 @@
}
return kind == 'script' && !failureModule
}
let customUi: undefined | WhitelabelCustomUi = getContext('customUi')
</script>
<div class="p-4 h-full flex flex-col" id="flow-editor-flow-inputs">
@@ -193,7 +196,7 @@
<div class="pb-2" />
{/if}
<div class="flex flex-row flex-wrap gap-2" id="flow-editor-action-script">
{#each langs as [label, lang] (lang)}
{#each langs.filter((lang) => customUi?.languages == undefined || customUi?.languages?.includes(lang?.[1])) as [label, lang] (lang)}
{#if displayLang(lang, kind)}
<FlowScriptPicker
id={`flow-editor-action-script-${lang}`}
@@ -19,12 +19,14 @@
import { sendUserToast } from '$lib/utils'
import { workerTags } from '$lib/stores'
import { getLatestHashForScript } from '$lib/scripts'
import type { WhitelabelCustomUi } from '$lib/components/custom_ui'
export let module: FlowModule
const { scriptEditorDrawer, flowStore, selectedId } =
getContext<FlowEditorContext>('FlowEditorContext')
const dispatch = createEventDispatcher()
let customUi: undefined | WhitelabelCustomUi = getContext('customUi')
loadWorkerGroups()
@@ -132,15 +134,17 @@
Edit {#if module.value.hash != undefined} (locked hash){/if}
</Button>
{/if}
<Button
size="xs"
color="light"
on:click={() => dispatch('fork')}
startIcon={{ icon: GitFork }}
iconOnly={false}
>
Fork
</Button>
{#if customUi?.scriptFork != false}
<Button
size="xs"
color="light"
on:click={() => dispatch('fork')}
startIcon={{ icon: GitFork }}
iconOnly={false}
>
Fork
</Button>
{/if}
{/if}
<div class="px-0.5" />
{#if module.value.type === 'rawscript'}
@@ -35,6 +35,8 @@
export let disableStaticInputs = false
export let disableTutorials = false
export let disableAi = false
export let disableSettings = false
export let smallErrorHandler = false
let flowTutorials: FlowTutorials | undefined = undefined
@@ -240,7 +242,9 @@
{#if $copilotCurrentStepStore !== undefined}
<div transition:fade class="absolute inset-0 bg-gray-500 bg-opacity-75 z-[900] !m-0" />
{/if}
<FlowSettingsItem />
{#if !disableSettings}
<FlowSettingsItem />
{/if}
{#if !disableStaticInputs}
<FlowConstantsItem />
{/if}
@@ -1,10 +1,11 @@
<script lang="ts">
import { Menu } from '$lib/components/common'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, getContext } from 'svelte'
import { CheckCircle2, Code, Cross, GitBranch, Repeat, Square, Zap } from 'lucide-svelte'
import StepGen from '$lib/components/copilot/StepGen.svelte'
import type { FlowModule } from '$lib/gen'
import BarsStaggered from '$lib/components/icons/BarsStaggered.svelte'
import type { WhitelabelCustomUi } from '$lib/components/custom_ui'
const dispatch = createEventDispatcher()
export let trigger = false
@@ -16,6 +17,7 @@
export let disableAi = false
$: !open && (funcDesc = '')
let customUi: undefined | WhitelabelCustomUi = getContext('customUi')
</script>
<Menu
@@ -52,7 +54,7 @@
<Code size={14} />
Action
</button>
{#if trigger}
{#if customUi?.triggers != false && trigger}
<button
class="w-full text-left py-2 px-3 hover:bg-surface-hover whitespace-nowrap flex flex-row gap-2 items-center"
on:pointerdown={() => {
@@ -128,17 +130,19 @@
Branch to all
</button>
<button
class="w-full text-left py-2 px-3 hover:bg-surface-hover rounded-none whitespace-nowrap flex flex-row gap-2 items-center"
on:pointerdown={() => {
close()
dispatch('new', 'flow')
}}
role="menuitem"
>
<BarsStaggered size={14} />
Flow
</button>
{#if customUi?.flowNode != false}
<button
class="w-full text-left py-2 px-3 hover:bg-surface-hover rounded-none whitespace-nowrap flex flex-row gap-2 items-center"
on:pointerdown={() => {
close()
dispatch('new', 'flow')
}}
role="menuitem"
>
<BarsStaggered size={14} />
Flow
</button>
{/if}
{#if stop}
<button
class="w-full text-left py-2 px-3 hover:bg-surface-hover inline-flex gap-2.5"
@@ -71,6 +71,7 @@
!$selectedId.startsWith('settings') &&
$selectedId !== 'failure' &&
$selectedId !== 'Result'
let dataflow = false
let dispatch = createEventDispatcher()
@@ -13,6 +13,7 @@
type Node,
type Edge,
ConnectionLineType
// @ts-ignore
} from '@xyflow/svelte'
// @ts-ignore
import dagre from '@dagrejs/dagre'
@@ -1,4 +1,5 @@
<script lang="ts">
// @ts-ignore
import { getBezierPath, BaseEdge, type EdgeProps } from '@xyflow/svelte'
type $$Props = EdgeProps
@@ -1,18 +1,18 @@
<script lang="ts">
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
export let data: $$Props['data']
$$restProps
export let data: {
label: string
}
</script>
{#if data.time}
<NodeToolbar isVisible position={Position.Top} align="end">
<NodeToolbar isVisible position={Position.Top}>
<div style="width:300px;" class="flex flex-row">
<span class="text-xs">0.01s</span>
</NodeToolbar>
{/if}
</div>
</NodeToolbar>
<VirtualItem
label={data.label}
@@ -1,5 +1,6 @@
<script lang="ts">
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
@@ -1,6 +1,7 @@
<script lang="ts">
import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
@@ -1,10 +1,10 @@
<script lang="ts">
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
import { Wand2 } from 'lucide-svelte'
type $$Props = NodeProps
export let data: $$Props['data']
</script>
<NodeToolbar isVisible position={Position.Top}>
@@ -1,13 +1,12 @@
<script lang="ts">
import MapItem from '$lib/components/flows/map/MapItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
export let data: $$Props['data']
export let id: $$Props['id']
$$restProps
</script>
{#if data.time}
@@ -1,11 +1,11 @@
<script lang="ts">
import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
$$restProps
let darkMode: boolean = false
</script>
@@ -1,5 +1,6 @@
<script lang="ts">
import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
// @ts-ignore
import { Handle, NodeToolbar, Position, type NodeProps } from '@xyflow/svelte'
type $$Props = NodeProps
@@ -691,10 +691,12 @@
</div>
</h1>
{#if job?.['deleted']}
<Alert type="error" title="Deleted">
The content of this run was deleted (by an admin, no less)
</Alert>
<div class="my-2" />
<div class="max-w-7xl mx-auto w-full px-4">
<Alert type="error" title="Deleted">
The content of this run was deleted (by an admin, no less)
</Alert>
</div>
<div class="my-4" />
{/if}
<!-- Arguments and actions -->
+2 -2
View File
@@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi"
[packages]
wmill = ">=1.373.0"
wmill_pg = ">=1.373.0"
wmill = ">=1.374.0"
wmill_pg = ">=1.374.0"
sendgrid = "*"
mysql-connector-python = "*"
pymongo = "*"
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.373.0
version: 1.374.0
title: OpenFlow Spec
contact:
name: Ruben Fiszel
@@ -12,7 +12,7 @@
RootModule = 'WindmillClient.psm1'
# Version number of this module.
ModuleVersion = '1.373.0'
ModuleVersion = '1.374.0'
# Supported PSEditions
# CompatiblePSEditions = @()
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill"
version = "1.373.0"
version = "1.374.0"
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.373.0"
version = "1.374.0"
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.373.0",
"version": "1.374.0",
"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.373.0",
"version": "1.374.0",
"author": "Ruben Fiszel",
"license": "Apache 2.0",
"devDependencies": {
+1 -1
View File
@@ -1 +1 @@
1.373.0
1.374.0