mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-12 16:02:56 +00:00
Merge origin/main into restricted-job-tokens
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "1.820.0"
|
||||
".": "1.821.0"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
# Changelog
|
||||
|
||||
## [1.821.0](https://github.com/windmill-labs/windmill/compare/v1.820.0...v1.821.0) (2026-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add //no_network annotation for native scripts ([#11445](https://github.com/windmill-labs/windmill/issues/11445)) ([c25bb1e](https://github.com/windmill-labs/windmill/commit/c25bb1ed90d88167df0c36817942427a32fc3205))
|
||||
* add alert actions and reduce alert padding ([#11439](https://github.com/windmill-labs/windmill/issues/11439)) ([52c3188](https://github.com/windmill-labs/windmill/commit/52c31881fc433a03ef13f7a8cde1410da8634e19))
|
||||
* add test key button to AI resource drawers ([#11466](https://github.com/windmill-labs/windmill/issues/11466)) ([26be1d7](https://github.com/windmill-labs/windmill/commit/26be1d7da8be48c2e7d7a6b95d406513d649be4e))
|
||||
* add wmill datatable migrate status ([#11465](https://github.com/windmill-labs/windmill/issues/11465)) ([7f1bead](https://github.com/windmill-labs/windmill/commit/7f1beadf793e8db05333d253f464954510961a5b))
|
||||
* agents as a standalone kind with home listing, detail and editor pages ([#11332](https://github.com/windmill-labs/windmill/issues/11332)) ([8c7dcbb](https://github.com/windmill-labs/windmill/commit/8c7dcbbda58c86743bf3822c422be7faf1e8df51))
|
||||
* dispatch ai agent tools through the worker queue ([#11227](https://github.com/windmill-labs/windmill/issues/11227)) ([039f49e](https://github.com/windmill-labs/windmill/commit/039f49ef124eacefc0ee34dcb011ea5773383845))
|
||||
* group consecutive tool calls in the AI chat ([#11329](https://github.com/windmill-labs/windmill/issues/11329)) ([9613549](https://github.com/windmill-labs/windmill/commit/9613549abc1c1d63abb252e8a675c6a73142b26f))
|
||||
* harden job OIDC tokens with version claims, jti and a lifetime cap ([#11457](https://github.com/windmill-labs/windmill/issues/11457)) ([227e934](https://github.com/windmill-labs/windmill/commit/227e9342108bf7c5be5721a777ff9ec544a44f08))
|
||||
* labelled scope checkboxes in the oauth connect dialog ([#11460](https://github.com/windmill-labs/windmill/issues/11460)) ([840567f](https://github.com/windmill-labs/windmill/commit/840567fbe5c8779ac163b02a6e02e3d8ec1178a8))
|
||||
* let operators compose flows when the workspace grants the right ([#11228](https://github.com/windmill-labs/windmill/issues/11228)) ([ca44043](https://github.com/windmill-labs/windmill/commit/ca44043e12d4713d67ca13eb546eef9d00cc965e))
|
||||
* let slack connects issue a user token via user_scope ([#11452](https://github.com/windmill-labs/windmill/issues/11452)) ([d518aa5](https://github.com/windmill-labs/windmill/commit/d518aa5557910d10ec5a8ca6fff3fd0ad2fa31fc))
|
||||
* make hub integrations usable as examples in global AI chat ([#10599](https://github.com/windmill-labs/windmill/issues/10599)) ([8953ca6](https://github.com/windmill-labs/windmill/commit/8953ca670aac63feab1a04369df50a669c1f40bc))
|
||||
* offer slack write scopes as bot and user scope options ([#11472](https://github.com/windmill-labs/windmill/issues/11472)) ([ab2de83](https://github.com/windmill-labs/windmill/commit/ab2de838d76e2229da0867c93c2f18dc34d0d076))
|
||||
* open chat path pill actions from a hover menu ([#11441](https://github.com/windmill-labs/windmill/issues/11441)) ([083db5e](https://github.com/windmill-labs/windmill/commit/083db5e38855586491920abf678e3247d8c82a43))
|
||||
* rename agent memory options to On and Legacy, explain each ([#11442](https://github.com/windmill-labs/windmill/issues/11442)) ([077709b](https://github.com/windmill-labs/windmill/commit/077709b914b8b58cbd8c99f1048c7fecc2978c6b))
|
||||
* **sessions:** show an item's deployed page in the preview panel ([#11458](https://github.com/windmill-labs/windmill/issues/11458)) ([b10f83c](https://github.com/windmill-labs/windmill/commit/b10f83c763abf49118c05dc08ec2b19570e21475))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **apps:** hide custom component host while it is not rendered ([#11434](https://github.com/windmill-labs/windmill/issues/11434)) ([c728346](https://github.com/windmill-labs/windmill/commit/c728346a151e4a0a2d1ecaae397068871186323d))
|
||||
* await async def main in python scripts ([#11437](https://github.com/windmill-labs/windmill/issues/11437)) ([94ac34a](https://github.com/windmill-labs/windmill/commit/94ac34a4891a8572ad2493bdbbbf2f4911236aff))
|
||||
* block runs while a JSON input does not parse ([#11463](https://github.com/windmill-labs/windmill/issues/11463)) ([ddde41b](https://github.com/windmill-labs/windmill/commit/ddde41bc1de6f7dea32b21a61ce2a5bf3bf8bba6))
|
||||
* bump git sync hub scripts to cli 1.820.1 ([#11438](https://github.com/windmill-labs/windmill/issues/11438)) ([7664001](https://github.com/windmill-labs/windmill/commit/7664001b36afc80bd8d26cb12c917c971e24e96f))
|
||||
* **cli:** resolve fork specific items from the parent workspace entry ([#11436](https://github.com/windmill-labs/windmill/issues/11436)) ([1d8d4a1](https://github.com/windmill-labs/windmill/commit/1d8d4a16b4396acb70484c858058353eb1ba9d6f))
|
||||
* collapse run card in ai chat when the run is declined ([#11435](https://github.com/windmill-labs/windmill/issues/11435)) ([ab2a973](https://github.com/windmill-labs/windmill/commit/ab2a973357524c2c3aa81cc4aeb716d8cfd108d1))
|
||||
* embed a VERSIONINFO resource in the Windows binary ([#11433](https://github.com/windmill-labs/windmill/issues/11433)) ([9028432](https://github.com/windmill-labs/windmill/commit/9028432e8a71b9601ff65160a29e683a9cc24989))
|
||||
* ignore edited_at and edited_by in flow and item diffs ([#11455](https://github.com/windmill-labs/windmill/issues/11455)) ([851f6d7](https://github.com/windmill-labs/windmill/commit/851f6d74c98e849b25d6999e3d8ee492c997d5a9))
|
||||
* keep flow graph rendered between deploy and navigation ([#11454](https://github.com/windmill-labs/windmill/issues/11454)) ([c0fb2db](https://github.com/windmill-labs/windmill/commit/c0fb2db24454d17d33fffa41b59e6a4cf61db44f))
|
||||
* lost suspend decrement when concurrent approvals resume a flow ([#11450](https://github.com/windmill-labs/windmill/issues/11450)) ([a8e65ab](https://github.com/windmill-labs/windmill/commit/a8e65ab1e6287805f616f2531dc6a62134134e36))
|
||||
* **npm-proxy:** support _auth and username/_password basic auth from npmrc ([#11467](https://github.com/windmill-labs/windmill/issues/11467)) ([1c6758a](https://github.com/windmill-labs/windmill/commit/1c6758a65651d90088f981317c06b12a19f3b73f))
|
||||
* offer user scopes in the slack scope editor and drop the generated description on type change ([#11464](https://github.com/windmill-labs/windmill/issues/11464)) ([153b02a](https://github.com/windmill-labs/windmill/commit/153b02a5de19c615e6640d52ad48b1c507402851))
|
||||
* restore the save to workspace button on inline flow steps ([#11469](https://github.com/windmill-labs/windmill/issues/11469)) ([88d0cd0](https://github.com/windmill-labs/windmill/commit/88d0cd00e54de7dd9b008f6f233992cb6ae69571))
|
||||
* stop running deleted script versions from worker caches ([#11456](https://github.com/windmill-labs/windmill/issues/11456)) ([d2830cb](https://github.com/windmill-labs/windmill/commit/d2830cb4a0effc369aa5dbebdb32e770a2c87e18))
|
||||
|
||||
## [1.820.0](https://github.com/windmill-labs/windmill/compare/v1.819.0...v1.820.0) (2026-09-29)
|
||||
|
||||
|
||||
|
||||
Generated
+161
-123
File diff suppressed because it is too large
Load Diff
+18
-33
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -88,7 +88,7 @@ members = [
|
||||
exclude = ["./windmill-duckdb-ffi-internal", "./parsers/windmill-parser-wasm"]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -249,36 +249,21 @@ sqlx-sqlite = { git = "https://github.com/windmill-labs/sqlx", rev = "6bdaee94fa
|
||||
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7" }
|
||||
# Use tiberius main branch for libgssapi 0.8.1 fix (https://github.com/prisma/tiberius/issues/343)
|
||||
tiberius = { git = "https://github.com/prisma/tiberius", rev = "59db57960a14b422fb3a1309aa4aa47880896ff8" }
|
||||
# Pin tokio-postgres / postgres-types / postgres-protocol to the
|
||||
# MaterializeInc fork. windmill-trigger-postgres already pulled this
|
||||
# fork in transitively for the postgres-replication crate
|
||||
# (CopyBothDuplex, LogicalReplicationStream, TupleData with binary
|
||||
# tuple support) which upstream rust-postgres has declined to merge
|
||||
# since 2021 (PR #752 → #778, both still unmerged).
|
||||
# Pin tokio-postgres / postgres-types / postgres-protocol to
|
||||
# windmill-labs/rust-postgres, branch `windmill-describe-first`: the
|
||||
# MaterializeInc fork (postgres-replication, which upstream has not merged)
|
||||
# plus `Client::describe_typed`, which pg_executor needs before
|
||||
# query_typed_raw so result columns of types the client has not seen yet
|
||||
# (custom enums / domains, citext, postgis) don't deadlock a large result.
|
||||
# Each pinned commit carries a `windmill-*` tag so it stays reachable when the
|
||||
# branch is rebased onto MaterializeInc master.
|
||||
#
|
||||
# MI also carries a mitigation for the
|
||||
# Client::query_typed_raw / Client::prepare deadlock on result columns
|
||||
# whose Oid the client doesn't know about yet (citext, custom enums /
|
||||
# domains, postgis): MI's 2025-12-11 PR #33 resized the per-request
|
||||
# response channel from mpsc::channel(1) → mpsc::channel(1024).
|
||||
# bounded(1024) is sufficient for any realistic typeinfo deferral
|
||||
# (need ~2-3 batches) but leaves a theoretical failure mode at
|
||||
# >~64 MB results with a custom-Oid column. The strict-correct fix is
|
||||
# mpsc::unbounded(); a follow-up PR to MI is open proposing that.
|
||||
#
|
||||
# The [patch.crates-io] entries below force windmill-worker's
|
||||
# pg_executor (which imports `tokio_postgres::` directly from
|
||||
# crates.io) onto the same fork as windmill-trigger-postgres, so the
|
||||
# deadlock mitigation reaches both consumers.
|
||||
#
|
||||
# Upstream deadlock PRs (open, not on the critical path now that MI
|
||||
# is mitigated):
|
||||
# https://github.com/rust-postgres/rust-postgres/pull/1348
|
||||
# https://github.com/rust-postgres/rust-postgres/pull/1349
|
||||
# Reproducer: https://github.com/rubenfiszel/tokio-postgres-deadlock-repro
|
||||
tokio-postgres = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
|
||||
postgres-types = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
|
||||
postgres-protocol = { git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
|
||||
# The [patch.crates-io] entries force windmill-worker's pg_executor (which
|
||||
# imports `tokio_postgres::` from crates.io) onto the same fork as
|
||||
# windmill-trigger-postgres.
|
||||
tokio-postgres = { git = "https://github.com/windmill-labs/rust-postgres", rev = "7f4374f9237237759305942727e136742b1e7f8b" }
|
||||
postgres-types = { git = "https://github.com/windmill-labs/rust-postgres", rev = "7f4374f9237237759305942727e136742b1e7f8b" }
|
||||
postgres-protocol = { git = "https://github.com/windmill-labs/rust-postgres", rev = "7f4374f9237237759305942727e136742b1e7f8b" }
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
@@ -630,8 +615,8 @@ convert_case = "0.6.0"
|
||||
getrandom = "0.2"
|
||||
tokio-postgres = {version = "^0.7", features = ["array-impls", "with-serde_json-1", "with-chrono-0_4", "with-uuid-1", "with-bit-vec-0_6"]}
|
||||
postgres-protocol = "0.6"
|
||||
rust-postgres = { package = "tokio-postgres", git = "https://github.com/MaterializeInc/rust-postgres", rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe"}
|
||||
rust-postgres-native-tls = { package = "postgres-native-tls", git = "https://github.com/MaterializeInc/rust-postgres", features = ["runtime"], rev = "78c1222577bb091d69bc22b1bc7ad01c14675abe" }
|
||||
rust-postgres = { package = "tokio-postgres", git = "https://github.com/windmill-labs/rust-postgres", rev = "7f4374f9237237759305942727e136742b1e7f8b"}
|
||||
rust-postgres-native-tls = { package = "postgres-native-tls", git = "https://github.com/windmill-labs/rust-postgres", features = ["runtime"], rev = "7f4374f9237237759305942727e136742b1e7f8b" }
|
||||
bit-vec = "=0.6.3"
|
||||
mappable-rc = "^0"
|
||||
mysql_async = { version = "*", default-features = false, features = ["minimal", "default", "native-tls-tls", "rust_decimal"]}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"github": {
|
||||
"auth_url": "https://github.com/login/oauth/authorize",
|
||||
"token_url": "https://github.com/login/oauth/access_token",
|
||||
"scopes": ["workflow", "repo"]
|
||||
"scopes": ["workflow", "repo"],
|
||||
"scope_options": ["repo", "workflow", "gist", "read:org"]
|
||||
},
|
||||
"gitlab": {
|
||||
"auth_url": "https://gitlab.com/oauth/authorize",
|
||||
|
||||
+24
-24
@@ -6216,7 +6216,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
@@ -6302,7 +6302,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-macros"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -6314,7 +6314,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"serde",
|
||||
@@ -6323,7 +6323,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6335,7 +6335,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-csharp"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -6347,7 +6347,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -6359,7 +6359,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6371,7 +6371,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-java"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -6383,7 +6383,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-nu"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"nu-parser",
|
||||
@@ -6394,7 +6394,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -6405,7 +6405,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -6417,7 +6417,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-asset"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"rustpython-ast",
|
||||
@@ -6428,7 +6428,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -6450,7 +6450,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-r"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -6462,7 +6462,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ruby"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6476,7 +6476,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-rust"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case",
|
||||
@@ -6493,7 +6493,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6506,7 +6506,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql-asset"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -6518,7 +6518,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6536,7 +6536,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts-asset"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde-wasm-bindgen",
|
||||
@@ -6552,7 +6552,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wac"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"rustpython-ast",
|
||||
@@ -6568,7 +6568,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.17",
|
||||
@@ -6600,7 +6600,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-yaml"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -6614,7 +6614,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-types"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
|
||||
@@ -12,7 +12,7 @@ resolver = "2"
|
||||
members = ["."]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
edition = "2021"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
|
||||
|
||||
+39
-39
@@ -44,28 +44,27 @@ use windmill_common::{
|
||||
CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING, CRITICAL_ALERT_MUTE_UI_SETTING,
|
||||
CRITICAL_ALERT_MUTE_ZOMBIE_JOB_RESTART_SETTING, CRITICAL_ERROR_CHANNELS_SETTING,
|
||||
CUSTOM_TAGS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING,
|
||||
DISABLE_PASSWORD_LOGIN_SETTING, EMAIL_DOMAIN_SETTING, ENV_SETTINGS,
|
||||
EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
|
||||
DEPENDENCY_JOB_TAG_SETTING, DISABLE_PASSWORD_LOGIN_SETTING, EMAIL_DOMAIN_SETTING,
|
||||
ENV_SETTINGS, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
|
||||
EXTRA_PIP_INDEX_URL_SETTING, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
|
||||
HTTP_ROUTE_DEFAULT_ALLOWED_ORIGINS_SETTING, HTTP_ROUTE_WORKSPACED_ROUTE_SETTING,
|
||||
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INDEXER_SETTING,
|
||||
INSTANCE_EVENTS_WEBHOOK_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
|
||||
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING,
|
||||
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING, MAVEN_SETTINGS_XML_SETTING,
|
||||
MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING,
|
||||
NO_DEFAULT_MAVEN_SETTING,
|
||||
NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING,
|
||||
NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING,
|
||||
OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
|
||||
POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
|
||||
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RESTART_COORDINATION_SETTING,
|
||||
RETENTION_PERIOD_SECS_OVERRIDES_SETTING, RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING,
|
||||
SAML_METADATA_SETTING, SANDBOX_IMAGE_CACHE_MAX_MB_SETTING,
|
||||
SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING, SANDBOX_IMAGE_MAX_SIZE_MB_SETTING,
|
||||
SANDBOX_IMAGE_PULL_POLICY_SETTING, SANDBOX_REGISTRY_AUTH_SETTING, SCIM_TOKEN_SETTING,
|
||||
SERVICE_LOG_RETENTION_SECS_SETTING, SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING,
|
||||
TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING,
|
||||
UV_INDEX_STRATEGY_SETTING, UV_PYTHON_INSTALL_MIRROR_SETTING,
|
||||
NO_DEFAULT_MAVEN_SETTING, NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING,
|
||||
NSJAIL_TMP_BACKING_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING,
|
||||
OTEL_TRACES_RETENTION_SECS_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING,
|
||||
POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING,
|
||||
REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING,
|
||||
RESTART_COORDINATION_SETTING, RETENTION_PERIOD_SECS_OVERRIDES_SETTING,
|
||||
RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING, SAML_METADATA_SETTING,
|
||||
SANDBOX_IMAGE_CACHE_MAX_MB_SETTING, SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING,
|
||||
SANDBOX_IMAGE_MAX_SIZE_MB_SETTING, SANDBOX_IMAGE_PULL_POLICY_SETTING,
|
||||
SANDBOX_REGISTRY_AUTH_SETTING, SCIM_TOKEN_SETTING, SERVICE_LOG_RETENTION_SECS_SETTING,
|
||||
SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING, TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
|
||||
UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING, UV_PYTHON_INSTALL_MIRROR_SETTING,
|
||||
WORKSPACE_FAIRNESS_DURATION_SECS_SETTING, WORKSPACE_FAIRNESS_ENABLED_SETTING,
|
||||
WORKSPACE_FAIRNESS_MAX_PERCENT_SETTING, WORKSPACE_FAIRNESS_MIN_TOTAL_SETTING,
|
||||
WORKSPACE_MAX_QUEUED_JOBS_SETTING, WORKSPACE_REGISTRIES_SETTING,
|
||||
@@ -126,24 +125,23 @@ use windmill_worker::{
|
||||
};
|
||||
|
||||
use crate::monitor::{
|
||||
initial_load, load_concurrency_key_max_queued, load_disable_password_login,
|
||||
load_fork_workspace_tag_append_fork_suffix, load_keep_job_dir,
|
||||
load_mcp_disable_token_query_param, load_metrics_debug_enabled,
|
||||
load_preview_tags_override, load_require_preexisting_user, load_retention_period_overrides,
|
||||
load_tag_per_workspace_enabled, load_tag_per_workspace_workspaces,
|
||||
load_workspace_fairness_duration_secs, load_workspace_fairness_enabled,
|
||||
load_workspace_fairness_max_percent, load_workspace_fairness_min_total,
|
||||
load_workspace_max_queued_jobs, monitor_db, reload_app_workspaced_route_setting,
|
||||
reload_audit_log_retention_days_setting, reload_base_url_setting,
|
||||
reload_bun_install_min_release_age_setting, reload_bunfig_install_scopes_setting,
|
||||
reload_critical_alert_mute_ui_setting, reload_critical_alert_mute_zombie_job_restart_setting,
|
||||
initial_load, load_concurrency_key_max_queued, load_dependency_job_tag,
|
||||
load_disable_password_login, load_fork_workspace_tag_append_fork_suffix, load_keep_job_dir,
|
||||
load_mcp_disable_token_query_param, load_metrics_debug_enabled, load_preview_tags_override,
|
||||
load_require_preexisting_user, load_retention_period_overrides, load_tag_per_workspace_enabled,
|
||||
load_tag_per_workspace_workspaces, load_workspace_fairness_duration_secs,
|
||||
load_workspace_fairness_enabled, load_workspace_fairness_max_percent,
|
||||
load_workspace_fairness_min_total, load_workspace_max_queued_jobs, monitor_db,
|
||||
reload_app_workspaced_route_setting, reload_audit_log_retention_days_setting,
|
||||
reload_base_url_setting, reload_bun_install_min_release_age_setting,
|
||||
reload_bunfig_install_scopes_setting, reload_critical_alert_mute_ui_setting,
|
||||
reload_critical_alert_mute_zombie_job_restart_setting,
|
||||
reload_critical_alerts_on_token_expiry_setting, reload_critical_error_channels_setting,
|
||||
reload_extra_pip_index_url_setting, reload_http_route_default_allowed_origins_setting,
|
||||
reload_http_route_workspaced_route_setting,
|
||||
reload_hub_api_secret_setting, reload_hub_base_url_setting,
|
||||
reload_instance_events_webhook_setting, reload_job_default_timeout_setting,
|
||||
reload_job_isolation_setting, reload_jwt_secret_setting, reload_license_key,
|
||||
reload_npm_config_registry_setting, reload_nsjail_tmp_backing_setting,
|
||||
reload_http_route_workspaced_route_setting, reload_hub_api_secret_setting,
|
||||
reload_hub_base_url_setting, reload_instance_events_webhook_setting,
|
||||
reload_job_default_timeout_setting, reload_job_isolation_setting, reload_jwt_secret_setting,
|
||||
reload_license_key, reload_npm_config_registry_setting, reload_nsjail_tmp_backing_setting,
|
||||
reload_nsjail_tmpfs_size_setting, reload_otel_traces_retention_secs_setting,
|
||||
reload_otel_tracing_proxy_setting, reload_pip_index_url_setting,
|
||||
reload_retention_period_setting, reload_sandbox_image_cache_max_setting,
|
||||
@@ -423,7 +421,6 @@ struct HubResourceTypeRaw {
|
||||
pub display_name: Option<Option<String>>,
|
||||
}
|
||||
|
||||
|
||||
/// Processed resource type with parsed schema
|
||||
#[derive(serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct HubResourceType {
|
||||
@@ -1889,12 +1886,10 @@ async fn process_notify_event(
|
||||
);
|
||||
windmill_common::workspaces::PUBLIC_APP_RATE_LIMIT_CACHE.remove(payload);
|
||||
}
|
||||
windmill_common::SCRIPT_VERSION_DELETED_CHANNEL => {
|
||||
match serde_json::from_str(payload) {
|
||||
Ok(deleted) => windmill_api_scripts::scripts::evict_deleted_script_versions(deleted),
|
||||
Err(e) => tracing::error!("Invalid script version deletion payload {payload}: {e}"),
|
||||
}
|
||||
}
|
||||
windmill_common::SCRIPT_VERSION_DELETED_CHANNEL => match serde_json::from_str(payload) {
|
||||
Ok(deleted) => windmill_api_scripts::scripts::evict_deleted_script_versions(deleted),
|
||||
Err(e) => tracing::error!("Invalid script version deletion payload {payload}: {e}"),
|
||||
},
|
||||
"notify_runnable_version_change" => {
|
||||
tracing::info!("Runnable version change detected: {}", payload);
|
||||
match payload.split(':').collect::<Vec<&str>>().as_slice() {
|
||||
@@ -2055,6 +2050,11 @@ async fn process_notify_event(
|
||||
tracing::error!("Error loading preview tags override: {e:#}");
|
||||
}
|
||||
}
|
||||
DEPENDENCY_JOB_TAG_SETTING => {
|
||||
if let Err(e) = load_dependency_job_tag(db).await {
|
||||
tracing::error!("Error loading dependency job tag: {e:#}");
|
||||
}
|
||||
}
|
||||
WORKSPACE_FAIRNESS_ENABLED_SETTING => {
|
||||
if let Err(e) = load_workspace_fairness_enabled(db).await {
|
||||
tracing::error!("Error loading workspace fairness enabled: {e:#}");
|
||||
|
||||
+37
-16
@@ -60,17 +60,17 @@ use windmill_common::{
|
||||
CRITICAL_ALERTS_ON_DB_OVERSIZE_SETTING, CRITICAL_ALERTS_ON_TOKEN_EXPIRY_SETTING,
|
||||
CRITICAL_ALERT_MUTE_UI_SETTING, CRITICAL_ALERT_MUTE_ZOMBIE_JOB_RESTART_SETTING,
|
||||
CRITICAL_ERROR_CHANNELS_SETTING, CUSTOM_TAGS_SETTING, DEFAULT_TAGS_PER_WORKSPACE_SETTING,
|
||||
DEFAULT_TAGS_WORKSPACES_SETTING, DISABLE_PASSWORD_LOGIN, DISABLE_PASSWORD_LOGIN_SETTING,
|
||||
EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING, EXTRA_PIP_INDEX_URL_SETTING,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING, HUB_API_SECRET_SETTING,
|
||||
HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING,
|
||||
JOB_ISOLATION_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING,
|
||||
MCP_DISABLE_TOKEN_QUERY_PARAM, MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING,
|
||||
MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING, NPM_CONFIG_REGISTRY_SETTING,
|
||||
NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING, NUGET_CONFIG_SETTING,
|
||||
OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING, OTEL_TRACING_PROXY_SETTING,
|
||||
PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING,
|
||||
PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
|
||||
DEFAULT_TAGS_WORKSPACES_SETTING, DEPENDENCY_JOB_TAG_SETTING, DISABLE_PASSWORD_LOGIN,
|
||||
DISABLE_PASSWORD_LOGIN_SETTING, EXPOSE_DEBUG_METRICS_SETTING, EXPOSE_METRICS_SETTING,
|
||||
EXTRA_PIP_INDEX_URL_SETTING, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
|
||||
HUB_API_SECRET_SETTING, HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING,
|
||||
JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING,
|
||||
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MCP_DISABLE_TOKEN_QUERY_PARAM,
|
||||
MCP_DISABLE_TOKEN_QUERY_PARAM_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING,
|
||||
NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING, NSJAIL_TMP_BACKING_SETTING,
|
||||
NUGET_CONFIG_SETTING, OTEL_SETTING, OTEL_TRACES_RETENTION_SECS_SETTING,
|
||||
OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING,
|
||||
POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING,
|
||||
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
|
||||
SAML_METADATA_SETTING, SANDBOX_IMAGE_CACHE_MAX_MB_SETTING,
|
||||
SANDBOX_IMAGE_DEFAULT_REGISTRY_SETTING, SANDBOX_IMAGE_MAX_SIZE_MB_SETTING,
|
||||
@@ -93,11 +93,11 @@ use windmill_common::{
|
||||
load_periodic_bash_script_interval_from_env, load_whitelist_env_vars_from_env,
|
||||
load_worker_config, store_pull_query, store_suspended_pull_query, Connection, WorkerConfig,
|
||||
CLOUD_HOSTED, CONCURRENCY_KEY_MAX_QUEUED, CONCURRENCY_KEY_MAX_QUEUED_DEFAULT,
|
||||
DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX,
|
||||
INDEXER_CONFIG, PREVIEW_TAGS_OVERRIDE, SMTP_CONFIG, WINDMILL_DIR, WORKER_CONFIG,
|
||||
WORKER_GROUP, WORKSPACE_FAIRNESS_DURATION_SECS, WORKSPACE_FAIRNESS_ENABLED,
|
||||
WORKSPACE_FAIRNESS_MAX_PERCENT, WORKSPACE_FAIRNESS_MIN_TOTAL, WORKSPACE_MAX_QUEUED_JOBS,
|
||||
WORKSPACE_MAX_QUEUED_JOBS_DEFAULT,
|
||||
DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, DEPENDENCY_JOB_TAG,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX, INDEXER_CONFIG, PREVIEW_TAGS_OVERRIDE, SMTP_CONFIG,
|
||||
WINDMILL_DIR, WORKER_CONFIG, WORKER_GROUP, WORKSPACE_FAIRNESS_DURATION_SECS,
|
||||
WORKSPACE_FAIRNESS_ENABLED, WORKSPACE_FAIRNESS_MAX_PERCENT, WORKSPACE_FAIRNESS_MIN_TOTAL,
|
||||
WORKSPACE_MAX_QUEUED_JOBS, WORKSPACE_MAX_QUEUED_JOBS_DEFAULT,
|
||||
},
|
||||
KillpillSender, AUDIT_LOG_RETENTION_DAYS, BASE_URL, CRITICAL_ALERTS_ON_DB_OVERSIZE,
|
||||
CRITICAL_ALERTS_ON_TOKEN_EXPIRY, CRITICAL_ALERT_MUTE_UI_ENABLED,
|
||||
@@ -312,6 +312,9 @@ pub async fn initial_load(
|
||||
pass.setting(PREVIEW_TAGS_OVERRIDE_SETTING, false, |v| async move {
|
||||
apply_preview_tags_override(v)
|
||||
});
|
||||
pass.setting(DEPENDENCY_JOB_TAG_SETTING, false, |v| async move {
|
||||
apply_dependency_job_tag(v)
|
||||
});
|
||||
|
||||
// Load per-workspace retention overrides before the first cleanup tick so a fresh server
|
||||
// never sweeps globally without honoring configured longer-retention workspaces.
|
||||
@@ -876,6 +879,24 @@ pub fn apply_preview_tags_override(value: Option<serde_json::Value>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn load_dependency_job_tag(db: &DB) -> error::Result<()> {
|
||||
let v = load_value_from_global_settings(db, DEPENDENCY_JOB_TAG_SETTING).await?;
|
||||
apply_dependency_job_tag(v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_dependency_job_tag(value: Option<serde_json::Value>) {
|
||||
let tag = match value {
|
||||
Some(serde_json::Value::String(t)) if !t.trim().is_empty() => Some(t.trim().to_string()),
|
||||
None | Some(serde_json::Value::Null) | Some(serde_json::Value::String(_)) => None,
|
||||
Some(other) => {
|
||||
tracing::error!("{DEPENDENCY_JOB_TAG_SETTING} is not a string: {other}, ignoring");
|
||||
return;
|
||||
}
|
||||
};
|
||||
DEPENDENCY_JOB_TAG.store(std::sync::Arc::new(tag));
|
||||
}
|
||||
|
||||
// Upper bound on the duration window. Postgres `make_interval(secs => $1::int4)` is the consumer
|
||||
// downstream, so this stays comfortably below `i32::MAX` and the subsequent `u32 -> i32` cast in
|
||||
// `workspace_fairness::refresh_overloaded` cannot wrap into a negative interval (which would
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
//! Sets the process-wide `DEPENDENCY_JOB_TAG`, so it lives in its own test binary: any other
|
||||
//! test queuing a dependency job in the same process would land on the overridden tag.
|
||||
|
||||
use sqlx::{Pool, Postgres};
|
||||
use windmill_common::worker::DEPENDENCY_JOB_TAG;
|
||||
use windmill_dep_map::scoped_dependency_map::DependencyDependent;
|
||||
|
||||
#[sqlx::test(fixtures("base"))]
|
||||
async fn relocks_go_to_the_configured_dependency_job_tag(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
DEPENDENCY_JOB_TAG.store(std::sync::Arc::new(Some("deps-$workspace".to_string())));
|
||||
|
||||
for (path, hash, tag) in [
|
||||
("f/tags/tagged", 7_100_001_i64, Some("default-$workspace")),
|
||||
("f/tags/plain", 7_100_002_i64, None),
|
||||
] {
|
||||
sqlx::query(
|
||||
"INSERT INTO script(workspace_id, created_by, content, schema, summary, description, path, hash, language, tag)
|
||||
VALUES ('test-workspace', 'test-user', 'def main(): pass', '{}', '', '', $1, $2, 'python3', $3)",
|
||||
)
|
||||
.bind(path)
|
||||
.bind(hash)
|
||||
.bind(tag)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
}
|
||||
let importers = ["f/tags/tagged", "f/tags/plain"]
|
||||
.map(|p| DependencyDependent {
|
||||
importer_path: p.to_string(),
|
||||
importer_kind: "script".to_string(),
|
||||
importer_node_ids: None,
|
||||
})
|
||||
.to_vec();
|
||||
windmill_dep_map::trigger_dependents::trigger_dependents_to_recompute_dependencies(
|
||||
"test-workspace",
|
||||
importers,
|
||||
None,
|
||||
None,
|
||||
"test@windmill.dev",
|
||||
"test-user",
|
||||
"u/test-user",
|
||||
&db,
|
||||
vec![],
|
||||
)
|
||||
.await?;
|
||||
|
||||
let tags: Vec<(String, String)> = sqlx::query_as(
|
||||
"SELECT runnable_path, tag FROM v2_job WHERE kind = 'dependencies' ORDER BY runnable_path",
|
||||
)
|
||||
.fetch_all(&db)
|
||||
.await?;
|
||||
assert_eq!(
|
||||
tags,
|
||||
vec![
|
||||
(
|
||||
"f/tags/plain".to_string(),
|
||||
"deps-test-workspace".to_string()
|
||||
),
|
||||
(
|
||||
"f/tags/tagged".to_string(),
|
||||
"deps-test-workspace".to_string()
|
||||
),
|
||||
]
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.820.0
|
||||
version: 1.821.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
|
||||
@@ -9,6 +9,7 @@ pub const DEFAULT_TAGS_WORKSPACES_SETTING: &str = "default_tags_workspaces";
|
||||
pub const FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING: &str =
|
||||
"fork_workspace_tag_append_fork_suffix";
|
||||
pub const PREVIEW_TAGS_OVERRIDE_SETTING: &str = "preview_tags_override";
|
||||
pub const DEPENDENCY_JOB_TAG_SETTING: &str = "dependency_job_tag";
|
||||
pub const BASE_URL_SETTING: &str = "base_url";
|
||||
pub const WS_BASE_URL_SETTING: &str = "ws_base_url";
|
||||
pub const OAUTH_SETTING: &str = "oauths";
|
||||
|
||||
@@ -275,6 +275,8 @@ pub struct GlobalSettings {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auto_build_binary_tag: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub dependency_job_tag: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ws_base_url: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub github_app_webhook_base_url: Option<String>,
|
||||
|
||||
@@ -28,7 +28,9 @@ use crate::utils::StripPath;
|
||||
/// `push`'s default (the language tag). Every relock of a script must use this, or a relock
|
||||
/// lands on a worker pool other than the one its deploy locked on and resolves packages
|
||||
/// differently.
|
||||
/// Dedicated workers are handled by `push`, which gives `dedicated_worker` precedence.
|
||||
/// Dedicated workers are handled by `push`, which gives `dedicated_worker` precedence. Below
|
||||
/// that, `push` replaces this result with the instance's `dependency_job_tag` setting when it is
|
||||
/// set, except for bunnative.
|
||||
pub fn dependency_job_tag(tag: Option<String>, language: &ScriptLang) -> Option<String> {
|
||||
if tag.as_ref().is_some_and(|x| x.contains("$args[")) {
|
||||
None
|
||||
|
||||
@@ -450,6 +450,7 @@ lazy_static::lazy_static! {
|
||||
pub static ref DEFAULT_TAGS_WORKSPACES: arc_swap::ArcSwap<Option<Vec<String>>> = arc_swap::ArcSwap::from_pointee(None);
|
||||
pub static ref FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX: AtomicBool = AtomicBool::new(false);
|
||||
pub static ref PREVIEW_TAGS_OVERRIDE: AtomicBool = AtomicBool::new(false);
|
||||
pub static ref DEPENDENCY_JOB_TAG: arc_swap::ArcSwap<Option<String>> = arc_swap::ArcSwap::from_pointee(None);
|
||||
|
||||
pub static ref MAX_TIMEOUT: u64 = std::env::var("TIMEOUT")
|
||||
.ok()
|
||||
|
||||
@@ -81,9 +81,9 @@ use windmill_common::{
|
||||
users::{SUPERADMIN_NOTIFICATION_EMAIL, SUPERADMIN_SECRET_EMAIL},
|
||||
utils::{not_found_if_none, report_critical_error, StripPath, WarnAfterExt},
|
||||
worker::{
|
||||
to_raw_value, CLOUD_HOSTED, DISABLE_FLOW_SCRIPT, NO_LOGS, PREVIEW_TAGS_OVERRIDE,
|
||||
WORKER_PULL_QUERIES, WORKER_PULL_QUERIES_FAIRNESS, WORKER_SUSPENDED_PULL_QUERY,
|
||||
WORKSPACE_FAIRNESS_OVERLOADED,
|
||||
to_raw_value, CLOUD_HOSTED, DEPENDENCY_JOB_TAG, DISABLE_FLOW_SCRIPT, NO_LOGS,
|
||||
PREVIEW_TAGS_OVERRIDE, WORKER_PULL_QUERIES, WORKER_PULL_QUERIES_FAIRNESS,
|
||||
WORKER_SUSPENDED_PULL_QUERY, WORKSPACE_FAIRNESS_OVERLOADED,
|
||||
},
|
||||
DB, METRICS_ENABLED,
|
||||
};
|
||||
@@ -4611,15 +4611,27 @@ pub async fn pull(
|
||||
&& !(job.kind.is_preview()
|
||||
&& PREVIEW_TAGS_OVERRIDE.load(std::sync::atomic::Ordering::Relaxed))
|
||||
{
|
||||
let effective_ws = per_workspace_tag(&job.workspace_id, db).await;
|
||||
let base_tag = if job.is_flow() {
|
||||
"flow".to_string()
|
||||
} else {
|
||||
"dependency".to_string()
|
||||
};
|
||||
let tag = match &effective_ws {
|
||||
Some(ws) => format!("{}-{}", base_tag, ws),
|
||||
None => base_tag,
|
||||
let tag = match configured_dependency_job_tag(
|
||||
&job.kind,
|
||||
job.script_lang.as_ref(),
|
||||
&job.workspace_id,
|
||||
db,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Some(tag) => tag,
|
||||
None => {
|
||||
let effective_ws = per_workspace_tag(&job.workspace_id, db).await;
|
||||
let base_tag = if job.is_flow() {
|
||||
"flow".to_string()
|
||||
} else {
|
||||
"dependency".to_string()
|
||||
};
|
||||
match &effective_ws {
|
||||
Some(ws) => format!("{}-{}", base_tag, ws),
|
||||
None => base_tag,
|
||||
}
|
||||
}
|
||||
};
|
||||
sqlx::query!(
|
||||
"UPDATE v2_job_queue SET tag = $1, running = false WHERE id = $2",
|
||||
@@ -5267,6 +5279,24 @@ pub async fn resolve_push_tag(
|
||||
Some(interpolate_args(tag.to_string(), args, &tag_ws))
|
||||
}
|
||||
|
||||
/// The tag a dependency job is routed to when the instance's `dependency_job_tag` setting is
|
||||
/// set, whatever tag the script, flow or app itself runs on. `None` for any other job kind, for
|
||||
/// bunnative (its bundle must be built on a worker with the bun tag), or when the setting is
|
||||
/// unset.
|
||||
pub async fn configured_dependency_job_tag(
|
||||
job_kind: &JobKind,
|
||||
language: Option<&ScriptLang>,
|
||||
workspace_id: &str,
|
||||
db: &DB,
|
||||
) -> Option<String> {
|
||||
if !job_kind.is_dependency() || language == Some(&ScriptLang::Bunnative) {
|
||||
return None;
|
||||
}
|
||||
let tag = DEPENDENCY_JOB_TAG.load_full();
|
||||
let tag = tag.as_deref()?;
|
||||
resolve_push_tag(tag, &PushArgs::from(&HashMap::new()), workspace_id, db).await
|
||||
}
|
||||
|
||||
/// Refuses a `tag` the caller chose that the instance's custom tags do not let `w_id` use,
|
||||
/// judging the queue it resolves to. `args` must be the ones the job is pushed with: resolving
|
||||
/// with any others checks a queue the job does not land on.
|
||||
@@ -7183,6 +7213,10 @@ async fn push_inner<'c, 'd>(
|
||||
runnable_path.clone().expect("dedicated script has a path")
|
||||
);
|
||||
windmill_common::worker::dedicated_worker_tag(workspace_id, &full_path)
|
||||
} else if let Some(tag) =
|
||||
configured_dependency_job_tag(&job_kind, language.as_ref(), workspace_id, db).await
|
||||
{
|
||||
tag
|
||||
} else {
|
||||
let interpolated_tag = match tag {
|
||||
Some(x) => resolve_push_tag(&x, &args, workspace_id, db).await,
|
||||
|
||||
@@ -101,6 +101,7 @@ mappable-rc.workspace = true
|
||||
git-version.workspace = true
|
||||
once_cell.workspace = true
|
||||
tokio-postgres.workspace = true
|
||||
postgres-protocol.workspace = true
|
||||
bit-vec.workspace = true
|
||||
url.workspace = true
|
||||
async-stream.workspace = true
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::net::IpAddr;
|
||||
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -362,6 +361,79 @@ fn wrap_param_encoding_error(
|
||||
to_anyhow(err).into()
|
||||
}
|
||||
|
||||
/// Whether a statement may return a row stream, and so needs its column types described
|
||||
/// before it runs. Anything not recognised as returning at most a row counts as a stream:
|
||||
/// a wrong guess only costs a round trip, while a missed stream can hang the job.
|
||||
fn can_stream_rows(query: &str) -> bool {
|
||||
let Some(keyword) = leading_keyword(query) else {
|
||||
return true;
|
||||
};
|
||||
let rowless = matches!(
|
||||
keyword.as_str(),
|
||||
"insert"
|
||||
| "update"
|
||||
| "delete"
|
||||
| "merge"
|
||||
| "create"
|
||||
| "alter"
|
||||
| "drop"
|
||||
| "truncate"
|
||||
| "grant"
|
||||
| "revoke"
|
||||
| "comment"
|
||||
| "set"
|
||||
| "reset"
|
||||
| "call"
|
||||
| "do"
|
||||
| "begin"
|
||||
| "commit"
|
||||
| "rollback"
|
||||
| "lock"
|
||||
| "vacuum"
|
||||
| "analyze"
|
||||
| "refresh"
|
||||
);
|
||||
!rowless || query.to_ascii_lowercase().contains("returning")
|
||||
}
|
||||
|
||||
/// The first keyword of a statement, past whitespace and comments, following Postgres's
|
||||
/// scanner: a `--` comment ends at CR or LF, and block comments nest, so
|
||||
/// `/* /* a */ INSERT */ SELECT` starts with SELECT. `None` when the comments never end.
|
||||
fn leading_keyword(query: &str) -> Option<String> {
|
||||
let mut rest = query;
|
||||
loop {
|
||||
rest = rest.trim_start();
|
||||
if let Some(after) = rest.strip_prefix("--") {
|
||||
rest = &after[after.find(['\n', '\r'])?..];
|
||||
} else if rest.starts_with("/*") {
|
||||
let mut depth = 0usize;
|
||||
let mut i = 0;
|
||||
let bytes = rest.as_bytes();
|
||||
loop {
|
||||
match bytes.get(i..i + 2)? {
|
||||
b"/*" => depth += 1,
|
||||
b"*/" => depth -= 1,
|
||||
_ => {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
i += 2;
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rest = &rest[i..];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let end = rest
|
||||
.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_' || c == '$'))
|
||||
.unwrap_or(rest.len());
|
||||
Some(rest[..end].to_ascii_lowercase())
|
||||
}
|
||||
|
||||
fn otyp_to_pg_type(otyp: &str) -> error::Result<Type> {
|
||||
let base = otyp.trim_end_matches("[]");
|
||||
let is_array = otyp.ends_with("[]");
|
||||
@@ -510,15 +582,25 @@ fn do_postgresql_inner<'a>(
|
||||
let result_f = async move {
|
||||
let mut res: Vec<Box<serde_json::value::RawValue>> = vec![];
|
||||
|
||||
// Always prefer query_typed_raw (unnamed prepared statement). It is sent as
|
||||
// a single Parse+Bind+Execute+Sync round-trip, so it survives transaction-mode
|
||||
// connection poolers (PgBouncer/Supabase pooler/RDS Proxy) where named
|
||||
// Always prefer query_typed_raw (unnamed prepared statement). It and its
|
||||
// describe are each a self-contained round-trip ending in Sync, so they
|
||||
// survive transaction-mode connection poolers (PgBouncer/Supabase
|
||||
// pooler/RDS Proxy) where named
|
||||
// statements ("s0", "s1", ...) can be reported missing because the prepare
|
||||
// and the execute land on different backend connections. Fall back to
|
||||
// prepare + query_raw only when an arg has a type unsupported by
|
||||
// otyp_to_pg_type (e.g. custom enum, geometry, …) — in that case we lose
|
||||
// pooler safety, but the query at least runs against a direct connection.
|
||||
let rows = if all_types_resolved {
|
||||
// query_typed_raw looks up result column types this connection has not seen
|
||||
// (enums, domains, extension types) while the rows already stream, and on a
|
||||
// large result that lookup waits behind them forever. Describing first resolves
|
||||
// them up front, still without a named statement.
|
||||
if can_stream_rows(&query) {
|
||||
if let Err(e) = client.describe_typed(&query, ¶m_types).await {
|
||||
return Err(wrap_param_encoding_error(e, ¶m_meta, ¶m_types));
|
||||
}
|
||||
}
|
||||
let typed_params = query_params
|
||||
.iter()
|
||||
.zip(param_types.iter())
|
||||
@@ -1889,8 +1971,8 @@ pub fn pg_cell_to_json_value_with_state(
|
||||
Type::UUID => get_basic(row, column, column_i, |a: uuid::Uuid| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
})?,
|
||||
Type::INET => get_basic(row, column, column_i, |a: IpAddr| {
|
||||
Ok(JSONValue::String(a.to_string()))
|
||||
Type::INET | Type::CIDR => get_basic(row, column, column_i, |a: InetStr| {
|
||||
Ok(JSONValue::String(a.0))
|
||||
})?,
|
||||
Type::INTERVAL => get_basic(row, column, column_i, |a: IntervalStr| {
|
||||
Ok(JSONValue::String(a.0))
|
||||
@@ -1997,6 +2079,9 @@ pub fn pg_cell_to_json_value_with_state(
|
||||
Type::BYTEA_ARRAY => get_array(row, column, column_i, |a: Vec<u8>| {
|
||||
Ok(JSONValue::String(format!("\\x{}", hex::encode(a))))
|
||||
})?,
|
||||
Type::INET_ARRAY | Type::CIDR_ARRAY => get_array(row, column, column_i, |a: InetStr| {
|
||||
Ok(JSONValue::String(a.0))
|
||||
})?,
|
||||
Type::VOID => JSONValue::Null,
|
||||
// Default fallback for unhandled column types: read as text. We use
|
||||
// `AnyTextValue` instead of plain `String` so that `Kind::Enum`,
|
||||
@@ -2156,6 +2241,29 @@ fn get_array<'a, T: FromSql<'a>>(
|
||||
})
|
||||
}
|
||||
|
||||
/// `inet` / `cidr` in Postgres's own text form. `IpAddr`'s `FromSql` drops the
|
||||
/// prefix length, so a network such as `10.0.0.0/8` would read back as a host.
|
||||
struct InetStr(String);
|
||||
impl FromSql<'_> for InetStr {
|
||||
fn from_sql(
|
||||
ty: &Type,
|
||||
raw: &[u8],
|
||||
) -> Result<InetStr, Box<dyn std::error::Error + Sync + Send>> {
|
||||
let inet = postgres_protocol::types::inet_from_sql(raw)?;
|
||||
let host_prefix = if inet.addr().is_ipv4() { 32 } else { 128 };
|
||||
Ok(InetStr(
|
||||
if *ty == Type::CIDR || inet.netmask() != host_prefix {
|
||||
format!("{}/{}", inet.addr(), inet.netmask())
|
||||
} else {
|
||||
inet.addr().to_string()
|
||||
},
|
||||
))
|
||||
}
|
||||
fn accepts(ty: &Type) -> bool {
|
||||
matches!(*ty, Type::INET | Type::CIDR)
|
||||
}
|
||||
}
|
||||
|
||||
// you can remove this section if not using TS_VECTOR (or other types requiring an intermediary `FromSQL` struct)
|
||||
struct StringCollector(String);
|
||||
impl FromSql<'_> for StringCollector {
|
||||
@@ -2271,6 +2379,19 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inet_keeps_the_prefix_postgres_prints() {
|
||||
let inet = |netmask: u8, addr: [u8; 4]| {
|
||||
let mut raw = vec![2, netmask, 0, 4];
|
||||
raw.extend(addr);
|
||||
raw
|
||||
};
|
||||
let read = |ty: &Type, raw: &[u8]| InetStr::from_sql(ty, raw).unwrap().0;
|
||||
assert_eq!(read(&Type::INET, &inet(32, [10, 1, 2, 3])), "10.1.2.3");
|
||||
assert_eq!(read(&Type::INET, &inet(8, [10, 0, 0, 0])), "10.0.0.0/8");
|
||||
assert_eq!(read(&Type::CIDR, &inet(32, [10, 1, 2, 3])), "10.1.2.3/32");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_naive_date() {
|
||||
// chrono's NaiveDate::to_string() format
|
||||
@@ -2472,6 +2593,39 @@ mod tests {
|
||||
windmill_parser_sql::parse_pg_typ(arg_t)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_rowless_statements_skip_the_describe() {
|
||||
for q in [
|
||||
"SELECT * FROM t",
|
||||
"-- $1 n (int)\nselect $1",
|
||||
"WITH x AS (DELETE FROM t RETURNING *) SELECT * FROM x",
|
||||
"INSERT INTO t VALUES (1) RETURNING id",
|
||||
"/* c */ UPDATE t SET a = 1\nreturning *",
|
||||
"UPDATE t SET note = $$a;b$$ RETURNING *",
|
||||
"/* /* inner */ INSERT */ SELECT * FROM t",
|
||||
"/* never closed INSERT",
|
||||
"-- INSERT",
|
||||
"-- header\rSELECT m, pad AS\nupdate FROM t",
|
||||
"insert_rows()",
|
||||
"TABLE t",
|
||||
"VALUES (1)",
|
||||
"EXPLAIN SELECT 1",
|
||||
] {
|
||||
assert!(can_stream_rows(q), "{q}");
|
||||
}
|
||||
for q in [
|
||||
"INSERT INTO t VALUES (1)",
|
||||
"-- $1 n (int)\nUPDATE t SET a = $1",
|
||||
"delete from t",
|
||||
"CREATE TABLE t (a int)",
|
||||
"SET search_path TO x",
|
||||
"CALL p()",
|
||||
"/* a /* b */ c */\n-- d\nINSERT INTO t VALUES (1)",
|
||||
] {
|
||||
assert!(!can_stream_rows(q), "{q}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_val_null_for_every_known_arg_t() {
|
||||
// `Value::Null` for every type the parser may resolve, plus an unknown
|
||||
|
||||
+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.820.0";
|
||||
export const VERSION = "v1.821.0";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-chat",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-chat",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@ai-sdk/react": "^4.0.102",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-chat",
|
||||
"description": "Build chat interfaces on Windmill flows deployed in chat mode, from any frontend or raw app",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache-2.0",
|
||||
"homepage": "https://github.com/windmill-labs/windmill/tree/main/chat-sdk#readme",
|
||||
|
||||
@@ -10,4 +10,4 @@ export const WM_FORK_PREFIX = "wm-fork";
|
||||
// (e.g. utils.ts) can read it without importing main.ts and creating a circular
|
||||
// dependency (main → workspace → utils → main) that triggers a TDZ.
|
||||
// Re-exported from main.ts for backwards compatibility.
|
||||
export const VERSION = "1.820.0";
|
||||
export const VERSION = "1.821.0";
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@windmill-labs/components",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@windmill-labs/components",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@windmill-labs/components",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"dev:ui-builder": "mv static/ui_builder static/ui_builder.dev-disabled 2>/dev/null || true ; trap 'mv static/ui_builder.dev-disabled static/ui_builder 2>/dev/null || true' EXIT ; vite dev",
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
DEFAULT_TAGS_PER_WORKSPACE_SETTING,
|
||||
DEFAULT_TAGS_WORKSPACES_SETTING,
|
||||
FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING,
|
||||
PREVIEW_TAGS_OVERRIDE_SETTING
|
||||
PREVIEW_TAGS_OVERRIDE_SETTING,
|
||||
DEPENDENCY_JOB_TAG_SETTING
|
||||
} from '$lib/consts'
|
||||
import TextInput from './text_input/TextInput.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
import MultiSelect from './select/MultiSelect.svelte'
|
||||
import { safeSelectItems } from './select/utils.svelte'
|
||||
@@ -31,12 +33,14 @@
|
||||
let limitToWorkspaces = $state(false)
|
||||
let previewTagsOverride = $state(false)
|
||||
let forkAppendForkSuffix = $state(false)
|
||||
let dependencyJobTag = $state('')
|
||||
|
||||
// Change detection
|
||||
let originalDefaultTagPerWorkspace = $state<boolean | undefined>(defaultTagPerWorkspace)
|
||||
let originalDefaultTagWorkspaces = $state<string[]>(defaultTagWorkspaces)
|
||||
let originalPreviewTagsOverride = $state(false)
|
||||
let originalForkAppendForkSuffix = $state(false)
|
||||
let originalDependencyJobTag = $state('')
|
||||
|
||||
// Detect changes
|
||||
let hasChanges = $derived(
|
||||
@@ -44,7 +48,8 @@
|
||||
JSON.stringify($state.snapshot(originalDefaultTagWorkspaces)?.sort() || []) !==
|
||||
JSON.stringify($state.snapshot(defaultTagWorkspaces)?.sort() || []) ||
|
||||
originalPreviewTagsOverride !== previewTagsOverride ||
|
||||
originalForkAppendForkSuffix !== forkAppendForkSuffix
|
||||
originalForkAppendForkSuffix !== forkAppendForkSuffix ||
|
||||
originalDependencyJobTag.trim() !== dependencyJobTag.trim()
|
||||
)
|
||||
|
||||
let workspaces: string[] = $state([])
|
||||
@@ -70,6 +75,11 @@
|
||||
})) as any
|
||||
forkAppendForkSuffix = forkSetting ?? false
|
||||
originalForkAppendForkSuffix = forkAppendForkSuffix
|
||||
dependencyJobTag =
|
||||
((await SettingService.getGlobal({
|
||||
key: DEPENDENCY_JOB_TAG_SETTING
|
||||
})) as any) ?? ''
|
||||
originalDependencyJobTag = dependencyJobTag
|
||||
} catch (err) {
|
||||
sendUserToast(`Could not load default tags: ${err}`, true)
|
||||
}
|
||||
@@ -104,11 +114,19 @@
|
||||
}
|
||||
})
|
||||
|
||||
await SettingService.setGlobal({
|
||||
key: DEPENDENCY_JOB_TAG_SETTING,
|
||||
requestBody: {
|
||||
value: dependencyJobTag.trim() || undefined
|
||||
}
|
||||
})
|
||||
|
||||
// Update original state after save
|
||||
originalDefaultTagPerWorkspace = defaultTagPerWorkspace
|
||||
originalDefaultTagWorkspaces = [...(defaultTagWorkspaces || [])]
|
||||
originalPreviewTagsOverride = previewTagsOverride
|
||||
originalForkAppendForkSuffix = forkAppendForkSuffix
|
||||
originalDependencyJobTag = dependencyJobTag
|
||||
|
||||
loadDefaultTags()
|
||||
sendUserToast('Saved')
|
||||
@@ -218,6 +236,33 @@
|
||||
disabled={!$enterpriseLicense}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1 max-w-md">
|
||||
<span class="text-xs font-semibold text-emphasis">Dependency job tag</span>
|
||||
<span class="text-2xs text-secondary">
|
||||
Route every dependency job (lockfile resolution at deploy and relocks triggered by an
|
||||
imported script changing, for scripts, flows and apps) to this tag, whatever tag the
|
||||
runnable itself runs on. Supports <code>$workspace</code>. Dedicated workers still build
|
||||
their own locks, and Bun native scripts still build their bundle on the bun tag.
|
||||
</span>
|
||||
<span class="text-2xs text-secondary">
|
||||
Leave empty for the default routing: a script's dependency job runs on the script's own
|
||||
tag, or on its language's default tag (e.g. <code
|
||||
>{defaultTagPerWorkspace ? 'python3-$workspace' : 'python3'}</code
|
||||
>) when it has none; flow and app dependency jobs run on
|
||||
<code>{defaultTagPerWorkspace ? 'dependency-$workspace' : 'dependency'}</code>.
|
||||
<a
|
||||
href="https://www.windmill.dev/docs/core_concepts/worker_groups"
|
||||
target="_blank"
|
||||
class="gap-1 items-baseline"
|
||||
>Worker groups <ExternalLink size={12} class="inline-block" /></a
|
||||
>
|
||||
</span>
|
||||
<TextInput
|
||||
bind:value={dependencyJobTag}
|
||||
size="sm"
|
||||
inputProps={{ placeholder: 'e.g. dependency', disabled: !$enterpriseLicense }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 items-center mb-1">
|
||||
@@ -240,6 +285,17 @@
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{#if dependencyJobTag.trim()}
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="w-36">
|
||||
<Badge color="transparent">all dependency jobs</Badge>
|
||||
</div>
|
||||
<div class="w-6 flex justify-center text-secondary">→</div>
|
||||
<div class="flex-1">
|
||||
<Badge color="blue">{dependencyJobTag.trim()}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if previewTagsOverride}
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="w-36">
|
||||
|
||||
@@ -47,6 +47,7 @@ export const DEFAULT_TAGS_PER_WORKSPACE_SETTING = 'default_tags_per_workspace'
|
||||
export const DEFAULT_TAGS_WORKSPACES_SETTING = 'default_tags_workspaces'
|
||||
export const FORK_WORKSPACE_TAG_APPEND_FORK_SUFFIX_SETTING = 'fork_workspace_tag_append_fork_suffix'
|
||||
export const PREVIEW_TAGS_OVERRIDE_SETTING = 'preview_tags_override'
|
||||
export const DEPENDENCY_JOB_TAG_SETTING = 'dependency_job_tag'
|
||||
|
||||
export const WORKSPACE_FAIRNESS_ENABLED_SETTING = 'workspace_fairness_enabled'
|
||||
export const WORKSPACE_FAIRNESS_MAX_PERCENT_SETTING = 'workspace_fairness_max_percent'
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.820.0"
|
||||
wmill = ">=1.821.0"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: '3.0.3'
|
||||
|
||||
info:
|
||||
version: 1.820.0
|
||||
version: 1.821.0
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'WindmillClient.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.820.0'
|
||||
ModuleVersion = '1.821.0'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.820.0"
|
||||
version = "1.821.0"
|
||||
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 @@
|
||||
{
|
||||
"name": "@windmill/windmill",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"exports": "./src/index.ts",
|
||||
"publish": {
|
||||
"exclude": ["!src", "./s3Types.ts", "./sqlUtils.ts", "./client.ts", "./wacError.ts"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-client",
|
||||
"description": "Windmill SDK client for browsers and Node.js",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"homepage": "https://github.com/windmill-labs/windmill/tree/main/typescript-client#readme",
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.820.0
|
||||
1.821.0
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-yaml-validator",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-yaml-validator",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"license": "Apache 2.0",
|
||||
"dependencies": {
|
||||
"@stoplight/yaml": "^4.3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-yaml-validator",
|
||||
"version": "1.820.0",
|
||||
"version": "1.821.0",
|
||||
"description": "YAML validator for Windmill flow, schedule, and trigger files",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
Reference in New Issue
Block a user