mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-23 08:03:33 +00:00
Merge remote-tracking branch 'origin/main' into di/flow-input-redesign
This commit is contained in:
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
@@ -41,13 +41,13 @@ jobs:
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
run: |
|
||||
mkdir -p fake_frontend_build
|
||||
FRONTEND_BUILD_DIR=$(pwd)/fake_frontend_build SQLX_OFFLINE=true cargo check --features $(./all_features_oss.sh)
|
||||
FRONTEND_BUILD_DIR=$(pwd)/fake_frontend_build SQLX_OFFLINE=true cargo check --features all_sqlx_features
|
||||
|
||||
check_ee:
|
||||
runs-on: ubicloud-standard-8
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
timeout-minutes: 16
|
||||
@@ -112,10 +112,10 @@ jobs:
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
- name: cargo check
|
||||
timeout-minutes: 16
|
||||
working-directory: ./backend
|
||||
run: |
|
||||
mkdir -p fake_frontend_build
|
||||
FRONTEND_BUILD_DIR=$(pwd)/fake_frontend_build SQLX_OFFLINE=true cargo check --all-features
|
||||
FRONTEND_BUILD_DIR=$(pwd)/fake_frontend_build SQLX_OFFLINE=true cargo check --features all_sqlx_features,private
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
override: true
|
||||
|
||||
- name: Substitute EE code
|
||||
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache-workspaces: backend
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
|
||||
- name: cargo check
|
||||
working-directory: ./backend
|
||||
|
||||
@@ -117,6 +117,85 @@ jobs:
|
||||
body: 'Successfully ran sqlx update'
|
||||
})
|
||||
|
||||
demo:
|
||||
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/demo')
|
||||
runs-on: ubicloud-standard-2
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Claude Code for Demo Generation
|
||||
uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
timeout_minutes: "10"
|
||||
allowed_tools: "Bash"
|
||||
direct_prompt: |
|
||||
You need to:
|
||||
|
||||
1. Extract the Cloudflare preview URL from the cloudflare-workers-and-pages bot comment in this PR
|
||||
2. Analyze the PR changes to understand what feature was added/modified
|
||||
3. Create detailed demo instructions showing how to showcase the new feature
|
||||
4. Create a demo.json file with a valid JSON object containing:
|
||||
- instructions: the demo instructions
|
||||
- url: the preview URL
|
||||
5. VALIDATE the JSON file using `jq` before finishing
|
||||
DO NOT COMMIT THIS FILE TO THE PR.
|
||||
|
||||
Example demo.json:
|
||||
{
|
||||
"instructions": "Instructions here",
|
||||
"url": "https://example.pages.dev"
|
||||
}
|
||||
|
||||
CRITICAL: After creating demo.json, you MUST:
|
||||
1. Run `jq empty demo.json` to validate the JSON is properly formatted
|
||||
2. If validation fails, fix the JSON and validate again
|
||||
3. Only proceed once the JSON passes validation
|
||||
4. Use proper JSON escaping for newlines, quotes, and special characters
|
||||
|
||||
Make sure to:
|
||||
- Create a valid JSON object that passes `jq empty demo.json`
|
||||
- Extract the correct preview URL (should be a .pages.dev domain)
|
||||
- Create specific, actionable demo steps based on the actual changes in the PR
|
||||
- Properly escape all strings in the JSON (use jq to create the file if needed)
|
||||
- NOT COMMIT THE DEMO.JSON FILE TO THE PR
|
||||
|
||||
- name: Send instructions to Windmill
|
||||
env:
|
||||
DEMO_WEBHOOK_TOKEN: ${{ secrets.DEMO_WEBHOOK_TOKEN }}
|
||||
run: |
|
||||
if [[ -f "demo.json" ]]; then
|
||||
echo "Found demo.json, sending to Windmill..."
|
||||
cat demo.json
|
||||
|
||||
# Validate JSON one more time (Claude should have already done this)
|
||||
if ! jq empty demo.json; then
|
||||
echo "Error: demo.json is not valid JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RESULT=$(curl -s \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H "Authorization: Bearer $DEMO_WEBHOOK_TOKEN" \
|
||||
-X POST \
|
||||
-d @demo.json \
|
||||
'https://app.windmill.dev/api/w/windmill-labs/jobs/run/f/f/ai/browserbase_demo')
|
||||
|
||||
echo "Windmill response:"
|
||||
echo -E "$RESULT"
|
||||
else
|
||||
echo "Error: demo.json file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
update-ee-ref:
|
||||
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/eeref')
|
||||
runs-on: ubicloud-standard-2
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Setup Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.88.0
|
||||
toolchain: 1.90.0
|
||||
override: true
|
||||
|
||||
- name: Substitute EE code
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## [1.545.0](https://github.com/windmill-labs/windmill/compare/v1.544.2...v1.545.0) (2025-09-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* force cancel in batch cancel ([2eeaf56](https://github.com/windmill-labs/windmill/commit/2eeaf5639dfcdb0114dc5fc323dbd10ef5ceaca5))
|
||||
* load for loop jobs timeline directly from for loop flow status ([#6646](https://github.com/windmill-labs/windmill/issues/6646)) ([f71f9b0](https://github.com/windmill-labs/windmill/commit/f71f9b089438fc29dfb26a21ec2b8aa5867d0296))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add termination handler earlier in lifecycle ([56cdb69](https://github.com/windmill-labs/windmill/commit/56cdb69e599e295a51284c58d6ff56498ad22fd7))
|
||||
* allow variable picker in password field ([194887e](https://github.com/windmill-labs/windmill/commit/194887e97b3250ef28b0ddf5c03932148858ca24))
|
||||
* fix flow quick picker stuck ([#6638](https://github.com/windmill-labs/windmill/issues/6638)) ([5cab802](https://github.com/windmill-labs/windmill/commit/5cab802c421c5aeda8c2b57242a4e0c4c074a5f8))
|
||||
* fix too strict aggrid coldef validation ([612d003](https://github.com/windmill-labs/windmill/commit/612d00367c2a288920c14449561433d199b95cae))
|
||||
* retry python relative imports on errno 104 ([81ff0dc](https://github.com/windmill-labs/windmill/commit/81ff0dcd8cc2fb1c5fc12a558702cbc950ca1eb4))
|
||||
* teams api improvements ([#6643](https://github.com/windmill-labs/windmill/issues/6643)) ([70e9ae1](https://github.com/windmill-labs/windmill/commit/70e9ae14a9541862aaa31b8435abb0185805d4b7))
|
||||
|
||||
## [1.544.2](https://github.com/windmill-labs/windmill/compare/v1.544.1...v1.544.2) (2025-09-18)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
ARG DEBIAN_IMAGE=debian:bookworm-slim
|
||||
ARG RUST_IMAGE=rust:1.88-slim-bookworm
|
||||
ARG RUST_IMAGE=rust:1.90-slim-bookworm
|
||||
|
||||
# Build libwindmill_duckdb_ffi_internal.so separately
|
||||
FROM ${RUST_IMAGE} AS windmill_duckdb_ffi_internal_builder
|
||||
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET flow_status = \n CASE WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN\n JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT],\n $4\n ),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $5),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $6)\n ELSE\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4)\n END\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0088b5bf5cf1c7e47f18c3d05cce09f3462c8e39cb3291f0d497742ad4763fa3"
|
||||
}
|
||||
+5
-5
@@ -46,11 +46,11 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET flow_status = \n CASE WHEN flow_status->'modules'->$1::int->'flow_jobs_duration' IS NOT NULL THEN\n JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status,\n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT],\n $4\n ),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $5),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $6)\n ELSE\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4)\n END\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "081f838b3dbe81631d17e7ca0751db725a7f92d4e43a86bcfa06a4ac7c70ac8f"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "VACUUM (SKIP_LOCKED) v2_job_queue, v2_job_runtime, v2_job_status, job_perms",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0cc221cb8b3059b21e6b3b4c874b8f4d32815edd2090ccb5d562a89142a7dd9c"
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT hash FROM script WHERE path = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "16e4b1bead9fc77fd98658b8cb8cc6d6bf1df758b30e99bd661da866062ef14f"
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET flow_status = \n CASE \n WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN\n JSONB_SET(\n JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status, \n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6),\n ARRAY['modules', $1::TEXT, 'iterator', 'index'], ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n )\n ELSE\n JSONB_SET(JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'iterator', 'index'],\n ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb\n ) END\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "2d0df658c31d45592dca7add8c69d06da7d81e7177a324e3f3f9af1076b3ab66"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "VACUUM v2_job_queue, v2_job_runtime, v2_job_status, job_perms",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4221d98d76f3cb32d6be581b0f63cf7578429009bee4f648e2c1bc3784fdbefc"
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO script (summary, description, dedicated_worker, content, workspace_id, path, hash, language, tag, created_by, lock) VALUES ('', '', true, $1, $2, $3, $4, $5, $6, $7, '') ON CONFLICT (workspace_id, hash) DO NOTHING",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Int8",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "script_lang",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"python3",
|
||||
"deno",
|
||||
"go",
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
"snowflake",
|
||||
"graphql",
|
||||
"powershell",
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust",
|
||||
"ansible",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java",
|
||||
"duckdb",
|
||||
"ruby"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "804fc11e35f4afc0db194b6fe2594f91df7e588d4d2431bc85f4d8734920c8bf"
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO v2_job_queue (id, workspace_id, scheduled_for, tag) SELECT unnest($1::uuid[]), $2, now(), $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray",
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "85705fc3d7f8ba5f1b12d5fb222c38fc64deb1226aab9dc3bc4465324fce37d1"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET flow_status = \n CASE \n WHEN flow_status->'modules'->$1::int->'flow_jobs_duration' IS NOT NULL THEN\n JSONB_SET(\n JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status, \n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n ELSE\n JSONB_SET(JSONB_SET(\n flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n END\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "93f00e2d164c090a959da12cbb7e4fc6e5804fea077116d339a041c0f2b0c1fa"
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO v2_job_status (id, flow_status) SELECT unnest($1::uuid[]), $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "a0b3e10e077d30c1da135dff9feca3761d400391f1f46a8294da3e6c9af63887"
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE v2_job_status SET flow_status = \n CASE \n WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN\n JSONB_SET(\n JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status, \n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5), \n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n ELSE\n JSONB_SET(JSONB_SET(\n flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),\n ARRAY['modules', $1::TEXT, 'branchall', 'branch'],\n ((flow_status->'modules'->$1::int->'branchall'->>'branch')::int + 1)::text::jsonb\n )\n END\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'branchall'->>'branch')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "a49e59c814d440bfed7d6bfc2755518225b1243a9d39ce659b95637c33d0954f"
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO v2_job (id, runnable_id, runnable_path, kind, script_lang, tag, created_by, permissioned_as, permissioned_as_email, workspace_id, raw_flow) (SELECT gen_random_uuid(), $1, $2, $3, $4, $5, $6, $7, $8, $9, $10 FROM generate_series(1, 1)) RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Varchar",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "job_kind",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"script",
|
||||
"preview",
|
||||
"flow",
|
||||
"dependencies",
|
||||
"flowpreview",
|
||||
"script_hub",
|
||||
"identity",
|
||||
"flowdependencies",
|
||||
"http",
|
||||
"graphql",
|
||||
"postgresql",
|
||||
"noop",
|
||||
"appdependencies",
|
||||
"deploymentcallback",
|
||||
"singlescriptflow",
|
||||
"flowscript",
|
||||
"flownode",
|
||||
"appscript",
|
||||
"aiagent"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Custom": {
|
||||
"name": "script_lang",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"python3",
|
||||
"deno",
|
||||
"go",
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
"snowflake",
|
||||
"graphql",
|
||||
"powershell",
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust",
|
||||
"ansible",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java",
|
||||
"duckdb",
|
||||
"ruby"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ab04cda71f8e2be9acbecabe1ee5ef756b8e5c1955fbe111df9ee171dc262338"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n UPDATE v2_job_status SET flow_status = \n JSONB_SET(JSONB_SET(JSONB_SET(JSONB_SET(\n flow_status, \n ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4), \n ARRAY['modules', $1::TEXT, 'iterator', 'index'], ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5),\n ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6)\n WHERE id = $2\n RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "int4",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Uuid",
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Jsonb"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "ac5dd4a4d7991159e053f1c11bce03a6d51c24fc9a2d8ac872aaf41a20af5045"
|
||||
}
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "b3dbdfb50ee8118bdaed3164b210cb549a34b96554ae1872355b90304f5dcb76"
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO v2_job_runtime (id) SELECT unnest($1::uuid[])",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"UuidArray"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b4a9abcb38997587b28655b0f4a212a5bd4039b57fab20b163617e33a4c9dd46"
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO v2_job (id, runnable_id, runnable_path, kind, script_lang, tag, created_by, permissioned_as, permissioned_as_email, workspace_id) (SELECT gen_random_uuid(), $1, $2, $3, $4, $5, $6, $7, $8, $9 FROM generate_series(1, $10)) RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Uuid"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Varchar",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "job_kind",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"script",
|
||||
"preview",
|
||||
"flow",
|
||||
"dependencies",
|
||||
"flowpreview",
|
||||
"script_hub",
|
||||
"identity",
|
||||
"flowdependencies",
|
||||
"http",
|
||||
"graphql",
|
||||
"postgresql",
|
||||
"noop",
|
||||
"appdependencies",
|
||||
"deploymentcallback",
|
||||
"singlescriptflow",
|
||||
"flowscript",
|
||||
"flownode",
|
||||
"appscript",
|
||||
"aiagent"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Custom": {
|
||||
"name": "script_lang",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"python3",
|
||||
"deno",
|
||||
"go",
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
"snowflake",
|
||||
"graphql",
|
||||
"powershell",
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust",
|
||||
"ansible",
|
||||
"csharp",
|
||||
"oracledb",
|
||||
"nu",
|
||||
"java",
|
||||
"duckdb",
|
||||
"ruby"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ff0403790674cdb07022af71c2377afbd8b3a660b3be27514b517c077c63c238"
|
||||
}
|
||||
Generated
+48
-47
@@ -219,9 +219,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.99"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
@@ -1923,9 +1923,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.37"
|
||||
version = "1.2.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44"
|
||||
checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@@ -2032,9 +2032,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.47"
|
||||
version = "4.5.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
|
||||
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -2042,9 +2042,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.47"
|
||||
version = "4.5.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
|
||||
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -5252,9 +5252,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
|
||||
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
@@ -11770,9 +11770,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.14.0"
|
||||
version = "3.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
|
||||
checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
@@ -11790,11 +11790,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.14.0"
|
||||
version = "3.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f"
|
||||
checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e"
|
||||
dependencies = [
|
||||
"darling 0.20.11",
|
||||
"darling 0.21.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
@@ -13480,11 +13480,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.43"
|
||||
version = "0.3.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031"
|
||||
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
@@ -13893,9 +13894,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
|
||||
dependencies = [
|
||||
"winnow 0.7.13",
|
||||
]
|
||||
@@ -15128,7 +15129,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"aws-sdk-config",
|
||||
@@ -15188,7 +15189,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -15308,7 +15309,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
@@ -15323,7 +15324,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
@@ -15336,7 +15337,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-autoscaling"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -15355,7 +15356,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -15439,7 +15440,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-git-sync"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
@@ -15454,7 +15455,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-indexer"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -15478,7 +15479,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-macros"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"lazy_static",
|
||||
@@ -15490,7 +15491,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"serde",
|
||||
@@ -15499,7 +15500,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -15511,7 +15512,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-csharp"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -15523,7 +15524,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -15535,7 +15536,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -15547,7 +15548,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-java"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -15559,7 +15560,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-nu"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"nu-parser",
|
||||
@@ -15570,7 +15571,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -15581,7 +15582,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
@@ -15593,7 +15594,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -15616,7 +15617,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ruby"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -15630,7 +15631,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-rust"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -15647,7 +15648,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -15661,7 +15662,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -15679,7 +15680,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.16",
|
||||
@@ -15704,7 +15705,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-yaml"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
@@ -15714,7 +15715,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -15747,7 +15748,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-sql-datatype-parser-wasm"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
@@ -15757,7 +15758,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-once-cell",
|
||||
|
||||
+6
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -34,7 +34,7 @@ members = [
|
||||
exclude = ["./windmill-duckdb-ffi-internal"]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -102,6 +102,10 @@ ruby = ["windmill-worker/ruby"]
|
||||
all_languages = ["python", "deno_core", "rust", "mysql", "oracledb", "duckdb", "mssql", "bigquery", "csharp", "nu", "php", "java", "ruby"]
|
||||
# For windows we have another set of languages enabled
|
||||
all_languages_windows = ["python", "deno_core", "rust", "mysql", "oracledb", "duckdb", "mssql", "bigquery", "csharp", "nu", "php", "java"]
|
||||
all_sqlx_features = ["all_languages", "enterprise", "enterprise_saml", "loki", "embedding", "parquet", "prometheus", "flow_testing",
|
||||
"openidconnect", "cloud", "jemalloc", "tantivy", "sqlx", "kafka", "nats", "otel", "dind", "websocket", "http_trigger",
|
||||
"postgres_trigger", "mcp", "mqtt_trigger", "sqs_trigger", "gcp_trigger", "smtp", "stripe",
|
||||
"license", "oauth2", "zip", "static_frontend", "scoped_cache", "agent_worker_server"]
|
||||
|
||||
[patch.crates-io]
|
||||
object_store = { git = "https://github.com/apache/arrow-rs-object-store", rev = "36752c975d4f29e20b57c91f81a10872dcd48ae7" }
|
||||
|
||||
@@ -1 +1 @@
|
||||
1dc77acb47053b2dd84569d70884456de0188290
|
||||
aa4c7936b99d0de2f7af31cde79dfc7b1b482c29
|
||||
@@ -363,11 +363,11 @@ async fn parse_python_imports_inner(
|
||||
// This way we make sure there is no multiple annotations for same script
|
||||
// and we get detailed span on conflicting versions
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
struct InlineMetadata {
|
||||
requires_python: String,
|
||||
dependencies: Vec<String>,
|
||||
}
|
||||
// #[derive(serde::Serialize, serde::Deserialize)]
|
||||
// struct InlineMetadata {
|
||||
// requires_python: String,
|
||||
// dependencies: Vec<String>,
|
||||
// }
|
||||
|
||||
let find_requirements = code.lines().find_position(|x| {
|
||||
x.starts_with("#requirements:")
|
||||
|
||||
+21
-11
@@ -300,6 +300,19 @@ async fn cache_hub_scripts(file_path: Option<String>) -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
async fn windmill_main() -> anyhow::Result<()> {
|
||||
let (killpill_tx, mut killpill_rx) = KillpillSender::new(2);
|
||||
let mut monitor_killpill_rx = killpill_tx.subscribe();
|
||||
let (killpill_phase2_tx, _killpill_phase2_rx) = tokio::sync::broadcast::channel::<()>(2);
|
||||
let server_killpill_rx = killpill_phase2_tx.subscribe();
|
||||
|
||||
let shutdown_tx = killpill_tx.clone();
|
||||
let shutdown_rx = killpill_tx.subscribe();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = windmill_common::shutdown_signal(shutdown_tx, shutdown_rx).await {
|
||||
tracing::error!("Error in shutdown signal: {e:#}");
|
||||
}
|
||||
});
|
||||
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
update_ca_certificates_if_requested();
|
||||
@@ -463,13 +476,18 @@ async fn windmill_main() -> anyhow::Result<()> {
|
||||
|
||||
if !skip_migration {
|
||||
// migration code to avoid break
|
||||
migration_handle = windmill_api::migrate_db(&db).await?;
|
||||
migration_handle = windmill_api::migrate_db(&db, killpill_rx.resubscribe()).await?;
|
||||
} else {
|
||||
tracing::info!("SKIP_MIGRATION set, skipping db migration...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if killpill_rx.try_recv().is_ok() {
|
||||
tracing::info!("Received early killpill, aborting startup");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let worker_mode = num_workers > 0;
|
||||
|
||||
let conn = if mode == Mode::Agent {
|
||||
@@ -483,14 +501,6 @@ async fn windmill_main() -> anyhow::Result<()> {
|
||||
Connection::Sql(db)
|
||||
};
|
||||
|
||||
let (killpill_tx, mut killpill_rx) = KillpillSender::new(2);
|
||||
let mut monitor_killpill_rx = killpill_tx.subscribe();
|
||||
let (killpill_phase2_tx, _killpill_phase2_rx) = tokio::sync::broadcast::channel::<()>(2);
|
||||
let server_killpill_rx = killpill_phase2_tx.subscribe();
|
||||
|
||||
let shutdown_signal =
|
||||
windmill_common::shutdown_signal(killpill_tx.clone(), killpill_tx.subscribe());
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
tracing::info!(
|
||||
"
|
||||
@@ -1257,10 +1267,9 @@ Windmill Community Edition {GIT_VERSION}
|
||||
}
|
||||
|
||||
if mcp_mode {
|
||||
futures::try_join!(shutdown_signal, workers_f, server_f)?;
|
||||
futures::try_join!(workers_f, server_f)?;
|
||||
} else {
|
||||
futures::try_join!(
|
||||
shutdown_signal,
|
||||
workers_f,
|
||||
monitor_f,
|
||||
server_f,
|
||||
@@ -1285,6 +1294,7 @@ Windmill Community Edition {GIT_VERSION}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::process::exit(0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ if [[ "$(uname)" == "Darwin" ]]; then
|
||||
sed -i '' 's/^# \(samael = { git="https:\/\/github.com\/njaremko\/samael", rev="464d015e3ae393e4b5dd00b4d6baa1b617de0dd6", features = \["xmlsec"\] }\)/\1/' Cargo.toml
|
||||
fi
|
||||
|
||||
cargo sqlx prepare --workspace -- --all-targets --all-features
|
||||
cargo sqlx prepare --workspace -- --all-targets --features all_sqlx_features,private
|
||||
|
||||
# Undo the samael changes on macOS
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.544.2
|
||||
version: 1.545.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
@@ -7727,6 +7727,10 @@ paths:
|
||||
- job
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- name: force_cancel
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
requestBody:
|
||||
description: uuids of the jobs to cancel
|
||||
required: true
|
||||
@@ -18318,17 +18322,6 @@ components:
|
||||
- script_path
|
||||
- git_repo_resource_path
|
||||
|
||||
UploadFilePart:
|
||||
type: object
|
||||
properties:
|
||||
part_number:
|
||||
type: integer
|
||||
tag:
|
||||
type: string
|
||||
required:
|
||||
- part_number
|
||||
- tag
|
||||
|
||||
MetricMetadata:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -147,14 +147,14 @@ fn is_false(b: &bool) -> bool {
|
||||
!b
|
||||
}
|
||||
|
||||
#[derive(FromRow, Serialize, Deserialize)]
|
||||
pub struct AppVersion {
|
||||
pub id: i64,
|
||||
pub app_id: Uuid,
|
||||
pub value: sqlx::types::Json<Box<RawValue>>,
|
||||
pub created_by: String,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
// #[derive(FromRow, Serialize, Deserialize)]
|
||||
// pub struct AppVersion {
|
||||
// pub id: i64,
|
||||
// pub app_id: Uuid,
|
||||
// pub value: sqlx::types::Json<Box<RawValue>>,
|
||||
// pub created_by: String,
|
||||
// pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
||||
pub struct AppWithLastVersion {
|
||||
@@ -180,15 +180,6 @@ pub struct AppWithLastVersionAndStarred {
|
||||
pub starred: Option<bool>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
#[derive(Debug, Serialize, FromRow)]
|
||||
pub struct AppWithLastVersionAndWorkspace {
|
||||
#[sqlx(flatten)]
|
||||
#[serde(flatten)]
|
||||
pub app: AppWithLastVersion,
|
||||
pub workspace_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, FromRow)]
|
||||
pub struct AppWithLastVersionAndDraft {
|
||||
#[sqlx(flatten)]
|
||||
|
||||
@@ -101,14 +101,20 @@ impl Migrate for CustomMigrator {
|
||||
let mut r = false;
|
||||
|
||||
while !r {
|
||||
r = sqlx::query_scalar!("SELECT pg_try_advisory_lock($1)", lock_id)
|
||||
.fetch_one(&mut *self.inner)
|
||||
r = match tokio::time::timeout(std::time::Duration::from_secs(5), sqlx::query_scalar!("SELECT pg_try_advisory_lock($1)", lock_id)
|
||||
.fetch_one(&mut *self.inner))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Error acquiring lock: {e:#}");
|
||||
sqlx::migrate::MigrateError::Execute(e)
|
||||
})?
|
||||
.unwrap_or(false);
|
||||
{
|
||||
Ok(Ok(r)) => r.unwrap_or(false),
|
||||
Ok(Err(e)) => {
|
||||
tracing::error!("Error acquiring lock: {e:#}");
|
||||
return Err(sqlx::migrate::MigrateError::Execute(e));
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Timed out acquiring lock retrying in 5s: {e:#}");
|
||||
false
|
||||
}
|
||||
};
|
||||
if !r {
|
||||
tracing::info!("PG migration lock already acquired by another server or worker, a migration is in progress, this may take a long time if you have many jobs and be normal, rechecking in 5s.");
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
@@ -196,7 +202,10 @@ impl Migrate for CustomMigrator {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn migrate(db: &DB) -> Result<Option<JoinHandle<()>>, Error> {
|
||||
pub async fn migrate(
|
||||
db: &DB,
|
||||
mut killpill_rx: tokio::sync::broadcast::Receiver<()>,
|
||||
) -> Result<Option<JoinHandle<()>>, Error> {
|
||||
let migrator = db.acquire().await?;
|
||||
let mut custom_migrator = CustomMigrator { inner: migrator };
|
||||
|
||||
@@ -211,20 +220,27 @@ pub async fn migrate(db: &DB) -> Result<Option<JoinHandle<()>>, Error> {
|
||||
tracing::info!("Could not remove sqlx migrations: {err:#}");
|
||||
}
|
||||
|
||||
match sqlx::migrate!("../migrations")
|
||||
.run_direct(&mut custom_migrator)
|
||||
.await
|
||||
{
|
||||
Ok(_) => Ok(()),
|
||||
Err(sqlx::migrate::MigrateError::VersionMissing(e)) => {
|
||||
tracing::error!("Database had been applied more migrations than this container.
|
||||
This usually mean than another container on a more recent version migrated the database and this one is on an earlier version.
|
||||
Please update the container to latest. Not critical, but may cause issues if migration introduced a breaking change. Version missing: {e:#}");
|
||||
custom_migrator.unlock().await?;
|
||||
Ok(())
|
||||
tokio::select! {
|
||||
_ = killpill_rx.recv() => {
|
||||
tracing::info!("Killpill received, stopping migration");
|
||||
return Ok(None);
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}?;
|
||||
migration_result = sqlx::migrate!("../migrations")
|
||||
.run_direct(&mut custom_migrator)
|
||||
=> {
|
||||
match migration_result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(sqlx::migrate::MigrateError::VersionMissing(e)) => {
|
||||
tracing::error!("Database had been applied more migrations than this container.
|
||||
This usually mean than another container on a more recent version migrated the database and this one is on an earlier version.
|
||||
Please update the container to latest. Not critical, but may cause issues if migration introduced a breaking change. Version missing: {e:#}");
|
||||
custom_migrator.unlock().await?;
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}?;
|
||||
}
|
||||
}
|
||||
|
||||
return crate::live_migrations::custom_migrations(&mut custom_migrator, db).await;
|
||||
}
|
||||
|
||||
@@ -30,15 +30,6 @@ use axum::response::Response;
|
||||
#[cfg(all(feature = "parquet", not(feature = "private")))]
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[cfg(not(feature = "private"))]
|
||||
pub struct LoadImagePreviewQuery {
|
||||
#[allow(dead_code)]
|
||||
pub file_key: String,
|
||||
#[allow(dead_code)]
|
||||
pub storage: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[cfg(not(feature = "private"))]
|
||||
pub struct DownloadFileQuery {
|
||||
|
||||
@@ -1751,6 +1751,7 @@ pub struct RunJobQuery {
|
||||
pub timeout: Option<i32>,
|
||||
pub cache_ttl: Option<i32>,
|
||||
pub skip_preprocessor: Option<bool>,
|
||||
pub poll_delay_ms: Option<u64>,
|
||||
}
|
||||
|
||||
impl RunJobQuery {
|
||||
@@ -2055,6 +2056,7 @@ async fn cancel_jobs(
|
||||
db: &DB,
|
||||
username: &str,
|
||||
w_id: &str,
|
||||
force_cancel: bool,
|
||||
) -> error::JsonResult<Vec<Uuid>> {
|
||||
let mut uuids = vec![];
|
||||
let mut tx = db.begin().await?;
|
||||
@@ -2114,7 +2116,7 @@ async fn cancel_jobs(
|
||||
w_id,
|
||||
tx,
|
||||
db,
|
||||
false,
|
||||
force_cancel,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
@@ -2145,11 +2147,17 @@ async fn cancel_jobs(
|
||||
Ok(Json(uuids))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CancelSelectionQuery {
|
||||
force_cancel: Option<bool>,
|
||||
}
|
||||
|
||||
async fn cancel_selection(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path(w_id): Path<String>,
|
||||
Query(query): Query<CancelSelectionQuery>,
|
||||
Json(jobs): Json<Vec<Uuid>>,
|
||||
) -> error::JsonResult<Vec<Uuid>> {
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
@@ -2163,7 +2171,14 @@ async fn cancel_selection(
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
cancel_jobs(jobs_to_cancel, &db, authed.username.as_str(), w_id.as_str()).await
|
||||
cancel_jobs(
|
||||
jobs_to_cancel,
|
||||
&db,
|
||||
authed.username.as_str(),
|
||||
w_id.as_str(),
|
||||
query.force_cancel.unwrap_or(false),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_filtered_job_uuids(
|
||||
@@ -5280,6 +5295,7 @@ pub async fn stream_job(
|
||||
.to_args_from_runnable(&db, &w_id, runnable_id.clone(), run_query.skip_preprocessor)
|
||||
.await?;
|
||||
|
||||
let poll_delay_ms = run_query.poll_delay_ms;
|
||||
let uuid = match runnable_id {
|
||||
RunnableId::ScriptId(ScriptId::ScriptPath(script_path))
|
||||
| RunnableId::HubScript(script_path) => {
|
||||
@@ -5349,6 +5365,7 @@ pub async fn stream_job(
|
||||
None,
|
||||
None,
|
||||
tx,
|
||||
poll_delay_ms,
|
||||
);
|
||||
|
||||
let body = axum::body::Body::from_stream(stream.map(Result::<_, std::convert::Infallible>::Ok));
|
||||
@@ -6521,6 +6538,7 @@ pub struct JobUpdateQuery {
|
||||
pub only_result: Option<bool>,
|
||||
pub fast: Option<bool>,
|
||||
pub is_flow: Option<bool>,
|
||||
pub poll_delay_ms: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
@@ -6682,6 +6700,7 @@ async fn get_job_update_sse(
|
||||
only_result,
|
||||
fast,
|
||||
is_flow,
|
||||
poll_delay_ms,
|
||||
}): Query<JobUpdateQuery>,
|
||||
) -> error::Result<Response> {
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(32);
|
||||
@@ -6701,6 +6720,7 @@ async fn get_job_update_sse(
|
||||
no_logs,
|
||||
is_flow,
|
||||
tx,
|
||||
poll_delay_ms,
|
||||
);
|
||||
|
||||
let stream = tokio_stream::wrappers::ReceiverStream::new(rx).map(|x| {
|
||||
@@ -6746,6 +6766,7 @@ fn start_job_update_sse_stream(
|
||||
no_logs: Option<bool>,
|
||||
is_flow: Option<bool>,
|
||||
tx: tokio::sync::mpsc::Sender<JobUpdateSSEStream>,
|
||||
poll_delay_ms: Option<u64>,
|
||||
) -> () {
|
||||
tokio::spawn(async move {
|
||||
let mut log_offset = initial_log_offset;
|
||||
@@ -6828,13 +6849,27 @@ fn start_job_update_sse_stream(
|
||||
|
||||
loop {
|
||||
i += 1;
|
||||
let ms_duration = if i > 100 || !fast.unwrap_or(false) {
|
||||
let mut ms_duration = if i > 100 || !fast.unwrap_or(false) {
|
||||
3000
|
||||
} else if i > 10 {
|
||||
500
|
||||
} else {
|
||||
100
|
||||
};
|
||||
|
||||
if let Some(poll_delay_ms) = poll_delay_ms {
|
||||
#[cfg(feature = "enterprise")]
|
||||
if poll_delay_ms < 50 {
|
||||
tracing::warn!("Poll delay ms is less than 50, setting it to 50");
|
||||
ms_duration = 50;
|
||||
} else {
|
||||
ms_duration = poll_delay_ms;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
tracing::warn!("Settable poll delay requires EE");
|
||||
}
|
||||
|
||||
if last_ping.elapsed().as_secs() > 5 {
|
||||
if tx.send(JobUpdateSSEStream::Ping).await.is_err() {
|
||||
tracing::warn!("Failed to send job ping for job {job_id}");
|
||||
|
||||
@@ -100,10 +100,10 @@ mod inkeep_oss;
|
||||
mod inputs;
|
||||
mod integration;
|
||||
mod live_migrations;
|
||||
pub mod openapi;
|
||||
#[cfg(all(feature = "private", feature = "parquet"))]
|
||||
pub mod s3_proxy_ee;
|
||||
mod s3_proxy_oss;
|
||||
pub mod openapi;
|
||||
|
||||
mod approvals;
|
||||
#[cfg(all(feature = "enterprise", feature = "private"))]
|
||||
@@ -155,10 +155,10 @@ pub mod stripe_ee;
|
||||
#[cfg(all(feature = "stripe", feature = "enterprise"))]
|
||||
mod stripe_oss;
|
||||
#[cfg(feature = "private")]
|
||||
pub mod teams_ee;
|
||||
#[cfg(feature = "private")]
|
||||
pub mod teams_cache_ee;
|
||||
mod teams_cache_oss;
|
||||
#[cfg(feature = "private")]
|
||||
pub mod teams_ee;
|
||||
mod teams_oss;
|
||||
mod token;
|
||||
mod tracing_init;
|
||||
@@ -696,9 +696,10 @@ pub async fn run_server(
|
||||
name.map(|x| format!("name={x}")).unwrap_or_default()
|
||||
);
|
||||
|
||||
port_tx
|
||||
.send(format!("http://localhost:{}", port))
|
||||
.expect("Failed to send port");
|
||||
if let Err(e) = port_tx.send(format!("http://localhost:{}", port)) {
|
||||
tracing::error!("Failed to send port: {e:#}");
|
||||
return Err(anyhow::anyhow!("Failed to send port, exiting early: {e:#}"));
|
||||
}
|
||||
|
||||
let server = server.with_graceful_shutdown(async move {
|
||||
killpill_rx.recv().await.ok();
|
||||
@@ -794,8 +795,11 @@ async fn openapi_json() -> Response {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn migrate_db(db: &DB) -> anyhow::Result<Option<JoinHandle<()>>> {
|
||||
db::migrate(db)
|
||||
pub async fn migrate_db(
|
||||
db: &DB,
|
||||
killpill_rx: tokio::sync::broadcast::Receiver<()>,
|
||||
) -> anyhow::Result<Option<JoinHandle<()>>> {
|
||||
db::migrate(db, killpill_rx)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Error migrating db: {e:#}"))
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ struct WorkerPing {
|
||||
wm_memory_usage: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct EnableWorkerQuery {
|
||||
disable: bool,
|
||||
}
|
||||
// #[derive(Serialize, Deserialize)]
|
||||
// struct EnableWorkerQuery {
|
||||
// disable: bool,
|
||||
// }
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ListWorkerQuery {
|
||||
|
||||
@@ -261,11 +261,11 @@ pub struct WorkspaceSettings {
|
||||
pub auto_add_instance_groups_roles: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(sqlx::Type, Serialize, Deserialize, Debug)]
|
||||
#[sqlx(type_name = "WORKSPACE_KEY_KIND", rename_all = "lowercase")]
|
||||
pub enum WorkspaceKeyKind {
|
||||
Cloud,
|
||||
}
|
||||
// #[derive(sqlx::Type, Serialize, Deserialize, Debug)]
|
||||
// #[sqlx(type_name = "WORKSPACE_KEY_KIND", rename_all = "lowercase")]
|
||||
// pub enum WorkspaceKeyKind {
|
||||
// Cloud,
|
||||
// }
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct EditCommandScript {
|
||||
@@ -1488,9 +1488,9 @@ async fn delete_git_sync_repository(
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct EditDeployUIConfig {
|
||||
#[cfg(feature = "enterprise")]
|
||||
deploy_ui_settings: Option<WorkspaceDeploymentUISettings>,
|
||||
}
|
||||
|
||||
@@ -2553,7 +2553,7 @@ async fn clone_variables(
|
||||
source_workspace_id: &str,
|
||||
target_workspace_id: &str,
|
||||
) -> Result<()> {
|
||||
sqlx::query!(
|
||||
sqlx::query!(
|
||||
"INSERT INTO variable (workspace_id, path, value, is_secret, description, extra_perms, account, is_oauth, expires_at)
|
||||
SELECT $2, path, value, is_secret, description, extra_perms, account, is_oauth, expires_at
|
||||
FROM variable
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::{spawn, sync::broadcast};
|
||||
|
||||
use ee_oss::CriticalErrorChannel;
|
||||
use error::Error;
|
||||
@@ -198,8 +198,47 @@ pub async fn shutdown_signal(
|
||||
},
|
||||
}
|
||||
|
||||
spawn(async move {
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
tokio::select! {
|
||||
_ = terminate() => {
|
||||
tracing::info!("2nd shutdown monitor received terminate");
|
||||
},
|
||||
_ = tokio::signal::ctrl_c() => {
|
||||
tracing::info!("2nd shutdown monitor received ctrl-c");
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
tokio::select! {
|
||||
_ = tokio::signal::ctrl_c() => {},
|
||||
_ = rx.recv() => {
|
||||
tracing::info!("2nd shutdown monitor received killpill");
|
||||
},
|
||||
}
|
||||
|
||||
tracing::info!("Second terminate signal received, forcefully exiting");
|
||||
|
||||
let handle = tokio::runtime::Handle::current();
|
||||
let metrics = handle.metrics();
|
||||
tracing::info!(
|
||||
"Alive tasks: {}, global queue depth: {}",
|
||||
metrics.num_alive_tasks(),
|
||||
metrics.global_queue_depth()
|
||||
);
|
||||
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
tracing::info!("signal received, starting graceful shutdown");
|
||||
let _ = tx.send();
|
||||
|
||||
spawn(async move {
|
||||
tokio::time::sleep(std::time::Duration::from_hours(24 * 7)).await;
|
||||
tracing::info!("Forcefully exiting after 7 days");
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -51,25 +51,32 @@ class WindmillFinder(MetaPathFinder):
|
||||
url = f"{os.environ.get('BASE_INTERNAL_URL')}/api/w/{os.environ.get('WM_WORKSPACE')}/scripts/raw/p/{script_path}.py{query_params}"
|
||||
|
||||
req = urllib.request.Request(url, None, headers)
|
||||
try:
|
||||
req_start = time.time()
|
||||
with urllib.request.urlopen(req) as response:
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
r = response.read().decode("utf-8")
|
||||
if r == "WINDMILL_IS_FOLDER":
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
with open(fullpath, "w+") as f:
|
||||
f.write(r)
|
||||
return ModuleSpec(name, SourceFileLoader(name, fullpath))
|
||||
except urllib.error.HTTPError as e:
|
||||
duration = time.time() - req_start
|
||||
if e.code != 404:
|
||||
print(f"Error fetching script {script_path}: HTTP {e.code} - {e.reason} - {duration}s")
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
except Exception as e:
|
||||
duration = time.time() - req_start
|
||||
print(f"Error fetching script {script_path}: {e} - {duration}s")
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
|
||||
for attempt in range(4): # 0, 1, 2, 3 = up to 3 retries
|
||||
try:
|
||||
req_start = time.time()
|
||||
with urllib.request.urlopen(req) as response:
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
r = response.read().decode("utf-8")
|
||||
if r == "WINDMILL_IS_FOLDER":
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
with open(fullpath, "w+") as f:
|
||||
f.write(r)
|
||||
return ModuleSpec(name, SourceFileLoader(name, fullpath))
|
||||
except urllib.error.HTTPError as e:
|
||||
duration = time.time() - req_start
|
||||
if e.code != 404:
|
||||
print(f"Error fetching script {script_path}: HTTP {e.code} - {e.reason} - {duration}s")
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
except Exception as e:
|
||||
duration = time.time() - req_start
|
||||
# Check if this is errno 104 (Connection reset by peer) and we have retries left
|
||||
if (hasattr(e, 'errno') and e.errno == 104) and attempt < 3:
|
||||
print(f"Connection reset (errno 104) fetching script {script_path}, retrying in 3s (attempt {attempt + 1}/3)")
|
||||
time.sleep(3)
|
||||
continue
|
||||
print(f"Error fetching script {script_path}: {e} - {duration}s")
|
||||
return ModuleSpec(name, WindmillLoader(name))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -791,6 +791,7 @@ pub fn start_interactive_worker_shell(
|
||||
|
||||
loop {
|
||||
if let Ok(_) = killpill_rx.try_recv() {
|
||||
tracing::info!("Received killpill, exiting worker shell");
|
||||
break;
|
||||
} else {
|
||||
let pulled_job = match &conn {
|
||||
@@ -2041,8 +2042,14 @@ pub async fn run_worker(
|
||||
}
|
||||
tracing::info!(worker = %worker_name, hostname = %hostname, "waiting for interactive_shell to finish");
|
||||
if let Some(interactive_shell) = interactive_shell {
|
||||
if let Err(e) = interactive_shell.await {
|
||||
tracing::error!("error in awaiting interactive_shell process: {e:?}")
|
||||
match tokio::time::timeout(Duration::from_secs(10), interactive_shell).await {
|
||||
Ok(Ok(_)) => {}
|
||||
Ok(Err(e)) => {
|
||||
tracing::error!("error in interactive_shell process: {e:?}")
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::error!("timed out awaiting interactive_shell process")
|
||||
}
|
||||
}
|
||||
}
|
||||
tracing::info!(worker = %worker_name, hostname = %hostname, "worker {} exited", worker_name);
|
||||
|
||||
@@ -526,38 +526,25 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
tracing::error!(
|
||||
"flow_job_duration: {:?}, position: {:?} flow: {:?}",
|
||||
flow_job_duration,
|
||||
position,
|
||||
flow
|
||||
);
|
||||
|
||||
let nindex = if let Some(position) = position {
|
||||
sqlx::query_scalar!(
|
||||
"UPDATE v2_job_status SET flow_status =
|
||||
CASE
|
||||
WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN
|
||||
JSONB_SET(
|
||||
JSONB_SET(JSONB_SET(JSONB_SET(
|
||||
"
|
||||
UPDATE v2_job_status SET flow_status =
|
||||
JSONB_SET(JSONB_SET(JSONB_SET(JSONB_SET(
|
||||
flow_status,
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5),
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6),
|
||||
ARRAY['modules', $1::TEXT, 'iterator', 'index'], ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb
|
||||
)
|
||||
ELSE
|
||||
JSONB_SET(JSONB_SET(flow_status, ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT], $4),
|
||||
ARRAY['modules', $1::TEXT, 'iterator', 'index'],
|
||||
((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb
|
||||
) END
|
||||
ARRAY['modules', $1::TEXT, 'iterator', 'index'], ((flow_status->'modules'->$1::int->'iterator'->>'index')::int + 1)::text::jsonb),
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'started_at', $3::TEXT], $5),
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_duration', 'duration_ms', $3::TEXT], $6)
|
||||
WHERE id = $2
|
||||
RETURNING (flow_status->'modules'->$1::int->'iterator'->>'index')::int",
|
||||
old_status.step,
|
||||
flow,
|
||||
position as i32,
|
||||
json!(success),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at)),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms))
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at)).unwrap_or_default(),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms)).unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
sqlx::query_scalar!(
|
||||
@@ -578,8 +565,7 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
Error::internal_err(format!(
|
||||
"error while fetching iterator index: {e:#}"
|
||||
))
|
||||
})?
|
||||
.ok_or_else(|| Error::internal_err(format!("requiring an index in InProgress")))?;
|
||||
})?.ok_or_else(|| Error::internal_err(format!("requiring an index in InProgress for flow {flow} at step {}", old_status.step)))?;
|
||||
|
||||
// let status_for_debug = sqlx::query!(
|
||||
// "SELECT flow_status FROM v2_job_status WHERE id = $1",
|
||||
@@ -611,7 +597,7 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
sqlx::query_scalar!(
|
||||
"UPDATE v2_job_status SET flow_status =
|
||||
CASE
|
||||
WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN
|
||||
WHEN flow_status->'modules'->$1::int->'flow_jobs_duration' IS NOT NULL THEN
|
||||
JSONB_SET(
|
||||
JSONB_SET(JSONB_SET(JSONB_SET(
|
||||
flow_status,
|
||||
@@ -634,8 +620,8 @@ pub async fn update_flow_status_after_job_completion_internal(
|
||||
flow,
|
||||
position as i32,
|
||||
json!(success),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at)),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms))
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at)).unwrap_or_default(),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms)).unwrap_or_default(),
|
||||
)
|
||||
} else {
|
||||
sqlx::query_scalar!(
|
||||
@@ -1599,7 +1585,7 @@ async fn set_success_and_duration_in_flow_job_success<'c>(
|
||||
if let Some(position) = position {
|
||||
sqlx::query!(
|
||||
"UPDATE v2_job_status SET flow_status =
|
||||
CASE WHEN flow_status->'modules'->$1::TEXT->'flow_jobs_duration' IS NOT NULL THEN
|
||||
CASE WHEN flow_status->'modules'->$1::int->'flow_jobs_duration' IS NOT NULL THEN
|
||||
JSONB_SET(JSONB_SET(JSONB_SET(
|
||||
flow_status,
|
||||
ARRAY['modules', $1::TEXT, 'flow_jobs_success', $3::TEXT],
|
||||
@@ -1615,8 +1601,8 @@ async fn set_success_and_duration_in_flow_job_success<'c>(
|
||||
flow,
|
||||
position as i32,
|
||||
json!(success),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms)),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at))
|
||||
flow_job_duration.as_ref().map(|x| json!(x.duration_ms)).unwrap_or_default(),
|
||||
flow_job_duration.as_ref().map(|x| json!(x.started_at)).unwrap_or_default()
|
||||
)
|
||||
.execute(&mut **tx)
|
||||
.await
|
||||
|
||||
@@ -308,7 +308,7 @@ pub(crate) async fn queue_vacuum(conn: &Connection, worker_name: &str, hostname:
|
||||
tokio::task::spawn(
|
||||
(async move {
|
||||
tracing::info!(worker = %worker_name, hostname = %hostname, "vacuuming queue");
|
||||
if let Err(e) = sqlx::query!("VACUUM v2_job_queue, v2_job_runtime, v2_job_status, job_perms")
|
||||
if let Err(e) = sqlx::query!("VACUUM (SKIP_LOCKED) v2_job_queue, v2_job_runtime, v2_job_status, job_perms")
|
||||
.execute(&db2)
|
||||
.await
|
||||
{
|
||||
|
||||
+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.544.2";
|
||||
export const VERSION = "v1.545.0";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export {
|
||||
// }
|
||||
// });
|
||||
|
||||
export const VERSION = "1.544.2";
|
||||
export const VERSION = "1.545.0";
|
||||
|
||||
export const WM_FORK_PREFIX = "wm-fork";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM ghcr.io/windmill-labs/windmill:dev
|
||||
|
||||
# Rust
|
||||
COPY --from=rust:1.88.0 /usr/local/cargo /usr/local/cargo
|
||||
COPY --from=rust:1.88.0 /usr/local/rustup /usr/local/rustup
|
||||
COPY --from=rust:1.90.0 /usr/local/cargo /usr/local/cargo
|
||||
COPY --from=rust:1.90.0 /usr/local/rustup /usr/local/rustup
|
||||
RUN /usr/local/cargo/bin/cargo install cargo-sweep --version ^0.7
|
||||
|
||||
# Ansible
|
||||
|
||||
@@ -20,8 +20,8 @@ RUN if [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
|
||||
FROM ghcr.io/windmill-labs/windmill-ee:dev
|
||||
|
||||
# Rust
|
||||
COPY --from=rust:1.88.0 /usr/local/cargo /usr/local/cargo
|
||||
COPY --from=rust:1.88.0 /usr/local/rustup /usr/local/rustup
|
||||
COPY --from=rust:1.90.0 /usr/local/cargo /usr/local/cargo
|
||||
COPY --from=rust:1.90.0 /usr/local/rustup /usr/local/rustup
|
||||
RUN /usr/local/cargo/bin/cargo install cargo-sweep --version ^0.7
|
||||
|
||||
# Ansible
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.544.2",
|
||||
"version": "1.545.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.544.2",
|
||||
"version": "1.545.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.544.2",
|
||||
"version": "1.545.0",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -541,7 +541,7 @@
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-col w-full rounded-md relative',
|
||||
'flex flex-col w-full rounded-md relative group',
|
||||
minW ? 'min-w-[250px]' : '',
|
||||
diffStatus?.diff ? 'px-2' : '',
|
||||
diffStatus?.diff == 'added'
|
||||
@@ -1344,19 +1344,21 @@
|
||||
bind:value
|
||||
></textarea>
|
||||
{/key}
|
||||
{#if !disabled && itemPicker && extra?.['disableVariablePicker'] != true}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<button
|
||||
class="absolute right-1 top-1 py-1 min-w-min !px-2 items-center text-gray-800 bg-surface-secondary border rounded center-center hover:bg-gray-300 transition-all cursor-pointer"
|
||||
onclick={() => {
|
||||
pickForField = label
|
||||
itemPicker?.openDrawer?.()
|
||||
}}
|
||||
title="Insert a Variable"
|
||||
>
|
||||
<DollarSign class="!text-tertiary" size={14} />
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !disabled && itemPicker && extra?.['disableVariablePicker'] != true}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<button
|
||||
class="absolute {password || extra?.['password'] == true
|
||||
? 'right-16 top-1.5'
|
||||
: 'right-1 top-1'} opacity-0 group-hover:opacity-100 duration-200 py-1 min-w-min !px-2 items-center text-gray-800 bg-surface-secondary border rounded center-center hover:bg-gray-300 transition-all cursor-pointer"
|
||||
onclick={() => {
|
||||
pickForField = label
|
||||
itemPicker?.openDrawer?.()
|
||||
}}
|
||||
title="Insert a Variable"
|
||||
>
|
||||
<DollarSign class="!text-tertiary" size={14} />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{@render variableInput()}
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
<div class="pt-4 grow">
|
||||
{#if jobId}
|
||||
<FlowStatusViewer
|
||||
bind:flowStateStore={flowStateStore.val}
|
||||
bind:flowState={flowStateStore.val}
|
||||
{jobId}
|
||||
onJobsLoaded={({ job: newJob }) => {
|
||||
job = newJob
|
||||
|
||||
@@ -583,7 +583,7 @@
|
||||
bind:suspendStatus
|
||||
hideDownloadInGraph={customUi?.downloadLogs === false}
|
||||
wideResults
|
||||
bind:flowStateStore={flowStateStore.val}
|
||||
bind:flowState={flowStateStore.val}
|
||||
{jobId}
|
||||
onDone={() => {
|
||||
isRunning = false
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
jobId: string
|
||||
initialJob?: Job | undefined
|
||||
workspaceId?: string | undefined
|
||||
flowStateStore?: FlowState
|
||||
flowState?: FlowState
|
||||
selectedJobStep?: string | undefined
|
||||
hideFlowResult?: boolean
|
||||
hideTimeline?: boolean
|
||||
@@ -39,7 +39,7 @@
|
||||
jobId,
|
||||
initialJob = undefined,
|
||||
workspaceId = undefined,
|
||||
flowStateStore = $bindable({}),
|
||||
flowState = $bindable({}),
|
||||
selectedJobStep = $bindable(undefined),
|
||||
hideFlowResult = false,
|
||||
hideTimeline = false,
|
||||
@@ -67,7 +67,7 @@
|
||||
let globalRefreshes: Record<string, ((clear, root) => Promise<void>)[]> = $state({})
|
||||
|
||||
setContext<FlowStatusViewerContext>('FlowStatusViewer', {
|
||||
flowStateStore,
|
||||
flowState: flowState,
|
||||
suspendStatus,
|
||||
retryStatus,
|
||||
hideDownloadInGraph,
|
||||
@@ -88,7 +88,7 @@
|
||||
retryStatus.val = {}
|
||||
suspendStatus.val = {}
|
||||
globalRefreshes = {}
|
||||
flowStateStore.val = {}
|
||||
flowState.val = {}
|
||||
localDurationStatuses = {}
|
||||
localModuleStates = {}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
import JobAssetsViewer from './assets/JobAssetsViewer.svelte'
|
||||
|
||||
let {
|
||||
flowStateStore,
|
||||
flowState: flowStateStore,
|
||||
retryStatus,
|
||||
suspendStatus,
|
||||
hideDownloadInGraph,
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
attempted_at: string
|
||||
} | null = $state(null)
|
||||
|
||||
|
||||
function showSetting(setting: string, values: Record<string, any>) {
|
||||
if (setting == 'dev_instance') {
|
||||
if (values['license_key'] == undefined) {
|
||||
@@ -160,18 +159,19 @@
|
||||
fetch_available_python_versions()
|
||||
}
|
||||
|
||||
|
||||
function handleTeamChange(
|
||||
teamItem: { team_id: string; team_name: string } | undefined,
|
||||
i: number
|
||||
) {
|
||||
$values['critical_error_channels'][i] = {
|
||||
teams_channel: teamItem ? {
|
||||
team_id: teamItem.team_id,
|
||||
team_name: teamItem.team_name,
|
||||
channel_id: undefined, // Will be set when channel is selected
|
||||
channel_name: undefined
|
||||
} : undefined
|
||||
teams_channel: teamItem
|
||||
? {
|
||||
team_id: teamItem.team_id,
|
||||
team_name: teamItem.team_name,
|
||||
channel_id: undefined, // Will be set when channel is selected
|
||||
channel_name: undefined
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- {JSON.stringify($values, null, 2)} -->
|
||||
@@ -367,7 +366,7 @@
|
||||
<Password
|
||||
small
|
||||
placeholder={setting.placeholder}
|
||||
on:keydown={() => {
|
||||
onKeyDown={() => {
|
||||
licenseKeyChanged = true
|
||||
}}
|
||||
bind:password={$values[setting.key]}
|
||||
@@ -600,7 +599,8 @@
|
||||
: undefined,
|
||||
(channel) => handleChannelChange(channel, i)
|
||||
}
|
||||
onError={(e) => sendUserToast('Failed to load channels: ' + e.message, true)}
|
||||
onError={(e) =>
|
||||
sendUserToast('Failed to load channels: ' + e.message, true)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -645,8 +645,8 @@
|
||||
if ($values[setting.key] == undefined || !Array.isArray($values[setting.key])) {
|
||||
$values[setting.key] = []
|
||||
}
|
||||
// Start with a typed default to avoid invalid primitives in the array
|
||||
$values[setting.key] = $values[setting.key].concat({ email: '' })
|
||||
// Start with a typed default to avoid invalid primitives in the array
|
||||
$values[setting.key] = $values[setting.key].concat({ email: '' })
|
||||
}}
|
||||
id="arg-input-add-item"
|
||||
startIcon={{ icon: Plus }}
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
<script lang="ts">
|
||||
// @ts-nocheck
|
||||
import { onMount } from 'svelte'
|
||||
export let password: string | undefined
|
||||
export let placeholder = '******'
|
||||
export let disabled = false
|
||||
export let required = false
|
||||
export let small = false
|
||||
import { createBubbler } from 'svelte/legacy'
|
||||
|
||||
$: red = required && (password == '' || password == undefined)
|
||||
const bubble = createBubbler()
|
||||
interface Props {
|
||||
password: string | undefined
|
||||
placeholder?: string
|
||||
disabled?: boolean
|
||||
required?: boolean
|
||||
small?: boolean
|
||||
onKeyDown?: (event: KeyboardEvent) => void
|
||||
}
|
||||
|
||||
let hideValue = true
|
||||
let {
|
||||
password = $bindable(),
|
||||
placeholder = '******',
|
||||
disabled = false,
|
||||
required = false,
|
||||
small = false,
|
||||
onKeyDown
|
||||
}: Props = $props()
|
||||
|
||||
let red = $derived(required && (password == '' || password == undefined))
|
||||
|
||||
let hideValue = $state(true)
|
||||
|
||||
let randomId = (Math.random() * 10e15).toString(16)
|
||||
</script>
|
||||
@@ -29,7 +42,7 @@
|
||||
: ''} text-sm h-9"
|
||||
type="password"
|
||||
bind:value={password}
|
||||
on:keydown
|
||||
onkeydown={onKeyDown}
|
||||
autocomplete="new-password"
|
||||
{placeholder}
|
||||
{disabled}
|
||||
@@ -41,7 +54,7 @@
|
||||
: ''} text-sm h-9"
|
||||
type="text"
|
||||
bind:value={password}
|
||||
on:keydown
|
||||
onkeydown={bubble('keydown')}
|
||||
autocomplete="new-password"
|
||||
{placeholder}
|
||||
{disabled}
|
||||
|
||||
@@ -2,24 +2,32 @@
|
||||
import { VariableService } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { generateRandomString } from '$lib/utils'
|
||||
import { Button } from './common'
|
||||
import Password from './Password.svelte'
|
||||
import { untrack } from 'svelte'
|
||||
|
||||
export let value: string | undefined = undefined
|
||||
export let disabled: boolean
|
||||
interface Props {
|
||||
value?: string | undefined
|
||||
disabled: boolean
|
||||
}
|
||||
|
||||
let path = ''
|
||||
let password = value && typeof value === 'string' && !value.startsWith('$var:') ? value : ''
|
||||
let { value = $bindable(undefined), disabled }: Props = $props()
|
||||
|
||||
let path = $state('')
|
||||
let password = $state(
|
||||
value && typeof value === 'string' && !value.startsWith('$var:') ? value : ''
|
||||
)
|
||||
|
||||
let isGenerating = false
|
||||
|
||||
let userPrefix = $derived(
|
||||
'u/' + ($userStore?.username ?? $userStore?.email)?.split('@')[0] + '/secret_arg/'
|
||||
)
|
||||
async function generateValue() {
|
||||
if (isGenerating) return
|
||||
isGenerating = true
|
||||
try {
|
||||
let npath =
|
||||
'u/' +
|
||||
($userStore?.username ?? $userStore?.email)?.split('@')[0] +
|
||||
'/secret_arg/' +
|
||||
generateRandomString(12)
|
||||
let npath = userPrefix + generateRandomString(12)
|
||||
let nvalue = '$var:' + npath
|
||||
await VariableService.createVariable({
|
||||
workspace: $workspaceStore!,
|
||||
@@ -32,6 +40,7 @@
|
||||
}
|
||||
})
|
||||
path = npath
|
||||
console.log('generated', nvalue)
|
||||
value = nvalue
|
||||
debouncedUpdate()
|
||||
} finally {
|
||||
@@ -59,13 +68,33 @@
|
||||
timeout = setTimeout(updateValue, 500)
|
||||
}
|
||||
|
||||
$: password && debouncedUpdate()
|
||||
$effect(() => {
|
||||
password && untrack(() => debouncedUpdate())
|
||||
})
|
||||
|
||||
$: $workspaceStore &&
|
||||
($userStore?.username || $userStore?.email) &&
|
||||
path == '' &&
|
||||
password != '' &&
|
||||
generateValue()
|
||||
$effect(() => {
|
||||
$workspaceStore &&
|
||||
($userStore?.username || $userStore?.email) &&
|
||||
path == '' &&
|
||||
password != '' &&
|
||||
untrack(() => generateValue())
|
||||
})
|
||||
</script>
|
||||
|
||||
<Password {disabled} bind:password />
|
||||
{#if value?.startsWith('$var:') && !value.startsWith('$var:' + userPrefix)}
|
||||
<div class="flex items-center gap-2 text-sm text-tertiary">
|
||||
Linked to static variable
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
variant="border"
|
||||
onclick={() => {
|
||||
value = ''
|
||||
}}
|
||||
>
|
||||
Reset variable link
|
||||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<Password {disabled} bind:password />
|
||||
{/if}
|
||||
|
||||
@@ -27,9 +27,9 @@ export abstract class AbstractCellRenderer implements ICellRendererComp {
|
||||
eGui: any
|
||||
protected component:
|
||||
| {
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
}
|
||||
refresh: (params: ICellRendererParams) => void
|
||||
destroy: () => void
|
||||
}
|
||||
| undefined
|
||||
constructor(parentElement = 'span') {
|
||||
// create empty span (or other element) to place svelte component in
|
||||
@@ -275,7 +275,7 @@ export function validateColumnDefs(columnDefs: WindmillColumnDef[]): {
|
||||
}
|
||||
|
||||
// Check if 'field' property exists and is a non-empty string
|
||||
if (noField && !(colDef.children && Array.isArray(colDef.children))) {
|
||||
if (noField && !(colDef.children && Array.isArray(colDef.children)) && !colDef.cellRenderer) {
|
||||
isValid = false
|
||||
errors.push(
|
||||
`Column at index ${index} is missing a valid 'field' property nor having any children.`
|
||||
|
||||
@@ -6,7 +6,6 @@ import { charsToNumber, numberToChars } from './idUtils'
|
||||
// Computes the next available id
|
||||
export function nextId(flowState: FlowState, fullFlow: OpenFlow): string {
|
||||
const allIds = dfs(fullFlow.value.modules, (fm) => fm.id)
|
||||
console.log('allIds', allIds)
|
||||
|
||||
const max = allIds.concat(Object.keys(flowState)).reduce((acc, key) => {
|
||||
if (key.length >= 4) {
|
||||
|
||||
@@ -28,7 +28,7 @@ export type DurationStatus = {
|
||||
}
|
||||
|
||||
export type FlowStatusViewerContext = {
|
||||
flowStateStore?: FlowState
|
||||
flowState?: FlowState
|
||||
retryStatus: StateStore<Record<string, number | undefined>>
|
||||
suspendStatus: StateStore<Record<string, { nb: number; job: Job }>>
|
||||
hideDownloadInGraph?: boolean
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
jobKindsCat = undefined,
|
||||
minTs = $bindable(undefined),
|
||||
maxTs = $bindable(undefined),
|
||||
jobKinds = $bindable(''),
|
||||
jobKinds = $bindable(undefined),
|
||||
queue_count = $bindable(undefined),
|
||||
suspended_count = $bindable(undefined),
|
||||
autoRefresh = true,
|
||||
|
||||
@@ -858,6 +858,7 @@
|
||||
{:then Module}
|
||||
<Module.default
|
||||
showReset
|
||||
onlyMaskPassword
|
||||
disabled={!can_write}
|
||||
schema={$state.snapshot(schema)}
|
||||
bind:isValid
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
let queue_count: Tweened<number> | undefined = $state(undefined)
|
||||
let suspended_count: Tweened<number> | undefined = $state(undefined)
|
||||
|
||||
let jobKinds: string | undefined = undefined
|
||||
let jobKinds: string | undefined = $state(undefined)
|
||||
let loading: boolean = $state(false)
|
||||
let paths: string[] = $state([])
|
||||
let usernames: string[] = $state([])
|
||||
@@ -186,7 +186,7 @@
|
||||
confirmBtnText: string
|
||||
loading?: boolean
|
||||
preContent?: string
|
||||
onConfirm?: () => void
|
||||
onConfirm?: (forceCancel: boolean) => void
|
||||
type?: ConfirmationModal['$$prop_def']['type']
|
||||
} = $state(undefined)
|
||||
|
||||
@@ -544,10 +544,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function cancelJobs(uuidsToCancel: string[]) {
|
||||
async function cancelJobs(uuidsToCancel: string[], forceCancel: boolean = false) {
|
||||
const uuids = await JobService.cancelSelection({
|
||||
workspace: $workspaceStore ?? '',
|
||||
requestBody: uuidsToCancel
|
||||
requestBody: uuidsToCancel,
|
||||
forceCancel: forceCancel
|
||||
})
|
||||
selectedIds = []
|
||||
jobsLoader?.loadJobs(minTs, maxTs, true, true)
|
||||
@@ -556,6 +557,7 @@
|
||||
}
|
||||
|
||||
async function onCancelFilteredJobs() {
|
||||
forceCancelInPopup = false
|
||||
askingForConfirmation = {
|
||||
title: 'Confirm cancelling all jobs corresponding to the selected filters',
|
||||
confirmBtnText: 'Loading...',
|
||||
@@ -570,18 +572,19 @@
|
||||
title: `Confirm cancelling all jobs corresponding to the selected filters (${jobIdsToCancel.length} jobs)`,
|
||||
confirmBtnText: `Cancel ${jobIdsToCancel.length} jobs that matched the filters`,
|
||||
preContent: selectedFiltersString,
|
||||
onConfirm: () => {
|
||||
cancelJobs(jobIdsToCancel)
|
||||
onConfirm: (forceCancel) => {
|
||||
cancelJobs(jobIdsToCancel, forceCancel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function onCancelSelectedJobs() {
|
||||
forceCancelInPopup = true
|
||||
askingForConfirmation = {
|
||||
confirmBtnText: `Cancel ${selectedIds.length} jobs`,
|
||||
title: 'Confirm cancelling the selected jobs',
|
||||
onConfirm: () => {
|
||||
cancelJobs(selectedIds)
|
||||
onConfirm: (forceCancel) => {
|
||||
cancelJobs(selectedIds, forceCancel)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -798,6 +801,8 @@
|
||||
|
||||
const smallScreenWidth = 1920
|
||||
const verySmallScreenWidth = 1300
|
||||
|
||||
let forceCancelInPopup = $state(false)
|
||||
</script>
|
||||
|
||||
<JobsLoader
|
||||
@@ -820,7 +825,7 @@
|
||||
computeMinAndMax={manualDatePicker?.computeMinMax}
|
||||
bind:minTs
|
||||
bind:maxTs
|
||||
{jobKinds}
|
||||
bind:jobKinds
|
||||
bind:queue_count
|
||||
bind:suspended_count
|
||||
{autoRefresh}
|
||||
@@ -842,7 +847,7 @@
|
||||
open={!!askingForConfirmation}
|
||||
on:confirmed={async () => {
|
||||
const func = askingForConfirmation?.onConfirm
|
||||
await func?.()
|
||||
await func?.(forceCancelInPopup)
|
||||
askingForConfirmation = undefined
|
||||
}}
|
||||
type={askingForConfirmation?.type}
|
||||
@@ -853,6 +858,27 @@
|
||||
>
|
||||
{#if askingForConfirmation?.preContent}
|
||||
<pre>{askingForConfirmation.preContent}</pre>
|
||||
<Toggle
|
||||
size="xs"
|
||||
class="mt-4"
|
||||
color="red"
|
||||
bind:checked={forceCancelInPopup}
|
||||
options={{
|
||||
right: 'Force cancel',
|
||||
rightTooltip:
|
||||
'Only use this for jobs that refuse to gracefully cancel. This is dangerous, only do this if you have no alternatives!'
|
||||
}}
|
||||
></Toggle>
|
||||
{#if forceCancelInPopup}
|
||||
<div class="mt-4 text-red-500 p-2 text-sm">
|
||||
<p>
|
||||
Force cancel is enabled. This is dangerous, only do this if you have no alternatives.
|
||||
Instead of being gracefully cancelled, all jobs will be immediately sent to the completed
|
||||
job table regardless of them being processed or not or part of running flows. You may end
|
||||
up in an inconsistent state.
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</ConfirmationModal>
|
||||
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.544.2"
|
||||
wmill_pg = ">=1.544.2"
|
||||
wmill = ">=1.545.0"
|
||||
wmill_pg = ">=1.545.0"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.544.2
|
||||
version: 1.545.0
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'WindmillClient.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.544.2'
|
||||
ModuleVersion = '1.545.0'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.544.2"
|
||||
version = "1.545.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 @@
|
||||
[tool.poetry]
|
||||
name = "wmill-pg"
|
||||
version = "1.544.2"
|
||||
version = "1.545.0"
|
||||
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.544.2",
|
||||
"version": "1.545.0",
|
||||
"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.544.2",
|
||||
"version": "1.545.0",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.544.2
|
||||
1.545.0
|
||||
|
||||
Reference in New Issue
Block a user