mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-03 16:03:20 +00:00
downgrade images
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
name: Backend check
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "backend/**"
|
||||
- ".github/workflows/backend-check.yml"
|
||||
|
||||
jobs:
|
||||
check_oss:
|
||||
runs-on: ubicloud-standard-8
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.82.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: backend
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
run: SQLX_OFFLINE=true cargo check
|
||||
|
||||
check_oss_full:
|
||||
runs-on: ubicloud-standard-8
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
- name: install xmlsec1
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxml2-dev libxmlsec1-dev
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.82.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: backend
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
run: SQLX_OFFLINE=true cargo check --all-features
|
||||
|
||||
check_ee:
|
||||
runs-on: ubicloud-standard-8
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Read EE repo commit hash
|
||||
run: |
|
||||
echo "ee_repo_ref=$(cat ./backend/ee-repo-ref.txt)" >> "$GITHUB_ENV"
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: windmill-labs/windmill-ee-private
|
||||
path: ./windmill-ee-private
|
||||
ref: ${{ env.ee_repo_ref }}
|
||||
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
- name: Substitute EE code (EE logic is behind feature flag)
|
||||
run: |
|
||||
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
|
||||
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.82.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: backend
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
run: SQLX_OFFLINE=true cargo check
|
||||
|
||||
check_ee_full:
|
||||
runs-on: ubicloud-standard-8
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Read EE repo commit hash
|
||||
run: |
|
||||
echo "ee_repo_ref=$(cat ./backend/ee-repo-ref.txt)" >> "$GITHUB_ENV"
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: windmill-labs/windmill-ee-private
|
||||
path: ./windmill-ee-private
|
||||
ref: ${{ env.ee_repo_ref }}
|
||||
token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: install xmlsec1
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxml2-dev libxmlsec1-dev
|
||||
|
||||
- name: Substitute EE code (EE logic is behind feature flag)
|
||||
run: |
|
||||
./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.82.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: backend
|
||||
- name: cargo check
|
||||
timeout-minutes: 16
|
||||
working-directory: ./backend
|
||||
run: SQLX_OFFLINE=true cargo check --all-features
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ permissions: write-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubicloud-standard-30
|
||||
runs-on: ubicloud-standard-8
|
||||
if: (github.event_name != 'workflow_dispatch') || (inputs.ee == false)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
cache-to: type=gha
|
||||
|
||||
build_arm:
|
||||
runs-on: ubicloud-standard-30-arm
|
||||
runs-on: ubicloud-standard-8-arm
|
||||
if: (github.event_name != 'workflow_dispatch') || (inputs.ee == false)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# Changelog
|
||||
|
||||
## [1.440.1](https://github.com/windmill-labs/windmill/compare/v1.440.0...v1.440.1) (2024-12-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **internal:** updating rust to 1.82 ([02a8f1f](https://github.com/windmill-labs/windmill/commit/02a8f1f86453a5f8769364ba3798998b8830d086))
|
||||
|
||||
## [1.440.0](https://github.com/windmill-labs/windmill/compare/v1.439.0...v1.440.0) (2024-12-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cache:** remove persistent raw values from queue ([#4866](https://github.com/windmill-labs/windmill/issues/4866)) ([977ac5c](https://github.com/windmill-labs/windmill/commit/977ac5c3f3c2e8224f4915e483ae60f28ce008fc))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add workspace selector and fix css for create webhook page ([#4939](https://github.com/windmill-labs/windmill/issues/4939)) ([d880655](https://github.com/windmill-labs/windmill/commit/d8806555f1d78a5fae7ae77acbcdad402e89951d))
|
||||
* fix relative imports in cached flow scripts ([13be0cd](https://github.com/windmill-labs/windmill/commit/13be0cd1c822d7a809dc96914dd1286510b9f9eb))
|
||||
|
||||
## [1.439.0](https://github.com/windmill-labs/windmill/compare/v1.438.0...v1.439.0) (2024-12-15)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
ARG DEBIAN_IMAGE=debian:bookworm-slim
|
||||
ARG RUST_IMAGE=rust:1.80-slim-bookworm
|
||||
ARG RUST_IMAGE=rust:1.82-slim-bookworm
|
||||
ARG PYTHON_IMAGE=python:3.11.10-slim-bookworm
|
||||
|
||||
FROM ${RUST_IMAGE} AS rust_base
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT value AS \"value!: Json<Box<RawValue>>\"\n FROM flow_version WHERE id = $1 LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "value!: Json<Box<RawValue>>",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "7a9a711c7cb05ed8a61116586fb68ef270567ebd70266f07139f3e3e34940699"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT value AS \"value!: Json<Box<RawValue>>\"\n FROM flow_version_lite WHERE id = $1 LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "value!: Json<Box<RawValue>>",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "c7de95ef4934752b62d6d01bf663ab6a104bbcfb827a4a9e4e03e38732375d55"
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT lock AS \"lock: String\", content AS \"code!: String\",\n language AS \"language: Option<ScriptLang>\", envs AS \"envs: Vec<String>\", codebase AS \"codebase: String\" FROM script WHERE hash = $1 LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "lock: String",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "code!: String",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "language: Option<ScriptLang>",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "script_lang",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"python3",
|
||||
"deno",
|
||||
"go",
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
"snowflake",
|
||||
"graphql",
|
||||
"powershell",
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust",
|
||||
"ansible",
|
||||
"csharp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "envs: Vec<String>",
|
||||
"type_info": "VarcharArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "codebase: String",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "d061e7ca73987036928e17245360fd7f2969aab0c422a00bbdade6a7236aa75d"
|
||||
}
|
||||
Generated
+91
-91
@@ -537,7 +537,7 @@ dependencies = [
|
||||
"hex",
|
||||
"hmac",
|
||||
"http-types",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"hyper-tls 0.5.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -771,9 +771,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-async"
|
||||
version = "1.2.1"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c"
|
||||
checksum = "8aa8ff1492fd9fb99ae28e8467af0dbbb7c31512b16fabf1a0f10d7bb6ef78bb"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"pin-project-lite",
|
||||
@@ -830,9 +830,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-runtime"
|
||||
version = "1.7.4"
|
||||
version = "1.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f20685047ca9d6f17b994a07f629c813f08b5bce65523e47124879e60103d45"
|
||||
checksum = "431a10d0e07e09091284ef04453dae4069283aa108d209974d67e77ae1caa658"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http",
|
||||
@@ -845,7 +845,7 @@ dependencies = [
|
||||
"http-body 0.4.6",
|
||||
"http-body 1.0.1",
|
||||
"httparse",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"hyper-rustls 0.24.2",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
@@ -874,9 +874,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-types"
|
||||
version = "1.2.9"
|
||||
version = "1.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510"
|
||||
checksum = "8ecbf4d5dfb169812e2b240a4350f15ad3c6b03a54074e5712818801615f2dc5"
|
||||
dependencies = [
|
||||
"base64-simd 0.8.0",
|
||||
"bytes",
|
||||
@@ -934,7 +934,7 @@ dependencies = [
|
||||
"http 1.2.0",
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"itoa",
|
||||
"matchit",
|
||||
@@ -997,7 +997,7 @@ dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.8.0",
|
||||
"miniz_oxide 0.8.2",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
@@ -1272,7 +1272,7 @@ dependencies = [
|
||||
"hex",
|
||||
"http 1.2.0",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-named-pipe",
|
||||
"hyper-util",
|
||||
"hyperlocal",
|
||||
@@ -1283,7 +1283,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serde_urlencoded",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.8",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-service",
|
||||
@@ -1736,15 +1736,15 @@ checksum = "510ca239cf13b7f8d16a2b48f263de7b4f8c566f0af58d901031473c76afb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.8"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||
checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"unicode-width 0.1.14",
|
||||
"windows-sys 0.52.0",
|
||||
"once_cell",
|
||||
"unicode-width 0.2.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2593,8 +2593,8 @@ dependencies = [
|
||||
"hickory-resolver",
|
||||
"http 1.2.0",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper-rustls 0.27.3",
|
||||
"hyper 1.5.2",
|
||||
"hyper-rustls 0.27.4",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"percent-encoding",
|
||||
@@ -3114,9 +3114,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
@@ -3297,7 +3297,7 @@ checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"libz-sys",
|
||||
"miniz_oxide 0.8.0",
|
||||
"miniz_oxide 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3583,7 +3583,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.21.7",
|
||||
"dirs-next",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"hyper-rustls 0.24.2",
|
||||
"ring 0.16.20",
|
||||
"rustls 0.21.12",
|
||||
@@ -4068,11 +4068,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.9"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
|
||||
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4203,9 +4203,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.31"
|
||||
version = "0.14.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85"
|
||||
checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@@ -4227,9 +4227,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.5.1"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
|
||||
checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@@ -4253,7 +4253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
@@ -4269,7 +4269,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"log",
|
||||
"rustls 0.21.12",
|
||||
"rustls-native-certs 0.6.3",
|
||||
@@ -4279,13 +4279,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.3"
|
||||
version = "0.27.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
|
||||
checksum = "f6884a48c6826ec44f524c7456b163cebe9e55a18d7b5e307cb4f100371cc767"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"rustls 0.23.20",
|
||||
"rustls-native-certs 0.8.1",
|
||||
@@ -4302,7 +4302,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
|
||||
dependencies = [
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
@@ -4316,7 +4316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
@@ -4330,7 +4330,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
@@ -4349,7 +4349,7 @@ dependencies = [
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
"http-body 1.0.1",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio",
|
||||
@@ -4366,7 +4366,7 @@ checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-util",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
@@ -5241,9 +5241,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
@@ -5623,7 +5623,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
"humantime",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"itertools 0.13.0",
|
||||
"md-5 0.10.6",
|
||||
"parking_lot",
|
||||
@@ -6609,7 +6609,7 @@ dependencies = [
|
||||
"rustc-hash 2.1.0",
|
||||
"rustls 0.23.20",
|
||||
"socket2",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.8",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
@@ -6628,7 +6628,7 @@ dependencies = [
|
||||
"rustls 0.23.20",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.8",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
"web-time",
|
||||
@@ -6636,9 +6636,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527"
|
||||
checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -6940,7 +6940,7 @@ dependencies = [
|
||||
"h2 0.3.26",
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.31",
|
||||
"hyper 0.14.32",
|
||||
"hyper-tls 0.5.0",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
@@ -6984,8 +6984,8 @@ dependencies = [
|
||||
"http 1.2.0",
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper-rustls 0.27.3",
|
||||
"hyper 1.5.2",
|
||||
"hyper-rustls 0.27.4",
|
||||
"hyper-tls 0.6.0",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
@@ -7310,7 +7310,7 @@ dependencies = [
|
||||
"openssl-probe",
|
||||
"rustls-pki-types",
|
||||
"schannel",
|
||||
"security-framework 3.0.1",
|
||||
"security-framework 3.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7592,9 +7592,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.0.1"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8"
|
||||
checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation 0.10.0",
|
||||
@@ -7605,9 +7605,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.12.1"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2"
|
||||
checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -9195,11 +9195,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.7"
|
||||
version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767"
|
||||
checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.7",
|
||||
"thiserror-impl 2.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9215,9 +9215,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.7"
|
||||
version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36"
|
||||
checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -9655,7 +9655,7 @@ dependencies = [
|
||||
"http 1.2.0",
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"hyper-timeout",
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
@@ -10143,9 +10143,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.17"
|
||||
version = "0.3.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
|
||||
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id"
|
||||
@@ -10666,7 +10666,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -10707,7 +10707,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -10735,7 +10735,7 @@ dependencies = [
|
||||
"hf-hub",
|
||||
"hmac",
|
||||
"http 1.2.0",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"itertools 0.13.0",
|
||||
"jsonwebtoken",
|
||||
"lazy_static",
|
||||
@@ -10792,7 +10792,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
@@ -10810,7 +10810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
@@ -10823,7 +10823,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-autoscaling"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -10837,7 +10837,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@@ -10857,7 +10857,7 @@ dependencies = [
|
||||
"git-version",
|
||||
"hex",
|
||||
"hmac",
|
||||
"hyper 1.5.1",
|
||||
"hyper 1.5.2",
|
||||
"indexmap 2.7.0",
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
@@ -10880,7 +10880,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.8",
|
||||
"tikv-jemalloc-ctl",
|
||||
"tokio",
|
||||
"tonic",
|
||||
@@ -10895,7 +10895,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-git-sync"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
@@ -10909,7 +10909,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-indexer"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -10932,7 +10932,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-macros"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"itertools 0.13.0",
|
||||
"lazy_static",
|
||||
@@ -10944,7 +10944,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"serde",
|
||||
@@ -10953,7 +10953,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10965,7 +10965,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-csharp"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -10977,7 +10977,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -10989,7 +10989,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -11001,7 +11001,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.13.0",
|
||||
@@ -11012,7 +11012,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.13.0",
|
||||
@@ -11023,7 +11023,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -11041,7 +11041,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-rust"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -11058,7 +11058,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -11070,7 +11070,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -11088,7 +11088,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.15",
|
||||
@@ -11110,7 +11110,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-yaml"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -11120,7 +11120,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -11154,7 +11154,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-sql-datatype-parser-wasm"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
@@ -11164,7 +11164,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -30,7 +30,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -3848,6 +3848,7 @@ mod job_payload {
|
||||
concurrency_time_window_s: None,
|
||||
cache_ttl: None,
|
||||
dedicated_worker: None,
|
||||
path: "f/system/hello/test-0".into(),
|
||||
})
|
||||
.arg("world", json!("foo"))
|
||||
.run_until_complete(&db, port)
|
||||
@@ -3867,6 +3868,7 @@ mod job_payload {
|
||||
concurrency_time_window_s: None,
|
||||
cache_ttl: None,
|
||||
dedicated_worker: None,
|
||||
path: "f/system/hello/test-0".into(),
|
||||
})
|
||||
.arg("hello", json!("You know nothing Jean Neige"))
|
||||
.run_until_complete(&db, port)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.439.0
|
||||
version: 1.440.1
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
|
||||
@@ -1324,7 +1324,7 @@ async fn execute_component(
|
||||
let cache = cache::anon!({ u64 => Arc<Policy> } in "policy" <= 1000);
|
||||
arc_policy = policy_fut
|
||||
.map_ok(sqlx::types::Json) // cache as json.
|
||||
.cached(cache, &(id as u64), |sqlx::types::Json(x)| Arc::new(x))
|
||||
.cached(cache, id as u64, |sqlx::types::Json(x)| Arc::new(x))
|
||||
.await?;
|
||||
&*arc_policy
|
||||
} else {
|
||||
@@ -1353,7 +1353,7 @@ async fn execute_component(
|
||||
.fetch_one(&db)
|
||||
.map_err(Into::<Error>::into)
|
||||
.map_ok(sqlx::types::Json) // cache as json.
|
||||
.cached(cache, &(*id as u64), |sqlx::types::Json(x)| Arc::new(x))
|
||||
.cached(cache, *id as u64, |sqlx::types::Json(x)| Arc::new(x))
|
||||
.await?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
||||
@@ -7,11 +7,10 @@ use crate::scripts::ScriptLang;
|
||||
|
||||
use std::future::Future;
|
||||
use std::hash::Hash;
|
||||
use std::panic::Location;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::future::TryFutureExt;
|
||||
use quick_cache::Equivalent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::types::{Json, JsonRawValue as RawValue};
|
||||
use sqlx::PgExecutor;
|
||||
@@ -48,19 +47,23 @@ impl<Key: Eq + Hash + fs::Item, Val: Clone> FsBackedCache<Key, Val> {
|
||||
}
|
||||
|
||||
/// Gets or inserts an item in the cache with key `key`.
|
||||
pub async fn get_or_insert_async<'a, T: fs::Bundle, Q, F>(
|
||||
pub async fn get_or_insert_async<'a, T: fs::Bundle, F>(
|
||||
&'a self,
|
||||
key: &Q,
|
||||
key: Key,
|
||||
map: impl Fn(T) -> Val,
|
||||
with: F,
|
||||
) -> error::Result<Val>
|
||||
where
|
||||
Q: Hash + Equivalent<Key> + ToOwned<Owned = Key>,
|
||||
Key: Clone,
|
||||
F: Future<Output = error::Result<T>>,
|
||||
{
|
||||
if cfg!(test) {
|
||||
// Disable caching in tests: since `#[sqlx::test]` spawn a database per test, the cache
|
||||
// could yield unexpected results.
|
||||
return with.await.map(map);
|
||||
}
|
||||
self.cache
|
||||
.get_or_insert_async(key, async {
|
||||
let key = key.to_owned();
|
||||
.get_or_insert_async(&key, async {
|
||||
fs::import_or_insert_with(self.path(&key), with)
|
||||
.await
|
||||
.map(map)
|
||||
@@ -138,22 +141,22 @@ pub mod future {
|
||||
/// #[allow(unused)]
|
||||
/// async {
|
||||
/// let result = std::future::ready(Ok(Json(42)))
|
||||
/// .cached(cache::anon!({ u64 => Json<u64> } in "test" <= 1), &42, |x| x)
|
||||
/// .cached(cache::anon!({ u64 => Json<u64> } in "test" <= 1), 42, |x| x)
|
||||
/// .await;
|
||||
///
|
||||
/// assert_eq!(result.unwrap(), Json(42));
|
||||
/// };
|
||||
/// ```
|
||||
fn cached<Key: Eq + Hash + fs::Item, Val: Clone, Q>(
|
||||
fn cached<Key: Eq + Hash + fs::Item, Val: Clone>(
|
||||
self,
|
||||
cache: &FsBackedCache<Key, Val>,
|
||||
key: &Q,
|
||||
key: Key,
|
||||
map: impl Fn(T) -> Val,
|
||||
) -> impl Future<Output = error::Result<Val>>
|
||||
where
|
||||
Q: Hash + Equivalent<Key> + ToOwned<Owned = Key>,
|
||||
Key: Clone,
|
||||
{
|
||||
cache.get_or_insert_async(key, map, self)
|
||||
cache.get_or_insert_async(key.to_owned(), map, self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +224,17 @@ pub struct ScriptMetadata {
|
||||
pub codebase: Option<String>,
|
||||
}
|
||||
|
||||
fn unwrap_or_error<Key: std::fmt::Debug, Val>(
|
||||
at: &'static Location,
|
||||
entity: &'static str,
|
||||
key: Key,
|
||||
) -> impl FnOnce(Option<Val>) -> error::Result<Val> {
|
||||
move |optional| {
|
||||
optional
|
||||
.ok_or_else(|| error::Error::InternalErrAt(at, format!("{key:?}: {entity} not found")))
|
||||
}
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
impl fs::Bundle for FlowData {
|
||||
type Item = &'static str;
|
||||
@@ -302,110 +316,124 @@ pub mod flow {
|
||||
/// If not present, import from the file-system cache or fetch it from the database and write
|
||||
/// it to the file system and cache.
|
||||
/// This should be preferred over fetching the database directly.
|
||||
pub async fn fetch_script(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch_script<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
node: FlowNodeId,
|
||||
) -> error::Result<Arc<ScriptData>> {
|
||||
fetch_node(e, node).await.and_then(|data| match data {
|
||||
RawData::Script(data) => Ok(data),
|
||||
RawData::Flow(_) => Err(error::Error::InternalErr(format!(
|
||||
"Flow node ({:x}) isn't a script node.",
|
||||
node.0
|
||||
))),
|
||||
})
|
||||
) -> impl Future<Output = error::Result<Arc<ScriptData>>> {
|
||||
let fetch_node = fetch_node(e, node);
|
||||
async move {
|
||||
fetch_node.await.and_then(|data| match data {
|
||||
RawData::Script(data) => Ok(data),
|
||||
RawData::Flow(_) => Err(error::Error::InternalErr(format!(
|
||||
"Flow node ({:x}) isn't a script node.",
|
||||
node.0
|
||||
))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the flow node flow value referenced by `node` from the cache.
|
||||
/// If not present, import from the file-system cache or fetch it from the database and write
|
||||
/// it to the file system and cache.
|
||||
/// This should be preferred over fetching the database directly.
|
||||
pub async fn fetch_flow(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch_flow<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
node: FlowNodeId,
|
||||
) -> error::Result<Arc<FlowData>> {
|
||||
fetch_node(e, node).await.and_then(|data| match data {
|
||||
RawData::Flow(data) => Ok(data),
|
||||
RawData::Script(_) => Err(error::Error::InternalErr(format!(
|
||||
"Flow node ({:x}) isn't a flow node.",
|
||||
node.0
|
||||
))),
|
||||
})
|
||||
) -> impl Future<Output = error::Result<Arc<FlowData>>> {
|
||||
let fetch_node = fetch_node(e, node);
|
||||
async move {
|
||||
fetch_node.await.and_then(|data| match data {
|
||||
RawData::Flow(data) => Ok(data),
|
||||
RawData::Script(_) => Err(error::Error::InternalErr(format!(
|
||||
"Flow node ({:x}) isn't a flow node.",
|
||||
node.0
|
||||
))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the flow node referenced by `node` from the cache.
|
||||
/// If not present, import from the file-system cache or fetch it from the database and write
|
||||
/// it to the file system and cache.
|
||||
/// This should be preferred over fetching the database directly.
|
||||
pub(super) async fn fetch_node(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub(super) fn fetch_node<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
node: FlowNodeId,
|
||||
) -> error::Result<RawData> {
|
||||
) -> impl Future<Output = error::Result<RawData>> {
|
||||
let loc = Location::caller();
|
||||
// If not present, `get_or_insert_async` will lock the key until the future completes,
|
||||
// so only one thread will be able to fetch the data from the database and write it to
|
||||
// the file system and cache, hence no race on the file system.
|
||||
NODES
|
||||
.get_or_insert_async(
|
||||
&node,
|
||||
|(script, flow)| match flow {
|
||||
Some(flow) => RawData::Flow(Arc::new(flow)),
|
||||
_ => RawData::Script(Arc::new(script)),
|
||||
},
|
||||
async {
|
||||
sqlx::query!(
|
||||
"SELECT \
|
||||
lock AS \"lock: String\", \
|
||||
code AS \"code: String\", \
|
||||
flow AS \"flow: Json<Box<RawValue>>\" \
|
||||
FROM flow_node WHERE id = $1 LIMIT 1",
|
||||
node.0,
|
||||
NODES.get_or_insert_async(
|
||||
node,
|
||||
|(script, flow)| match flow {
|
||||
Some(flow) => RawData::Flow(Arc::new(flow)),
|
||||
_ => RawData::Script(Arc::new(script)),
|
||||
},
|
||||
async move {
|
||||
sqlx::query!(
|
||||
"SELECT \
|
||||
lock AS \"lock: String\", \
|
||||
code AS \"code: String\", \
|
||||
flow AS \"flow: Json<Box<RawValue>>\" \
|
||||
FROM flow_node WHERE id = $1 LIMIT 1",
|
||||
node.0,
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Flow node", node))
|
||||
.map(|r| {
|
||||
(
|
||||
ScriptData::from_raw(r.lock, r.code),
|
||||
r.flow.map(|Json(raw_flow)| FlowData::from_raw(raw_flow)),
|
||||
)
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.map(|r| {
|
||||
(
|
||||
ScriptData::from_raw(r.lock, r.code),
|
||||
r.flow.map(|Json(raw_flow)| FlowData::from_raw(raw_flow)),
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
.await
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn fetch_version(e: impl PgExecutor<'_>, id: i64) -> error::Result<Arc<FlowData>> {
|
||||
FLOWS
|
||||
.get_or_insert_async(&id, Arc::new, async {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT value AS \"value!: Json<Box<RawValue>>\"
|
||||
FROM flow_version WHERE id = $1 LIMIT 1",
|
||||
id,
|
||||
)
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.map(|Json(raw_flow)| FlowData::from_raw(raw_flow))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn fetch_version_lite(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch_version<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
id: i64,
|
||||
) -> error::Result<Arc<FlowData>> {
|
||||
FLOWS_LITE
|
||||
.get_or_insert_async(&id, Arc::new, async {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT value AS \"value!: Json<Box<RawValue>>\"
|
||||
FROM flow_version_lite WHERE id = $1 LIMIT 1",
|
||||
id,
|
||||
)
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.map(|Json(raw_flow)| FlowData::from_raw(raw_flow))
|
||||
})
|
||||
) -> impl Future<Output = error::Result<Arc<FlowData>>> {
|
||||
let loc = Location::caller();
|
||||
FLOWS.get_or_insert_async(id, Arc::new, async move {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT value AS \"value!: Json<Box<RawValue>>\"
|
||||
FROM flow_version WHERE id = $1 LIMIT 1",
|
||||
id,
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Flow version", id))
|
||||
.map(|Json(raw_flow)| FlowData::from_raw(raw_flow))
|
||||
})
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn fetch_version_lite<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
id: i64,
|
||||
) -> impl Future<Output = error::Result<Arc<FlowData>>> {
|
||||
let loc = Location::caller();
|
||||
FLOWS_LITE.get_or_insert_async(id, Arc::new, async move {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT value AS \"value!: Json<Box<RawValue>>\"
|
||||
FROM flow_version_lite WHERE id = $1 LIMIT 1",
|
||||
id,
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Flow version \"lite\"", id))
|
||||
.map(|Json(raw_flow)| FlowData::from_raw(raw_flow))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,44 +450,41 @@ pub mod script {
|
||||
/// If not present, import from the file-system cache or fetch it from the database and write
|
||||
/// it to the file system and cache.
|
||||
/// This should be preferred over fetching the database directly.
|
||||
pub async fn fetch(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
hash: ScriptHash,
|
||||
) -> error::Result<(Arc<ScriptData>, Arc<ScriptMetadata>)> {
|
||||
) -> impl Future<Output = error::Result<(Arc<ScriptData>, Arc<ScriptMetadata>)>> {
|
||||
// If not present, `get_or_insert_async` will lock the key until the future completes,
|
||||
// so only one thread will be able to fetch the data from the database and write it to
|
||||
// the file system and cache, hence no race on the file system.
|
||||
CACHE
|
||||
.get_or_insert_async(
|
||||
&hash,
|
||||
|(data, metadata)| (Arc::new(data), Arc::new(metadata)),
|
||||
async {
|
||||
sqlx::query!(
|
||||
"SELECT \
|
||||
lock AS \"lock: String\", \
|
||||
content AS \"code!: String\",
|
||||
language AS \"language: Option<ScriptLang>\", \
|
||||
envs AS \"envs: Vec<String>\", \
|
||||
codebase AS \"codebase: String\" \
|
||||
FROM script WHERE hash = $1 LIMIT 1",
|
||||
hash.0
|
||||
let loc = Location::caller();
|
||||
CACHE.get_or_insert_async(
|
||||
hash,
|
||||
|(data, metadata)| (Arc::new(data), Arc::new(metadata)),
|
||||
async move {
|
||||
sqlx::query!(
|
||||
"SELECT \
|
||||
lock AS \"lock: String\", \
|
||||
content AS \"code!: String\",
|
||||
language AS \"language: Option<ScriptLang>\", \
|
||||
envs AS \"envs: Vec<String>\", \
|
||||
codebase AS \"codebase: String\" \
|
||||
FROM script WHERE hash = $1 LIMIT 1",
|
||||
hash.0
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Script", hash))
|
||||
.map(|r| {
|
||||
(
|
||||
ScriptData::from_raw(r.lock, Some(r.code)),
|
||||
ScriptMetadata { language: r.language, envs: r.envs, codebase: r.codebase },
|
||||
)
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.map(|r| {
|
||||
(
|
||||
ScriptData::from_raw(r.lock, Some(r.code)),
|
||||
ScriptMetadata {
|
||||
language: r.language,
|
||||
envs: r.envs,
|
||||
codebase: r.codebase,
|
||||
},
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
.await
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Invalidate the script cache for the given `hash`.
|
||||
@@ -480,25 +505,26 @@ pub mod app {
|
||||
/// If not present, import from the file-system cache or fetch it from the database and write
|
||||
/// it to the file system and cache.
|
||||
/// This should be preferred over fetching the database directly.
|
||||
pub async fn fetch_script(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch_script<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
id: AppScriptId,
|
||||
) -> error::Result<Arc<ScriptData>> {
|
||||
) -> impl Future<Output = error::Result<Arc<ScriptData>>> {
|
||||
// If not present, `get_or_insert_async` will lock the key until the future completes,
|
||||
// so only one thread will be able to fetch the data from the database and write it to
|
||||
// the file system and cache, hence no race on the file system.
|
||||
CACHE
|
||||
.get_or_insert_async(&id, Arc::new, async {
|
||||
sqlx::query!(
|
||||
"SELECT lock, code FROM app_script WHERE id = $1 LIMIT 1",
|
||||
id.0,
|
||||
)
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.map(|r| ScriptData::from_raw(r.lock, Some(r.code)))
|
||||
})
|
||||
let loc = Location::caller();
|
||||
CACHE.get_or_insert_async(id, Arc::new, async move {
|
||||
sqlx::query!(
|
||||
"SELECT lock, code FROM app_script WHERE id = $1 LIMIT 1",
|
||||
id.0,
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Application script", id))
|
||||
.map(|r| ScriptData::from_raw(r.lock, Some(r.code)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,108 +539,129 @@ pub mod job {
|
||||
static ref PREVIEWS: Cache<Uuid, RawData> = Cache::new(50);
|
||||
}
|
||||
|
||||
pub async fn fetch_preview_flow(
|
||||
e: impl PgExecutor<'_>,
|
||||
job: &Uuid,
|
||||
#[track_caller]
|
||||
pub fn fetch_preview_flow<'a, 'c>(
|
||||
e: impl PgExecutor<'c> + 'a,
|
||||
job: &'a Uuid,
|
||||
// original raw values from `queue` or `completed_job` tables:
|
||||
// kept for backward compatibility.
|
||||
raw_flow: Option<Json<Box<RawValue>>>,
|
||||
) -> error::Result<Arc<FlowData>> {
|
||||
fetch_preview(e, job, None, None, raw_flow)
|
||||
.await
|
||||
.and_then(|data| match data {
|
||||
) -> impl Future<Output = error::Result<Arc<FlowData>>> + 'a {
|
||||
let fetch_preview = fetch_preview(e, job, None, None, raw_flow);
|
||||
async move {
|
||||
fetch_preview.await.and_then(|data| match data {
|
||||
RawData::Flow(data) => Ok(data),
|
||||
RawData::Script(_) => Err(error::Error::InternalErr(format!(
|
||||
"Job ({job}) isn't a flow job."
|
||||
))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_preview_script(
|
||||
e: impl PgExecutor<'_>,
|
||||
job: &Uuid,
|
||||
#[track_caller]
|
||||
pub fn fetch_preview_script<'a, 'c>(
|
||||
e: impl PgExecutor<'c> + 'a,
|
||||
job: &'a Uuid,
|
||||
// original raw values from `queue` or `completed_job` tables:
|
||||
// kept for backward compatibility.
|
||||
raw_lock: Option<String>,
|
||||
raw_code: Option<String>,
|
||||
) -> error::Result<Arc<ScriptData>> {
|
||||
fetch_preview(e, job, raw_lock, raw_code, None)
|
||||
.await
|
||||
.and_then(|data| match data {
|
||||
) -> impl Future<Output = error::Result<Arc<ScriptData>>> + 'a {
|
||||
let fetch_preview = fetch_preview(e, job, raw_lock, raw_code, None);
|
||||
async move {
|
||||
fetch_preview.await.and_then(|data| match data {
|
||||
RawData::Script(data) => Ok(data),
|
||||
RawData::Flow(_) => Err(error::Error::InternalErr(format!(
|
||||
"Job ({job}) isn't a script job."
|
||||
))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_preview(
|
||||
e: impl PgExecutor<'_>,
|
||||
job: &Uuid,
|
||||
#[track_caller]
|
||||
pub fn fetch_preview<'a, 'c>(
|
||||
e: impl PgExecutor<'c> + 'a,
|
||||
job: &'a Uuid,
|
||||
// original raw values from `queue` or `completed_job` tables:
|
||||
// kept for backward compatibility.
|
||||
raw_lock: Option<String>,
|
||||
raw_code: Option<String>,
|
||||
raw_flow: Option<Json<Box<RawValue>>>,
|
||||
) -> error::Result<RawData> {
|
||||
PREVIEWS
|
||||
.get_or_insert_async(job, async {
|
||||
match (raw_lock, raw_code, raw_flow) {
|
||||
(None, None, None) => sqlx::query!(
|
||||
"SELECT raw_code, raw_lock, raw_flow AS \"raw_flow: Json<Box<RawValue>>\" \
|
||||
FROM job WHERE id = $1 LIMIT 1",
|
||||
job
|
||||
)
|
||||
.fetch_one(e)
|
||||
.map_err(Into::into)
|
||||
.await
|
||||
.map(|r| (r.raw_lock, r.raw_code, r.raw_flow)),
|
||||
(lock, code, flow) => Ok((lock, code, flow)),
|
||||
}
|
||||
.map(|(lock, code, flow)| match flow {
|
||||
Some(Json(flow)) => RawData::Flow(Arc::new(FlowData::from_raw(flow))),
|
||||
_ => RawData::Script(Arc::new(ScriptData::from_raw(lock, code))),
|
||||
})
|
||||
) -> impl Future<Output = error::Result<RawData>> + 'a {
|
||||
let loc = Location::caller();
|
||||
let fetch = async move {
|
||||
match (raw_lock, raw_code, raw_flow) {
|
||||
(None, None, None) => sqlx::query!(
|
||||
"SELECT raw_code, raw_lock, raw_flow AS \"raw_flow: Json<Box<RawValue>>\" \
|
||||
FROM job WHERE id = $1 LIMIT 1",
|
||||
job
|
||||
)
|
||||
.fetch_optional(e)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
.and_then(unwrap_or_error(&loc, "Preview", job))
|
||||
.map(|r| (r.raw_lock, r.raw_code, r.raw_flow)),
|
||||
(lock, code, flow) => Ok((lock, code, flow)),
|
||||
}
|
||||
.map(|(lock, code, flow)| match flow {
|
||||
Some(Json(flow)) => RawData::Flow(Arc::new(FlowData::from_raw(flow))),
|
||||
_ => RawData::Script(Arc::new(ScriptData::from_raw(lock, code))),
|
||||
})
|
||||
.await
|
||||
};
|
||||
// Disable caching in tests: as `#[sqlx::test]` spawn a database per test, the cache
|
||||
// could yield unexpected results.
|
||||
#[cfg(test)]
|
||||
return fetch;
|
||||
#[cfg(not(test))]
|
||||
PREVIEWS.get_or_insert_async(job, fetch)
|
||||
}
|
||||
|
||||
pub async fn fetch_script(
|
||||
e: impl PgExecutor<'_>,
|
||||
#[track_caller]
|
||||
pub fn fetch_script<'c>(
|
||||
e: impl PgExecutor<'c>,
|
||||
kind: JobKind,
|
||||
hash: Option<ScriptHash>,
|
||||
) -> error::Result<Arc<ScriptData>> {
|
||||
) -> impl Future<Output = error::Result<Arc<ScriptData>>> {
|
||||
use JobKind::*;
|
||||
match (kind, hash.map(|ScriptHash(id)| id)) {
|
||||
(FlowScript, Some(id)) => flow::fetch_script(e, FlowNodeId(id)).await,
|
||||
(Script | Dependencies, Some(hash)) => script::fetch(e, ScriptHash(hash))
|
||||
.await
|
||||
.map(|(raw_script, _metadata)| raw_script),
|
||||
(AppScript, Some(id)) => app::fetch_script(e, AppScriptId(id)).await,
|
||||
_ => Err(error::Error::InternalErr(format!(
|
||||
"Isn't a script job: {:?}",
|
||||
kind
|
||||
))),
|
||||
let loc = Location::caller();
|
||||
async move {
|
||||
match (kind, hash.map(|ScriptHash(id)| id)) {
|
||||
(FlowScript, Some(id)) => flow::fetch_script(e, FlowNodeId(id)).await,
|
||||
(Script | Dependencies, Some(hash)) => script::fetch(e, ScriptHash(hash))
|
||||
.await
|
||||
.map(|(raw_script, _metadata)| raw_script),
|
||||
(AppScript, Some(id)) => app::fetch_script(e, AppScriptId(id)).await,
|
||||
_ => Err(error::Error::InternalErr(format!(
|
||||
"Isn't a script job: {:?}",
|
||||
kind
|
||||
))),
|
||||
}
|
||||
.map_err(error::relocate_internal(loc))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_flow(
|
||||
e: impl PgExecutor<'_> + Copy,
|
||||
#[track_caller]
|
||||
pub fn fetch_flow<'c>(
|
||||
e: impl PgExecutor<'c> + Copy,
|
||||
kind: JobKind,
|
||||
hash: Option<ScriptHash>,
|
||||
) -> error::Result<Arc<FlowData>> {
|
||||
) -> impl Future<Output = error::Result<Arc<FlowData>>> {
|
||||
use JobKind::*;
|
||||
match (kind, hash.map(|ScriptHash(id)| id)) {
|
||||
(FlowDependencies, Some(id)) => flow::fetch_version(e, id).await,
|
||||
(FlowNode, Some(id)) => flow::fetch_flow(e, FlowNodeId(id)).await,
|
||||
(Flow, Some(id)) => match flow::fetch_version_lite(e, id).await {
|
||||
Ok(raw_flow) => Ok(raw_flow),
|
||||
Err(_) => flow::fetch_version(e, id).await,
|
||||
},
|
||||
_ => Err(error::Error::InternalErr(format!(
|
||||
"Isn't a flow job {:?}",
|
||||
kind
|
||||
))),
|
||||
let loc = Location::caller();
|
||||
async move {
|
||||
match (kind, hash.map(|ScriptHash(id)| id)) {
|
||||
(FlowDependencies, Some(id)) => flow::fetch_version(e, id).await,
|
||||
(FlowNode, Some(id)) => flow::fetch_flow(e, FlowNodeId(id)).await,
|
||||
(Flow, Some(id)) => match flow::fetch_version_lite(e, id).await {
|
||||
Ok(raw_flow) => Ok(raw_flow),
|
||||
Err(_) => flow::fetch_version(e, id).await,
|
||||
},
|
||||
_ => Err(error::Error::InternalErr(format!(
|
||||
"Isn't a flow job {:?}",
|
||||
kind
|
||||
))),
|
||||
}
|
||||
.map_err(error::relocate_internal(loc))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* LICENSE-AGPL for a copy of the license.
|
||||
*/
|
||||
|
||||
use std::panic::Location;
|
||||
|
||||
use axum::body::Body;
|
||||
use axum::response::Response;
|
||||
use axum::{response::IntoResponse, response::Json};
|
||||
@@ -48,6 +50,8 @@ pub enum Error {
|
||||
QuotaExceeded(String),
|
||||
#[error("Internal: {0}")]
|
||||
InternalErr(String),
|
||||
#[error("Internal: {0}: {1}")]
|
||||
InternalErrAt(&'static Location<'static>, String),
|
||||
#[error("Hexadecimal decoding error: {0}")]
|
||||
HexErr(#[from] hex::FromHexError),
|
||||
#[error("Migrating database: {0}")]
|
||||
@@ -77,6 +81,17 @@ impl Error {
|
||||
pub fn dbg(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
pub fn relocate_internal(self, loc: &'static Location<'static>) -> Self {
|
||||
match self {
|
||||
Self::InternalErr(s) | Self::InternalErrAt(_, s) => Self::InternalErrAt(loc, s),
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn relocate_internal(loc: &'static Location<'static>) -> impl FnOnce(Error) -> Error {
|
||||
move |e| e.relocate_internal(loc)
|
||||
}
|
||||
|
||||
pub fn to_anyhow<T: 'static + std::error::Error + Send + Sync>(e: T) -> anyhow::Error {
|
||||
@@ -92,10 +107,9 @@ impl IntoResponse for Error {
|
||||
Self::NotFound(_) => axum::http::StatusCode::NOT_FOUND,
|
||||
Self::NotAuthorized(_) => axum::http::StatusCode::UNAUTHORIZED,
|
||||
Self::RequireAdmin(_) => axum::http::StatusCode::FORBIDDEN,
|
||||
Self::SqlErr(_)
|
||||
| Self::BadRequest(_)
|
||||
| Self::AiError(_)
|
||||
| Self::QuotaExceeded(_) => axum::http::StatusCode::BAD_REQUEST,
|
||||
Self::SqlErr(_) | Self::BadRequest(_) | Self::AiError(_) | Self::QuotaExceeded(_) => {
|
||||
axum::http::StatusCode::BAD_REQUEST
|
||||
}
|
||||
_ => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
};
|
||||
|
||||
|
||||
@@ -281,6 +281,7 @@ pub enum JobPayload {
|
||||
concurrency_time_window_s: Option<i32>,
|
||||
cache_ttl: Option<i32>,
|
||||
dedicated_worker: Option<bool>,
|
||||
path: String,
|
||||
},
|
||||
FlowNode {
|
||||
id: FlowNodeId, // flow_node(id).
|
||||
|
||||
@@ -2852,9 +2852,10 @@ pub async fn push<'c, 'd>(
|
||||
concurrency_time_window_s,
|
||||
cache_ttl,
|
||||
dedicated_worker,
|
||||
path,
|
||||
} => (
|
||||
Some(id.0),
|
||||
None,
|
||||
Some(path),
|
||||
None,
|
||||
JobKind::FlowScript,
|
||||
None,
|
||||
|
||||
@@ -2978,6 +2978,18 @@ fn payload_from_modules<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
fn get_path(flow_job: &QueuedJob, status: &FlowStatus, module: &FlowModule) -> String {
|
||||
if status
|
||||
.preprocessor_module
|
||||
.as_ref()
|
||||
.is_some_and(|x| x.id() == module.id)
|
||||
{
|
||||
format!("{}/preprocessor", flow_job.script_path())
|
||||
} else {
|
||||
format!("{}/step-{}", flow_job.script_path(), status.step)
|
||||
}
|
||||
}
|
||||
|
||||
async fn compute_next_flow_transform(
|
||||
arc_flow_job_args: Marc<HashMap<String, Box<RawValue>>>,
|
||||
arc_last_job_result: Arc<Box<RawValue>>,
|
||||
@@ -3023,6 +3035,7 @@ async fn compute_next_flow_transform(
|
||||
if is_skipped {
|
||||
return trivial_next_job(JobPayload::Identity);
|
||||
}
|
||||
|
||||
match module.get_value()? {
|
||||
FlowModuleValue::Identity => trivial_next_job(JobPayload::Identity),
|
||||
FlowModuleValue::Flow { path, .. } => {
|
||||
@@ -3052,17 +3065,8 @@ async fn compute_next_flow_transform(
|
||||
concurrency_time_window_s,
|
||||
..
|
||||
} => {
|
||||
let path = path.clone().or_else(|| {
|
||||
if status
|
||||
.preprocessor_module
|
||||
.as_ref()
|
||||
.is_some_and(|x| x.id() == module.id)
|
||||
{
|
||||
Some(format!("{}/preprocessor", flow_job.script_path()))
|
||||
} else {
|
||||
Some(format!("{}/step-{}", flow_job.script_path(), status.step))
|
||||
}
|
||||
});
|
||||
let path = path.unwrap_or_else(|| get_path(flow_job, status, module));
|
||||
|
||||
let payload = raw_script_to_payload(
|
||||
path,
|
||||
content,
|
||||
@@ -3089,6 +3093,8 @@ async fn compute_next_flow_transform(
|
||||
concurrency_time_window_s,
|
||||
..
|
||||
} => {
|
||||
let path = get_path(flow_job, status, module);
|
||||
|
||||
let payload = JobPayloadWithTag {
|
||||
payload: JobPayload::FlowScript {
|
||||
id,
|
||||
@@ -3098,6 +3104,7 @@ async fn compute_next_flow_transform(
|
||||
concurrency_time_window_s,
|
||||
cache_ttl: module.cache_ttl.map(|x| x as i32),
|
||||
dedicated_worker: None,
|
||||
path,
|
||||
},
|
||||
tag: tag.clone(),
|
||||
delete_after_use,
|
||||
@@ -3147,7 +3154,9 @@ async fn compute_next_flow_transform(
|
||||
/* forloop modules are expected set `iter: { value: Value, index: usize }` as job arguments */
|
||||
FlowModuleValue::ForloopFlow { modules, modules_node, iterator, parallel, .. } => {
|
||||
// if it's a simple single step flow, we will collapse it as an optimization and need to pass flow_input as an arg
|
||||
let is_simple = !parallel && is_simple_modules(&modules, flow.failure_module.as_ref());
|
||||
let is_simple = !matches!(flow_job.job_kind, JobKind::FlowPreview)
|
||||
&& !parallel
|
||||
&& is_simple_modules(&modules, flow.failure_module.as_ref());
|
||||
|
||||
// if is_simple {
|
||||
// match value {
|
||||
@@ -3459,7 +3468,7 @@ async fn next_loop_iteration(
|
||||
};
|
||||
return Ok(NextFlowTransform::Continue(
|
||||
ContinuePayload::SingleJob(
|
||||
payload_from_simple_module(value, db, flow_job, module, Some(inner_path())).await?,
|
||||
payload_from_simple_module(value, db, flow_job, module, inner_path()).await?,
|
||||
),
|
||||
NextStatus::NextLoopIteration { next: ns, simple_input_transforms },
|
||||
));
|
||||
@@ -3650,7 +3659,7 @@ async fn payload_from_simple_module(
|
||||
db: &sqlx::Pool<sqlx::Postgres>,
|
||||
flow_job: &QueuedJob,
|
||||
module: &FlowModule,
|
||||
inner_path: Option<String>,
|
||||
inner_path: String,
|
||||
) -> Result<JobPayloadWithTag, Error> {
|
||||
let delete_after_use = module.delete_after_use.unwrap_or(false);
|
||||
Ok(match value {
|
||||
@@ -3669,7 +3678,7 @@ async fn payload_from_simple_module(
|
||||
concurrency_time_window_s,
|
||||
..
|
||||
} => raw_script_to_payload(
|
||||
path.or(inner_path),
|
||||
path.unwrap_or_else(|| inner_path),
|
||||
content,
|
||||
language,
|
||||
lock,
|
||||
@@ -3697,6 +3706,7 @@ async fn payload_from_simple_module(
|
||||
concurrency_time_window_s,
|
||||
cache_ttl: module.cache_ttl.map(|x| x as i32),
|
||||
dedicated_worker: None,
|
||||
path: inner_path,
|
||||
},
|
||||
tag,
|
||||
delete_after_use,
|
||||
@@ -3707,7 +3717,7 @@ async fn payload_from_simple_module(
|
||||
}
|
||||
|
||||
fn raw_script_to_payload(
|
||||
path: Option<String>,
|
||||
path: String,
|
||||
content: String,
|
||||
language: windmill_common::scripts::ScriptLang,
|
||||
lock: Option<String>,
|
||||
@@ -3721,7 +3731,7 @@ fn raw_script_to_payload(
|
||||
JobPayloadWithTag {
|
||||
payload: JobPayload::Code(RawCode {
|
||||
hash: None,
|
||||
path,
|
||||
path: Some(path),
|
||||
content,
|
||||
language,
|
||||
lock,
|
||||
|
||||
+1
-1
@@ -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.439.0";
|
||||
export const VERSION = "v1.440.1";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ export {
|
||||
// }
|
||||
// });
|
||||
|
||||
export const VERSION = "1.439.0";
|
||||
export const VERSION = "1.440.1";
|
||||
|
||||
const command = new Command()
|
||||
.name("wmill")
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.439.0",
|
||||
"version": "1.440.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.439.0",
|
||||
"version": "1.440.1",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "^0.32.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.439.0",
|
||||
"version": "1.440.1",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -504,7 +504,8 @@
|
||||
initialPath: '',
|
||||
flowInputsStore: writable<FlowInput>({}),
|
||||
customUi: {},
|
||||
insertButtonOpen: writable(false)
|
||||
insertButtonOpen: writable(false),
|
||||
executionCount: writable(0),
|
||||
})
|
||||
setContext<PropPickerContext>('PropPickerContext', {
|
||||
flowPropPickerConfig: writable<FlowPropPickerConfig | undefined>(undefined),
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
export let disabledFlowInputs = false
|
||||
export let savedPrimarySchedule: ScheduleTrigger | undefined = undefined
|
||||
export let version: number | undefined = undefined
|
||||
export let setSavedraftCb: ((cb: () => void) => void) | undefined = undefined
|
||||
export let setSavedraftCb: ((cb: () => void) => void) | undefined = undefined
|
||||
|
||||
// Used by multiplayer deploy collision warning
|
||||
let deployedValue: Value | undefined = undefined // Value to diff against
|
||||
@@ -528,7 +528,8 @@
|
||||
initialPath,
|
||||
flowInputsStore: writable<FlowInput>({}),
|
||||
customUi,
|
||||
insertButtonOpen
|
||||
insertButtonOpen,
|
||||
executionCount: writable(0)
|
||||
})
|
||||
|
||||
setContext<TriggerContext>('TriggerContext', {
|
||||
|
||||
@@ -36,8 +36,16 @@
|
||||
runPreview($previewArgs, undefined)
|
||||
}
|
||||
|
||||
const { selectedId, previewArgs, flowStateStore, flowStore, pathStore, initialPath, customUi } =
|
||||
getContext<FlowEditorContext>('FlowEditorContext')
|
||||
const {
|
||||
selectedId,
|
||||
previewArgs,
|
||||
flowStateStore,
|
||||
flowStore,
|
||||
pathStore,
|
||||
initialPath,
|
||||
customUi,
|
||||
executionCount
|
||||
} = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function extractFlow(previewMode: 'upTo' | 'whole'): OpenFlow {
|
||||
@@ -330,6 +338,10 @@
|
||||
wideResults
|
||||
{flowStateStore}
|
||||
{jobId}
|
||||
on:done={() => {
|
||||
console.log('done')
|
||||
$executionCount = $executionCount + 1
|
||||
}}
|
||||
on:jobsLoaded={({ detail }) => {
|
||||
job = detail
|
||||
}}
|
||||
|
||||
@@ -627,7 +627,6 @@
|
||||
j != state?.selectedForloopIndex ||
|
||||
setManually != state?.selectedForLoopSetManually
|
||||
if (selectedNotEqual) {
|
||||
console.log('not equal')
|
||||
globalState?.update((topLevelModuleStates) => {
|
||||
topLevelModuleStates[modId] = {
|
||||
type: 'WaitingForPriorSteps',
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
value = nvalue
|
||||
if (typeof nvalue === 'string') {
|
||||
value = nvalue?.split('T')?.[0]
|
||||
} else {
|
||||
console.error('Invalid value', nvalue)
|
||||
value = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
pathStore,
|
||||
saveDraft,
|
||||
flowInputsStore,
|
||||
customUi
|
||||
customUi,
|
||||
executionCount
|
||||
} = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
export let flowModule: FlowModule
|
||||
@@ -107,17 +108,18 @@
|
||||
|
||||
$: editor !== undefined && setCopilotModuleEditor()
|
||||
|
||||
$: stepPropPicker = failureModule
|
||||
? getFailureStepPropPicker($flowStateStore, $flowStore, $previewArgs)
|
||||
: getStepPropPicker(
|
||||
$flowStateStore,
|
||||
parentModule,
|
||||
previousModule,
|
||||
flowModule.id,
|
||||
$flowStore,
|
||||
$previewArgs,
|
||||
false
|
||||
)
|
||||
$: stepPropPicker =
|
||||
$executionCount != undefined && failureModule
|
||||
? getFailureStepPropPicker($flowStateStore, $flowStore, $previewArgs)
|
||||
: getStepPropPicker(
|
||||
$flowStateStore,
|
||||
parentModule,
|
||||
previousModule,
|
||||
flowModule.id,
|
||||
$flowStore,
|
||||
$previewArgs,
|
||||
false
|
||||
)
|
||||
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.key == 'Enter') {
|
||||
|
||||
@@ -74,12 +74,18 @@ function getFlowInput(
|
||||
if (parentState && parentModule) {
|
||||
if (
|
||||
parentState.previewArgs &&
|
||||
!(parentModule.value?.type === 'forloopflow' && parentModule.value?.modules?.length === 1) &&
|
||||
parentState &&
|
||||
typeof parentState.previewArgs == 'object' &&
|
||||
`iter` in parentState.previewArgs
|
||||
) {
|
||||
return { ...topFlowInput, ...parentState.previewArgs }
|
||||
return {
|
||||
iter: {
|
||||
value: "Iteration's value",
|
||||
index: "Iteration's index"
|
||||
},
|
||||
...topFlowInput,
|
||||
...parentState.previewArgs
|
||||
}
|
||||
} else {
|
||||
let parentFlowInput = getFlowInput(parentModules, flowState, args, schema)
|
||||
if (parentModule.value.type === 'forloopflow') {
|
||||
|
||||
@@ -40,4 +40,5 @@ export type FlowEditorContext = {
|
||||
flowInputsStore: Writable<FlowInput>
|
||||
customUi: FlowBuilderWhitelabelCustomUi
|
||||
insertButtonOpen: Writable<boolean>
|
||||
executionCount: Writable<number>
|
||||
}
|
||||
|
||||
@@ -94,8 +94,10 @@
|
||||
let filteringFlowInputsOrResult = ''
|
||||
async function filterPickableProperties() {
|
||||
if (!$propPickerConfig || !filterActive) {
|
||||
flowInputsFiltered = pickableProperties.flow_input
|
||||
resultByIdFiltered = pickableProperties.priorIds
|
||||
if (search === EMPTY_STRING) {
|
||||
flowInputsFiltered = pickableProperties.flow_input
|
||||
resultByIdFiltered = pickableProperties.priorIds
|
||||
}
|
||||
filteringFlowInputsOrResult = ''
|
||||
return
|
||||
}
|
||||
@@ -189,7 +191,7 @@
|
||||
await updateCollapsable()
|
||||
}
|
||||
|
||||
$: search, $inputMatches, $propPickerConfig, updateState()
|
||||
$: search, $inputMatches, $propPickerConfig, pickableProperties, updateState()
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col h-full rounded">
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
export let isCollapsed: boolean = false
|
||||
|
||||
// When used outside of the side bar, where links to workspace settings and such don't make as much sense.
|
||||
export let strictWorkspaceSelect = false
|
||||
|
||||
async function toggleSwitchWorkspace(id: string) {
|
||||
if ($workspaceStore === id) {
|
||||
return
|
||||
@@ -76,7 +79,7 @@
|
||||
</MenuItem>
|
||||
{/each}
|
||||
</div>
|
||||
{#if isCloudHosted() || $superadmin}
|
||||
{#if (isCloudHosted() || $superadmin) && !strictWorkspaceSelect}
|
||||
<div class="py-1" role="none">
|
||||
<a
|
||||
href="{base}/user/create_workspace"
|
||||
@@ -89,6 +92,7 @@
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{#if !strictWorkspaceSelect}
|
||||
<div class="py-1" role="none">
|
||||
<a
|
||||
href="{base}/user/workspaces"
|
||||
@@ -102,7 +106,8 @@
|
||||
All workspaces
|
||||
</a>
|
||||
</div>
|
||||
{#if $userStore?.is_admin || $superadmin}
|
||||
{/if}
|
||||
{#if ($userStore?.is_admin || $superadmin) && !strictWorkspaceSelect}
|
||||
<div class="py-1" role="none">
|
||||
<MenuItem>
|
||||
<a
|
||||
@@ -118,7 +123,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if isCloudHosted() && !$isPremiumStore}
|
||||
{#if isCloudHosted() && !$isPremiumStore && !strictWorkspaceSelect}
|
||||
<div class="py-1" role="none">
|
||||
{#if $workspaceStore != 'demo'}
|
||||
<span class="text-secondary block w-full text-left px-4 py-2 text-xs"
|
||||
@@ -146,7 +151,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if $enterpriseLicense}
|
||||
{#if $enterpriseLicense && !strictWorkspaceSelect}
|
||||
<MultiplayerMenu />
|
||||
{/if}
|
||||
</Menu>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import ScriptPicker from '$lib/components/ScriptPicker.svelte'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import { Button } from '$lib/components/common'
|
||||
import { page } from '$app/stores'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
@@ -9,6 +7,7 @@
|
||||
import UserSettings from '$lib/components/UserSettings.svelte'
|
||||
import { generateRandomString } from '$lib/utils'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import WorkspaceMenu from '$lib/components/sidebar/WorkspaceMenu.svelte'
|
||||
|
||||
let itemPath: string | undefined = undefined
|
||||
let itemKind: 'script' | 'flow' | 'app' = 'script'
|
||||
@@ -77,73 +76,90 @@
|
||||
{scopes}
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<div class="flex items-center justify-center h-screen">
|
||||
<div class="flex flex-col gap-5">
|
||||
<div class="flex flex-row gap-3 items-center justify-center">
|
||||
<PageHeader title={`${clientName} wants to create a webhook`} />
|
||||
<div class="flex items-center justify-center h-screen w-screen min-w-0">
|
||||
<div class="flex flex-col gap-5 min-w-0 px-2">
|
||||
<div class="flex flex-row gap-3 items-center justify-center break-words whitespace-normal py-8">
|
||||
<h1 class="!text-3xl font-semibold text-center"
|
||||
>{`${clientName} wants to create a webhook`}</h1
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 items-center">
|
||||
<div
|
||||
class="flex items-center justify-center min-w-10 w-10 h-10 border-2 border-blue-500 text-blue-500 font-bold rounded-full"
|
||||
>
|
||||
1
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 items-center">
|
||||
<div
|
||||
class="flex items-center justify-center w-10 h-10 border-2 border-blue-500 text-blue-500 font-bold rounded-full"
|
||||
>
|
||||
1
|
||||
<h2>Select the script or flow to be triggered by the webhook</h2>
|
||||
</div>
|
||||
<div class="flex flex-row items-center justify-center w-100%">
|
||||
<div class="flex flex-col items-center gap-3 w-full">
|
||||
<div class="flex flex-row items-center justify-center w-full">
|
||||
<span class="flex justify-end w-full items-right"> Selected Workspace: </span>
|
||||
<WorkspaceMenu strictWorkspaceSelect />
|
||||
</div>
|
||||
<ScriptPicker
|
||||
allowEdit={false}
|
||||
allowFlow={true}
|
||||
allowRefresh={true}
|
||||
bind:scriptPath={itemPath}
|
||||
bind:itemKind
|
||||
/>
|
||||
<h4>or</h4>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button size="xs" color="light" variant="border" target="_blank" href="/scripts/add"
|
||||
>Create new script</Button
|
||||
>
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
target="_blank"
|
||||
href="/flows/add?nodraft=true">Create new flow</Button
|
||||
>
|
||||
</div>
|
||||
<h2>Select the script or flow to be triggered by the webhook</h2>
|
||||
</div>
|
||||
<div class="flex flex-row items-center justify-center w-100%">
|
||||
<div class="flex flex-col items-center gap-3 w-full">
|
||||
<ScriptPicker
|
||||
allowEdit={false}
|
||||
allowFlow={true}
|
||||
allowRefresh={true}
|
||||
bind:scriptPath={itemPath}
|
||||
bind:itemKind
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 items-center mt-3">
|
||||
<div
|
||||
class="flex items-center justify-center w-10 h-10 border-2 border-blue-500 text-blue-500 font-bold rounded-full min-w-10"
|
||||
>
|
||||
2
|
||||
</div>
|
||||
<h2>Create a token for this webhook</h2>
|
||||
<Tooltip customSize="150%">
|
||||
By generating a webhook specific token, you get a token that can only be used to trigger
|
||||
this {itemKind}, making it safe to share without risk of impersonation. You can also opt to
|
||||
use another token by entering it in the input field directly.
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex flex-row items-center justify-center">
|
||||
<div class="flex flex-col items-center gap-5 w-100%">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<input
|
||||
bind:value={token}
|
||||
disabled={itemPath == undefined}
|
||||
placeholder="enter or generate token"
|
||||
class="!text-md min-w-10 max-w-40"
|
||||
/>
|
||||
<h4>or</h4>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button size="xs" color="light" variant="border" target="_blank" href="/scripts/add">Create new script</Button>
|
||||
<Button size="xs" color="light" variant="border" target="_blank" href="/flows/add?nodraft=true">Create new flow</Button>
|
||||
</div>
|
||||
<Button
|
||||
size="md"
|
||||
btnClasses="whitespace-normal break-words flex flex-wrap"
|
||||
disabled={itemPath == undefined}
|
||||
on:click={userSettings.openDrawer}
|
||||
>
|
||||
Generate webhook-specific Token
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row gap-3 items-center mt-3">
|
||||
<div
|
||||
class="flex items-center justify-center w-10 h-10 border-2 border-blue-500 text-blue-500 font-bold rounded-full"
|
||||
>
|
||||
2
|
||||
</div>
|
||||
<h2>Create a token for this webhook</h2>
|
||||
<Tooltip customSize="150%">
|
||||
If you generate a token, it will have a scope such that it can only be used to
|
||||
trigger this {itemKind}. It is safe to share as it cannot be used to impersonate you.
|
||||
Otherwise you may enter another token but beware that it will be shared with the external
|
||||
application.
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex flex-row items-center justify-center">
|
||||
<div class="flex flex-col items-center gap-5 w-100%">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<input
|
||||
bind:value={token}
|
||||
disabled={itemPath == undefined}
|
||||
placeholder="enter or generate token"
|
||||
class="!text-md"
|
||||
/>
|
||||
<Button size="md" disabled={itemPath == undefined} on:click={userSettings.openDrawer}>
|
||||
Generate webhook-specific Token
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 mt-10">
|
||||
<Button
|
||||
disabled={!itemPath || !token || token === ''}
|
||||
on:click={() => itemPath && token && createWebhook(itemPath, itemKind, token)}
|
||||
>Approve and share with {clientName}</Button
|
||||
>
|
||||
<Button color="red" on:click={() => redirectCancel('user_canceled')}>Cancel</Button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 mt-10">
|
||||
<Button
|
||||
disabled={!itemPath || !token || token === ''}
|
||||
btnClasses="whitespace-normal break-words flex flex-wrap"
|
||||
on:click={() => itemPath && token && createWebhook(itemPath, itemKind, token)}
|
||||
>Approve and share with {clientName}</Button
|
||||
>
|
||||
<Button color="red" on:click={() => redirectCancel('user_canceled')}>Cancel</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CenteredPage>
|
||||
</div>
|
||||
|
||||
@@ -99,7 +99,8 @@
|
||||
initialPath: '',
|
||||
flowInputsStore: writable<FlowInput>({}),
|
||||
customUi: {},
|
||||
insertButtonOpen: writable(false)
|
||||
insertButtonOpen: writable(false),
|
||||
executionCount: writable(0)
|
||||
})
|
||||
setContext<PropPickerContext>('PropPickerContext', {
|
||||
flowPropPickerConfig: writable<FlowPropPickerConfig | undefined>(undefined),
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.439.0"
|
||||
wmill_pg = ">=1.439.0"
|
||||
wmill = ">=1.440.1"
|
||||
wmill_pg = ">=1.440.1"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.439.0
|
||||
version: 1.440.1
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'WindmillClient.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.439.0'
|
||||
ModuleVersion = '1.440.1'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
description = "A client library for accessing Windmill server wrapping the Windmill client API"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill-pg"
|
||||
version = "1.439.0"
|
||||
version = "1.440.1"
|
||||
description = "An extension client for the wmill client library focused on pg"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@windmill/windmill",
|
||||
"version": "1.439.0",
|
||||
"version": "1.440.1",
|
||||
"exports": "./src/index.ts",
|
||||
"publish": {
|
||||
"exclude": ["!src", "./s3Types.ts", "./client.ts"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-client",
|
||||
"description": "Windmill SDK client for browsers and Node.js",
|
||||
"version": "1.439.0",
|
||||
"version": "1.440.1",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.439.0
|
||||
1.440.1
|
||||
|
||||
Reference in New Issue
Block a user