Compare commits
87 Commits
v1.394.2
...
preprocess
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dcddf834e | ||
|
|
e6ff31ca1d | ||
|
|
398a09b741 | ||
|
|
fbd0071a54 | ||
|
|
81c2bb0691 | ||
|
|
aeb5b5bcd1 | ||
|
|
590321fd3c | ||
|
|
8a277a0ad9 | ||
|
|
8b7bbe80a0 | ||
|
|
34a50ef8ca | ||
|
|
93fa6a0e97 | ||
|
|
74c2cabd9f | ||
|
|
17a8700956 | ||
|
|
8a469e7595 | ||
|
|
ad69c08228 | ||
|
|
4d5415dbd2 | ||
|
|
99c24109de | ||
|
|
61f27acbd5 | ||
|
|
5c6c0ff3cc | ||
|
|
a500994cc2 | ||
|
|
a17195d88f | ||
|
|
e99e7b2b0b | ||
|
|
01c16f29a8 | ||
|
|
30017cc2b1 | ||
|
|
9c506a83cb | ||
|
|
50a6f789fa | ||
|
|
5be7be03a6 | ||
|
|
70fa78c10d | ||
|
|
304dac3447 | ||
|
|
815f34b2af | ||
|
|
794f87aa0d | ||
|
|
9e9562e1a4 | ||
|
|
8212532b29 | ||
|
|
2a9d1b587b | ||
|
|
aec6972e29 | ||
|
|
69b8754aef | ||
|
|
a20ee6096a | ||
|
|
30fe28ceec | ||
|
|
3fd626c8d2 | ||
|
|
07372e7e65 | ||
|
|
623ece8c67 | ||
|
|
63f70f67d7 | ||
|
|
1b3e90ce7a | ||
|
|
6855b8da9a | ||
|
|
69b53603a5 | ||
|
|
5973e427c3 | ||
|
|
37d152feeb | ||
|
|
1f2d203f11 | ||
|
|
d6d4756b7a | ||
|
|
f7454e621c | ||
|
|
1576d33232 | ||
|
|
a24365237c | ||
|
|
c661ac8696 | ||
|
|
39374d7ee1 | ||
|
|
89b516450c | ||
|
|
277d085dbe | ||
|
|
9297ffcac4 | ||
|
|
1b439218ef | ||
|
|
97839a3583 | ||
|
|
d57b139df2 | ||
|
|
8ae6c3262a | ||
|
|
de78f6c192 | ||
|
|
6ba77d533f | ||
|
|
692c1dcb93 | ||
|
|
396258f637 | ||
|
|
36fc048004 | ||
|
|
2e80107e03 | ||
|
|
af85d4936d | ||
|
|
51cf420272 | ||
|
|
e70b36ea22 | ||
|
|
11ca14a2d3 | ||
|
|
f140daf4dc | ||
|
|
a0a36a7d52 | ||
|
|
e81c8384e4 | ||
|
|
bde3339de5 | ||
|
|
bb620aba24 | ||
|
|
03a2eae49a | ||
|
|
bc62930fe9 | ||
|
|
4dc9ca7f4e | ||
|
|
7c16f2cef4 | ||
|
|
ff08b5a9b5 | ||
|
|
f222645dce | ||
|
|
5bef077480 | ||
|
|
93e5ba1d16 | ||
|
|
fb4c8d266a | ||
|
|
562b2fc671 | ||
|
|
51e6f36e13 |
6
.github/DockerfileBackendTests
vendored
6
.github/DockerfileBackendTests
vendored
@@ -11,8 +11,8 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN apt update -y
|
||||
RUN apt install -y unzip curl
|
||||
|
||||
RUN [ "$TARGETPLATFORM" == "linux/amd64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v1.41.0/deno-x86_64-unknown-linux-gnu.zip -o deno.zip || true
|
||||
RUN [ "$TARGETPLATFORM" == "linux/arm64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v1.41.0/deno-aarch64-unknown-linux-gnu.zip -o deno.zip || true
|
||||
RUN [ "$TARGETPLATFORM" == "linux/amd64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v1.46.3/deno-x86_64-unknown-linux-gnu.zip -o deno.zip || true
|
||||
RUN [ "$TARGETPLATFORM" == "linux/arm64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v1.46.3/deno-aarch64-unknown-linux-gnu.zip -o deno.zip || true
|
||||
|
||||
|
||||
RUN unzip deno.zip && rm deno.zip
|
||||
@@ -53,7 +53,7 @@ RUN wget https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VER
|
||||
|
||||
RUN /usr/local/bin/python3 -m pip install pip-tools
|
||||
|
||||
COPY --from=oven/bun:1.1.8 /usr/local/bin/bun /usr/bin/bun
|
||||
COPY --from=oven/bun:1.1.27 /usr/local/bin/bun /usr/bin/bun
|
||||
|
||||
|
||||
RUN [ "$TARGETPLATFORM" == "linux/amd64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v1.41.0/deno-x86_64-unknown-linux-gnu.zip -o deno.zip || true
|
||||
|
||||
25
.github/workflows/docker-image.yml
vendored
25
.github/workflows/docker-image.yml
vendored
@@ -1,10 +1,8 @@
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME:
|
||||
${{ github.event_name != 'pull_request' && github.repository ||
|
||||
IMAGE_NAME: ${{ github.event_name != 'pull_request' && github.repository ||
|
||||
'windmill-labs/windmill-test' }}
|
||||
DEV_SHA:
|
||||
${{ github.event_name != 'pull_request' && 'dev' || format('pr-{0}',
|
||||
DEV_SHA: ${{ github.event_name != 'pull_request' && 'dev' || format('pr-{0}',
|
||||
github.event.number) }}
|
||||
|
||||
name: Build windmill:main
|
||||
@@ -476,6 +474,7 @@ jobs:
|
||||
file: "./docker/DockerfileNsjail"
|
||||
tags: |
|
||||
${{ steps.meta-ee-public.outputs.tags }}
|
||||
ghcr.io/windmill-labs/windmill-ee-nsjail:main
|
||||
labels: |
|
||||
${{ steps.meta-ee-public.outputs.labels }}
|
||||
org.opencontainers.image.licenses=Windmill-Enterprise-License
|
||||
@@ -720,11 +719,11 @@ jobs:
|
||||
- uses: depot/setup-action@v1
|
||||
|
||||
- name: Docker meta
|
||||
id: meta-ee-public
|
||||
id: meta-public
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-full
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-full
|
||||
flavor: |
|
||||
latest=false
|
||||
tags: |
|
||||
@@ -738,17 +737,17 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push publicly ee
|
||||
- name: Build and push publicly
|
||||
uses: depot/build-push-action@v1
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: "./docker/DockerfileRust"
|
||||
file: "./docker/DockerfileFull"
|
||||
tags: |
|
||||
${{ steps.meta-ee-public.outputs.tags }}
|
||||
${{ steps.meta-public.outputs.tags }}
|
||||
labels: |
|
||||
${{ steps.meta-ee-public.outputs.labels }}
|
||||
${{ steps.meta-public.outputs.labels }}
|
||||
|
||||
build_ee_full:
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
@@ -787,9 +786,9 @@ jobs:
|
||||
uses: depot/build-push-action@v1
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: "./docker/DockerfileRustEe"
|
||||
file: "./docker/DockerfileFullEe"
|
||||
tags: |
|
||||
${{ steps.meta-ee-public.outputs.tags }}
|
||||
labels: |
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ frontend/src/routes/test.svelte
|
||||
CaddyfileRemoteMalo
|
||||
*.swp
|
||||
**/.idea/
|
||||
.direnv
|
||||
|
||||
146
CHANGELOG.md
146
CHANGELOG.md
@@ -1,5 +1,151 @@
|
||||
# Changelog
|
||||
|
||||
## [1.399.0](https://github.com/windmill-labs/windmill/compare/v1.398.1...v1.399.0) (2024-09-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add tag filtering to external JWT authentication ([#4425](https://github.com/windmill-labs/windmill/issues/4425)) ([590321f](https://github.com/windmill-labs/windmill/commit/590321fd3c88046a657e0a751b62a19424102060))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** version the whole client for deno compatibility ([81c2bb0](https://github.com/windmill-labs/windmill/commit/81c2bb069176a95b8fb9c52b31e5e03c1cc78afc))
|
||||
* correct AI generation for CRON and regex ([#4437](https://github.com/windmill-labs/windmill/issues/4437)) ([aeb5b5b](https://github.com/windmill-labs/windmill/commit/aeb5b5bcd163e2e7d1413d7e4aed8bd769996f24))
|
||||
|
||||
## [1.398.1](https://github.com/windmill-labs/windmill/compare/v1.398.0...v1.398.1) (2024-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* time handling in bun and deno ([#4423](https://github.com/windmill-labs/windmill/issues/4423)) ([61f27ac](https://github.com/windmill-labs/windmill/commit/61f27acbd5b477f0e2453d4b02d406a7aef76009))
|
||||
|
||||
## [1.398.0](https://github.com/windmill-labs/windmill/compare/v1.397.4...v1.398.0) (2024-09-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **frontend:** add http routing templates ([#4421](https://github.com/windmill-labs/windmill/issues/4421)) ([e99e7b2](https://github.com/windmill-labs/windmill/commit/e99e7b2b0bb1bc63d1253d147b80bac06eaff103))
|
||||
* http routing ([#4339](https://github.com/windmill-labs/windmill/issues/4339)) ([304dac3](https://github.com/windmill-labs/windmill/commit/304dac34475b8871621c54a768275fae1e9f845e))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow no body in job requests ([#4413](https://github.com/windmill-labs/windmill/issues/4413)) ([70fa78c](https://github.com/windmill-labs/windmill/commit/70fa78c10d8afb3e06be84e3449fdfdeb2673765))
|
||||
* **frontend:** Fix delete branch one index ([#4418](https://github.com/windmill-labs/windmill/issues/4418)) ([30017cc](https://github.com/windmill-labs/windmill/commit/30017cc2b1401ea439e3fbec5d7764b206100a38))
|
||||
* migrate smtp instance settings to global settings ([#4416](https://github.com/windmill-labs/windmill/issues/4416)) ([50a6f78](https://github.com/windmill-labs/windmill/commit/50a6f789fa8a03d70407b0429da049cc0740b6fa))
|
||||
* no failed renewal alert if trial ([#4414](https://github.com/windmill-labs/windmill/issues/4414)) ([5be7be0](https://github.com/windmill-labs/windmill/commit/5be7be03a6df34a9fae96ed7f844d693f7cfce3e))
|
||||
* update pip to 24.2 and python 3.11.8->3.11.10 ([a17195d](https://github.com/windmill-labs/windmill/commit/a17195d88ff52b72f0c2cdd95c6218df8ef6d7cf))
|
||||
* various improvements for ansible ([#4419](https://github.com/windmill-labs/windmill/issues/4419)) ([a500994](https://github.com/windmill-labs/windmill/commit/a500994cc2cd9cc6cbad722059cebd0bf74a8850))
|
||||
|
||||
## [1.397.4](https://github.com/windmill-labs/windmill/compare/v1.397.3...v1.397.4) (2024-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** make CLI not require latest version of windmill ([794f87a](https://github.com/windmill-labs/windmill/commit/794f87aa0d33a0b782fcb2726754fdc51bc1d73d))
|
||||
|
||||
## [1.397.3](https://github.com/windmill-labs/windmill/compare/v1.397.2...v1.397.3) (2024-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** make CLI compatible with Node 18 ([8212532](https://github.com/windmill-labs/windmill/commit/8212532b29fbcf971cb320b8cfc84f3a8d8ad795))
|
||||
|
||||
## [1.397.2](https://github.com/windmill-labs/windmill/compare/v1.397.1...v1.397.2) (2024-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **bun:** never pre-bundle BASE_URL env variable ([69b8754](https://github.com/windmill-labs/windmill/commit/69b8754aef32682bf812be783f79b81cd8526c7a))
|
||||
|
||||
## [1.397.1](https://github.com/windmill-labs/windmill/compare/v1.397.0...v1.397.1) (2024-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **go:** put shared directory in job dir and not go parent ([623ece8](https://github.com/windmill-labs/windmill/commit/623ece8c6791b2c18648a68c562fcd5c8291be9b))
|
||||
* improve ability to paste from macos in vscode extension ([07372e7](https://github.com/windmill-labs/windmill/commit/07372e7e65d77df338718929f133e477a1daf993))
|
||||
* update git sync script ([30fe28c](https://github.com/windmill-labs/windmill/commit/30fe28ceecb9043eee6811dce8c3e2cd9224927b))
|
||||
|
||||
## [1.397.0](https://github.com/windmill-labs/windmill/compare/v1.396.1...v1.397.0) (2024-09-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* ansible playbook support ([#4399](https://github.com/windmill-labs/windmill/issues/4399)) ([6855b8d](https://github.com/windmill-labs/windmill/commit/6855b8da9ad92aed514ee1ab214c9550d04e7a22))
|
||||
|
||||
## [1.396.1](https://github.com/windmill-labs/windmill/compare/v1.396.0...v1.396.1) (2024-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* postgres scripts that take longer than 20s do not timeout anymore ([37d152f](https://github.com/windmill-labs/windmill/commit/37d152feeb6abeb061daa5c93c24916e520b1fd0))
|
||||
|
||||
## [1.396.0](https://github.com/windmill-labs/windmill/compare/v1.395.0...v1.396.0) (2024-09-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Allow setProgress and getProgress from within the script ([#4400](https://github.com/windmill-labs/windmill/issues/4400)) ([d6d4756](https://github.com/windmill-labs/windmill/commit/d6d4756b7a40249dbc622c8a93633e8d8b8333da))
|
||||
|
||||
## [1.395.0](https://github.com/windmill-labs/windmill/compare/v1.394.6...v1.395.0) (2024-09-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* failed key renewal alert + renew on start if no recent renewal ([#4387](https://github.com/windmill-labs/windmill/issues/4387)) ([de78f6c](https://github.com/windmill-labs/windmill/commit/de78f6c19266c67d43c7f80016a94b7988347e01))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* cannot create duplicate apps and raw_apps ([d57b139](https://github.com/windmill-labs/windmill/commit/d57b139df2267d1650749b31a3cce5742a3654d9))
|
||||
* **cli:** update CLI schema parsers to latest ([6ba77d5](https://github.com/windmill-labs/windmill/commit/6ba77d533fc1c50cf4153730adaf1b14a466f10a))
|
||||
* **deno:** replace lock-write with frozen=false ([277d085](https://github.com/windmill-labs/windmill/commit/277d085dbed0b9b1424348cc580ba601d935759b))
|
||||
* **frontend:** add support for step id change for forloops and branch… ([#4395](https://github.com/windmill-labs/windmill/issues/4395)) ([97839a3](https://github.com/windmill-labs/windmill/commit/97839a3583ef398c11e2f51058aaceed8e7382fb))
|
||||
* **frontend:** new resource type name must be snake case ([#4396](https://github.com/windmill-labs/windmill/issues/4396)) ([9297ffc](https://github.com/windmill-labs/windmill/commit/9297ffcac4d2092022463cd68b4e8ce8f02dcb3c))
|
||||
* improve vscode extension handling of relative paths ([8ae6c32](https://github.com/windmill-labs/windmill/commit/8ae6c3262a75af378a261b49f0e3a08d668c74b3))
|
||||
* update bun to 1.1.27 ([39374d7](https://github.com/windmill-labs/windmill/commit/39374d7ee13ffa0fe1e4ded146c91869acad144c))
|
||||
|
||||
## [1.394.6](https://github.com/windmill-labs/windmill/compare/v1.394.5...v1.394.6) (2024-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve first time setup experience ([396258f](https://github.com/windmill-labs/windmill/commit/396258f637e65361a9d9e0285b0a42ca5189fad4))
|
||||
|
||||
## [1.394.5](https://github.com/windmill-labs/windmill/compare/v1.394.4...v1.394.5) (2024-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add filename to s3 upload ([11ca14a](https://github.com/windmill-labs/windmill/commit/11ca14a2d32155e215c0d14d485e2c4048e5c66e))
|
||||
* parquet renderer display number of rows" ([#4389](https://github.com/windmill-labs/windmill/issues/4389)) ([51cf420](https://github.com/windmill-labs/windmill/commit/51cf420272cce1948dc4295b587f5037455c4eba))
|
||||
* queue metrics graph ([#4388](https://github.com/windmill-labs/windmill/issues/4388)) ([af85d49](https://github.com/windmill-labs/windmill/commit/af85d4936ddd01b390976c9989f3e4e72da3d01e))
|
||||
* update internal hub scritps to bun ([#4384](https://github.com/windmill-labs/windmill/issues/4384)) ([f140daf](https://github.com/windmill-labs/windmill/commit/f140daf4dc18db0a11bf478451aa57ae4698fd32))
|
||||
|
||||
## [1.394.4](https://github.com/windmill-labs/windmill/compare/v1.394.3...v1.394.4) (2024-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **frontend:** prompt fix-AI not to rename existing variables ([#4382](https://github.com/windmill-labs/windmill/issues/4382)) ([03a2eae](https://github.com/windmill-labs/windmill/commit/03a2eae49ac5b7c858e642e9f264beebbb2e9b34))
|
||||
* **frontend:** table footer display on safari ([#4377](https://github.com/windmill-labs/windmill/issues/4377)) ([93e5ba1](https://github.com/windmill-labs/windmill/commit/93e5ba1d16fcf52dea54ae4b4d7e5b02a899d0bd))
|
||||
* **image:** correctly publish windmill-full image ([bde3339](https://github.com/windmill-labs/windmill/commit/bde3339de53ad8430df6d7add6cfb00b4eb895c6))
|
||||
* improve app select propagation to list inputs in apps ([fb4c8d2](https://github.com/windmill-labs/windmill/commit/fb4c8d266a359af1ada4541e21b68bac9cb268a8))
|
||||
* improve password input for resources editor ([5bef077](https://github.com/windmill-labs/windmill/commit/5bef077480f1d708c507d943abcb4d36de084175))
|
||||
* multiple secret picker candidates in resource adder ([f222645](https://github.com/windmill-labs/windmill/commit/f222645dcead8f6608b81be36c683df679a5ae1c))
|
||||
* tighten inputs for granular kinds ([#4379](https://github.com/windmill-labs/windmill/issues/4379)) ([ff08b5a](https://github.com/windmill-labs/windmill/commit/ff08b5a9b5606f02228d0b54b45d422704fed3cb))
|
||||
* tighten number input validity if min or max is set ([7c16f2c](https://github.com/windmill-labs/windmill/commit/7c16f2cef4943a5d02e2bc6163761d80618aeae4))
|
||||
* timeout in pg executor on postgresql connection after 20s ([4dc9ca7](https://github.com/windmill-labs/windmill/commit/4dc9ca7f4e1477c087fe4f9bf6ea03fbcc99099c))
|
||||
|
||||
## [1.394.3](https://github.com/windmill-labs/windmill/compare/v1.394.2...v1.394.3) (2024-09-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve runFlowAsync and run_flow_async default behavior + time formatting of scheduled for ([51e6f36](https://github.com/windmill-labs/windmill/commit/51e6f36e13b251f01ddb8514de0d6d1a2bcd2244))
|
||||
|
||||
## [1.394.2](https://github.com/windmill-labs/windmill/compare/v1.394.1...v1.394.2) (2024-09-11)
|
||||
|
||||
|
||||
|
||||
BIN
Coupa Supplier Portal - Register.pdf
Normal file
BIN
Coupa Supplier Portal - Register.pdf
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
ARG DEBIAN_IMAGE=debian:bookworm-slim
|
||||
ARG RUST_IMAGE=rust:1.80-slim-bookworm
|
||||
ARG PYTHON_IMAGE=python:3.11.8-slim-bookworm
|
||||
ARG PYTHON_IMAGE=python:3.11.10-slim-bookworm
|
||||
|
||||
FROM ${RUST_IMAGE} AS rust_base
|
||||
|
||||
@@ -95,6 +95,8 @@ ARG WITH_KUBECTL=true
|
||||
ARG WITH_HELM=true
|
||||
ARG WITH_GIT=true
|
||||
|
||||
RUN pip install --upgrade pip==24.2
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ca-certificates wget curl jq unzip build-essential unixodbc xmlsec1 software-properties-common \
|
||||
&& apt-get clean \
|
||||
@@ -172,7 +174,7 @@ COPY --from=builder /windmill/target/release/windmill ${APP}/windmill
|
||||
|
||||
COPY --from=denoland/deno:1.46.3 --chmod=755 /usr/bin/deno /usr/bin/deno
|
||||
|
||||
COPY --from=oven/bun:1.1.25 /usr/local/bin/bun /usr/bin/bun
|
||||
COPY --from=oven/bun:1.1.27 /usr/local/bin/bun /usr/bin/bun
|
||||
|
||||
COPY --from=php:8.3.7-cli /usr/local/bin/php /usr/bin/php
|
||||
COPY --from=composer:2.7.6 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
23
README.md
23
README.md
@@ -352,14 +352,25 @@ you to have it being synced automatically everyday.
|
||||
| DISABLE_RESPONSE_LOGS | false | Disable response logs | Server |
|
||||
|
||||
## Run a local dev setup
|
||||
See the [./frontend/README_DEV.md](./frontend/README_DEV.md) file for all
|
||||
running options.
|
||||
|
||||
### only Frontend
|
||||
This will use the backend of <https://app.windmill.dev> but your own frontend
|
||||
with hot-code reloading.
|
||||
1. Install [caddy](https://caddyserver.com)
|
||||
2. Go to `frontend/`:
|
||||
1. `npm install`, `npm run generate-backend-client` then `npm run dev`
|
||||
2. In another shell `sudo caddy run --config CaddyfileRemote`
|
||||
3. Et voilà, windmill should be available at `http://localhost/`
|
||||
with hot-code reloading. Note that you will need to use a username / password login due to CSRF checks using a different auth provider.
|
||||
|
||||
In the `frontend/` directory:
|
||||
|
||||
1. install the dependencies with `npm install` (or `pnpm install` or `yarn`)
|
||||
2. generate the windmill client:
|
||||
```
|
||||
npm run generate-backend-client
|
||||
## on mac use
|
||||
npm run generate-backend-client-mac
|
||||
```
|
||||
3. Run your dev server with `npm run dev`
|
||||
4. Et voilà, windmill should be available at `http://localhost/`
|
||||
|
||||
### Backend + Frontend
|
||||
See the [./frontend/README_DEV.md](./frontend/README_DEV.md) file for all
|
||||
running options.
|
||||
|
||||
89
backend/.sqlx/query-02f1a6eeb27067dc438459238e7b016f5ccf9e3fe0ffbe88471f15aad8f74441.json
generated
Normal file
89
backend/.sqlx/query-02f1a6eeb27067dc438459238e7b016f5ccf9e3fe0ffbe88471f15aad8f74441.json
generated
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT path, script_path, is_flow, route_path, workspace_id, is_async, requires_auth, edited_by, email, http_method as \"http_method: _\" FROM http_trigger WHERE workspace_id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "is_flow",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "route_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "workspace_id",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "is_async",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "requires_auth",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "http_method: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "02f1a6eeb27067dc438459238e7b016f5ccf9e3fe0ffbe88471f15aad8f74441"
|
||||
}
|
||||
@@ -32,6 +32,11 @@
|
||||
"ordinal": 5,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "format_extension",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -46,6 +51,7 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
20
backend/.sqlx/query-0aa47e68f9e21115d96a8a1117e95f800c8bfb9bd6872a657c7e7131a21563c8.json
generated
Normal file
20
backend/.sqlx/query-0aa47e68f9e21115d96a8a1117e95f800c8bfb9bd6872a657c7e7131a21563c8.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT 1 FROM password WHERE email = 'admin@windmill.dev' AND password_hash = '$argon2id$v=19$m=4096,t=3,p=1$oLJo/lPn/gezXCuFOEyaNw$i0T2tCkw3xUFsrBIKZwr8jVNHlIfoxQe+HfDnLtd12I'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "?column?",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "0aa47e68f9e21115d96a8a1117e95f800c8bfb9bd6872a657c7e7131a21563c8"
|
||||
}
|
||||
@@ -71,7 +71,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['failure_module'], $1), ARRAY['step'], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0aff8b0f2cddc0dd696759f48368c7315ff39060be5430c59582e1e05a4b3d90"
|
||||
}
|
||||
15
backend/.sqlx/query-0e52a588f3edeb8fb58d6d62247b8590e51171e2811c62737bdb81fb0ac8f182.json
generated
Normal file
15
backend/.sqlx/query-0e52a588f3edeb8fb58d6d62247b8590e51171e2811c62737bdb81fb0ac8f182.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE worker_ping SET \n ping_at = now(), \n jobs_executed = 1, \n current_job_id = $1, \n current_job_workspace_id = 'admins' \n WHERE worker = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "0e52a588f3edeb8fb58d6d62247b8590e51171e2811c62737bdb81fb0ac8f182"
|
||||
}
|
||||
36
backend/.sqlx/query-16c4fb122ceb30722f54c92db97427b0ddd36f495d549f8cd23d659d2c866a63.json
generated
Normal file
36
backend/.sqlx/query-16c4fb122ceb30722f54c92db97427b0ddd36f495d549f8cd23d659d2c866a63.json
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM http_trigger WHERE route_path_key = $1 AND http_method = $2)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "16c4fb122ceb30722f54c92db97427b0ddd36f495d549f8cd23d659d2c866a63"
|
||||
}
|
||||
16
backend/.sqlx/query-17e3e2a3232865c33fa535b5d99455942e30f932c5b97f1e5b508128f39a288f.json
generated
Normal file
16
backend/.sqlx/query-17e3e2a3232865c33fa535b5d99455942e30f932c5b97f1e5b508128f39a288f.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1), ARRAY['step'], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "17e3e2a3232865c33fa535b5d99455942e30f932c5b97f1e5b508128f39a288f"
|
||||
}
|
||||
@@ -51,7 +51,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
20
backend/.sqlx/query-388b3705f641621b0c2f4496e36cb7aa5a75b7e40fa312eff6590e54b02635a2.json
generated
Normal file
20
backend/.sqlx/query-388b3705f641621b0c2f4496e36cb7aa5a75b7e40fa312eff6590e54b02635a2.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM metrics WHERE id = 'license_key_renewal' AND created_at > NOW() - INTERVAL '24 hours')",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "388b3705f641621b0c2f4496e36cb7aa5a75b7e40fa312eff6590e54b02635a2"
|
||||
}
|
||||
20
backend/.sqlx/query-3d60b4f2cbedb61affeff94fd77b7c86493c30a4d3d648d0660a3281824156b9.json
generated
Normal file
20
backend/.sqlx/query-3d60b4f2cbedb61affeff94fd77b7c86493c30a4d3d648d0660a3281824156b9.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(*) FROM global_settings WHERE name = 'base_url'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "3d60b4f2cbedb61affeff94fd77b7c86493c30a4d3d648d0660a3281824156b9"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return \n FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 and flow.workspace_id = $2",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor \n FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 and flow.workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -15,8 +15,8 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "early_return",
|
||||
"type_info": "Text"
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -31,5 +31,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "872dcaec230579e4480adf23075e323557efbe52c813e3a6a0da6b855291951e"
|
||||
"hash": "3fedf12ee5d44e8af9c3864cc70a8f607dccc015ce2d5150c56c68074cd0f84d"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "WITH queue_metrics as (\n SELECT id, value, created_at\n FROM metrics\n WHERE id LIKE 'queue_%'\n AND created_at > now() - interval '14 day'\n ORDER BY created_at ASC\n )\n SELECT id, array_agg(json_build_object('value', value, 'created_at', created_at)) as \"values!\"\n FROM queue_metrics\n GROUP BY id\n ORDER BY id ASC",
|
||||
"query": "WITH queue_metrics as (\n SELECT id, value, created_at\n FROM metrics\n WHERE id LIKE 'queue_%'\n AND created_at > now() - interval '14 day'\n )\n SELECT id, array_agg(json_build_object('value', value, 'created_at', created_at) ORDER BY created_at ASC) as \"values!\"\n FROM queue_metrics\n GROUP BY id\n ORDER BY id ASC",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -22,5 +22,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "7c95f3652de4561b18c1a340db3e0113a4777d38de4468fc41b22ce5b6fd1db7"
|
||||
"hash": "44dd7a66ecc9564ad5727970b5f60a1717eda8924999741be522ffb74cc173fa"
|
||||
}
|
||||
14
backend/.sqlx/query-4c97fcc93b31c4b3262419d6ee183773a95de3b6694a398cb80d288bef4f130f.json
generated
Normal file
14
backend/.sqlx/query-4c97fcc93b31c4b3262419d6ee183773a95de3b6694a398cb80d288bef4f130f.json
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE completed_job SET args = '{\"reason\":\"PREPROCESSOR_ARGS_ARE_DISCARDED\"}'::jsonb WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4c97fcc93b31c4b3262419d6ee183773a95de3b6694a398cb80d288bef4f130f"
|
||||
}
|
||||
38
backend/.sqlx/query-4d8640e84fccf1a0b799d8396a51e69345137e68d5096c70ba0a4332075d97ea.json
generated
Normal file
38
backend/.sqlx/query-4d8640e84fccf1a0b799d8396a51e69345137e68d5096c70ba0a4332075d97ea.json
generated
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE http_trigger \n SET route_path = $1, route_path_key = $2, script_path = $3, path = $4, is_flow = $5, http_method = $6, edited_by = $7, email = $8, is_async = $9, requires_auth = $10, edited_at = now() \n WHERE workspace_id = $11 AND path = $12",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
"Bool",
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4d8640e84fccf1a0b799d8396a51e69345137e68d5096c70ba0a4332075d97ea"
|
||||
}
|
||||
108
backend/.sqlx/query-4fb95eae1c871241efe2ef79615ce03cba0e4a12aad3274e4829d98e38ca1491.json
generated
Normal file
108
backend/.sqlx/query-4fb95eae1c871241efe2ef79615ce03cba0e4a12aad3274e4829d98e38ca1491.json
generated
Normal file
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT workspace_id, path, route_path, route_path_key, script_path, is_flow, http_method as \"http_method: _\", edited_by, email, edited_at, extra_perms, is_async, requires_auth\n FROM http_trigger\n WHERE workspace_id = $1 AND path = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "workspace_id",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "route_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "route_path_key",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "is_flow",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "http_method: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "edited_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "extra_perms",
|
||||
"type_info": "Jsonb"
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "is_async",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "requires_auth",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "4fb95eae1c871241efe2ef79615ce03cba0e4a12aad3274e4829d98e38ca1491"
|
||||
}
|
||||
36
backend/.sqlx/query-55d44f569f8ebfccddf975e1a330ef0dc286f4138efe923832371cdbac7157b0.json
generated
Normal file
36
backend/.sqlx/query-55d44f569f8ebfccddf975e1a330ef0dc286f4138efe923832371cdbac7157b0.json
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE http_trigger SET script_path = $1, path = $2, is_flow = $3, http_method = $4, edited_by = $5, email = $6, is_async = $7, requires_auth = $8, edited_at = now() \n WHERE workspace_id = $9 AND path = $10",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
"Bool",
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "55d44f569f8ebfccddf975e1a330ef0dc286f4138efe923832371cdbac7157b0"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select path, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout from script where hash = $1 AND workspace_id = $2",
|
||||
"query": "select path, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor from script where hash = $1 AND workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -56,7 +56,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -81,6 +82,11 @@
|
||||
"ordinal": 10,
|
||||
"name": "timeout",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -100,8 +106,9 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "8b10c9ade85c0307e300224e87962ceba8e7ccbe53b56c4670a1634bb9d0e89c"
|
||||
"hash": "64ce3eabed6de7a4f99884640c21218ac19ab2a4bc5f8b42deb2476f85d0deac"
|
||||
}
|
||||
20
backend/.sqlx/query-74d5757014fc7a6818ae857bfdda9f6317cf2b9e0a78cbad80ebdc935d3246fd.json
generated
Normal file
20
backend/.sqlx/query-74d5757014fc7a6818ae857bfdda9f6317cf2b9e0a78cbad80ebdc935d3246fd.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT 1 FROM password LIMIT 2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "?column?",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "74d5757014fc7a6818ae857bfdda9f6317cf2b9e0a78cbad80ebdc935d3246fd"
|
||||
}
|
||||
15
backend/.sqlx/query-76ca60e456022cf3d1931245b7daf22783c81bc757d735a4b247cc693dfed719.json
generated
Normal file
15
backend/.sqlx/query-76ca60e456022cf3d1931245b7daf22783c81bc757d735a4b247cc693dfed719.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(flow_status, ARRAY['modules', flow_status->>'step', 'progress'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "76ca60e456022cf3d1931245b7daf22783c81bc757d735a4b247cc693dfed719"
|
||||
}
|
||||
@@ -32,6 +32,11 @@
|
||||
"ordinal": 5,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "format_extension",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -45,6 +50,7 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT config FROM config WHERE name = 'server'",
|
||||
"query": "SELECT value FROM global_settings WHERE name = 'smtp_settings'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "config",
|
||||
"name": "value",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
@@ -13,8 +13,8 @@
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "8ca76fcadc659d7069b97930cdde2d5200f3cef9dedb83b76c8a6a433d2a4de3"
|
||||
"hash": "83ec97f6aad154e0e06ee05a3647dab8f89b1b2d7a569c7eac8c4169e37b9f8b"
|
||||
}
|
||||
37
backend/.sqlx/query-867e0f8299e22a6b8e02d21adeb0281b1a10593715db823a5adeeac3ab1058cd.json
generated
Normal file
37
backend/.sqlx/query-867e0f8299e22a6b8e02d21adeb0281b1a10593715db823a5adeeac3ab1058cd.json
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM http_trigger WHERE route_path_key = $1 AND workspace_id = $2 AND http_method = $3)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "867e0f8299e22a6b8e02d21adeb0281b1a10593715db823a5adeeac3ab1058cd"
|
||||
}
|
||||
17
backend/.sqlx/query-870d7feec169f70d140b7477562315ed2fd4662975bf0d01cfbffac86a959368.json
generated
Normal file
17
backend/.sqlx/query-870d7feec169f70d140b7477562315ed2fd4662975bf0d01cfbffac86a959368.json
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2), ARRAY['step'], $3)\n WHERE id = $4",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "870d7feec169f70d140b7477562315ed2fd4662975bf0d01cfbffac86a959368"
|
||||
}
|
||||
24
backend/.sqlx/query-9422431d79de41518f651ef24e86819d7b6a2f5531740a7deea1b51775335977.json
generated
Normal file
24
backend/.sqlx/query-9422431d79de41518f651ef24e86819d7b6a2f5531740a7deea1b51775335977.json
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT scalar_int FROM job_stats WHERE workspace_id = $1 AND job_id = $2 AND metric_id = $3",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "scalar_int",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "9422431d79de41518f651ef24e86819d7b6a2f5531740a7deea1b51775335977"
|
||||
}
|
||||
41
backend/.sqlx/query-98081ee9a4a4a52ae70d74d26e8608a010722d7ea9dc343ae8f03e38978ffaba.json
generated
Normal file
41
backend/.sqlx/query-98081ee9a4a4a52ae70d74d26e8608a010722d7ea9dc343ae8f03e38978ffaba.json
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor\n FROM flow \n LEFT JOIN flow_version\n ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]\n WHERE flow.path = $1 and flow.workspace_id = $2",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "tag",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "dedicated_worker",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "early_return",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "98081ee9a4a4a52ae70d74d26e8608a010722d7ea9dc343ae8f03e38978ffaba"
|
||||
}
|
||||
23
backend/.sqlx/query-9a050ab74cfc13a4b855408e61ebcb0a9d27e5563fa7af5e00a4916b03a62ddb.json
generated
Normal file
23
backend/.sqlx/query-9a050ab74cfc13a4b855408e61ebcb0a9d27e5563fa7af5e00a4916b03a62ddb.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM http_trigger WHERE path = $1 AND workspace_id = $2)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "9a050ab74cfc13a4b855408e61ebcb0a9d27e5563fa7af5e00a4916b03a62ddb"
|
||||
}
|
||||
15
backend/.sqlx/query-9c17ddca92e0a93051b36bb688ad6c1c24108e45c94be52595ca6cb82135f4eb.json
generated
Normal file
15
backend/.sqlx/query-9c17ddca92e0a93051b36bb688ad6c1c24108e45c94be52595ca6cb82135f4eb.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue SET args = (select result FROM completed_job WHERE id = $1) WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9c17ddca92e0a93051b36bb688ad6c1c24108e45c94be52595ca6cb82135f4eb"
|
||||
}
|
||||
@@ -56,7 +56,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
22
backend/.sqlx/query-9ebb9c16948a695a053068d9a1df0152691271ac33d8c82db47be11746ccbcef.json
generated
Normal file
22
backend/.sqlx/query-9ebb9c16948a695a053068d9a1df0152691271ac33d8c82db47be11746ccbcef.json
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "9ebb9c16948a695a053068d9a1df0152691271ac33d8c82db47be11746ccbcef"
|
||||
}
|
||||
16
backend/.sqlx/query-ad8f9e0b06f288051cbec3c91877430a1d61353b9122fd42777d92e4cbc9f4fa.json
generated
Normal file
16
backend/.sqlx/query-ad8f9e0b06f288051cbec3c91877430a1d61353b9122fd42777d92e4cbc9f4fa.json
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['failure_module'], $1), ARRAY['step'], $2)\n WHERE id = $3",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ad8f9e0b06f288051cbec3c91877430a1d61353b9122fd42777d92e4cbc9f4fa"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, codebase) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30)",
|
||||
"query": "INSERT INTO script (workspace_id, hash, path, parent_hashes, summary, description, content, created_by, schema, is_template, extra_perms, lock, language, kind, tag, draft_only, envs, concurrent_limit, concurrency_time_window_s, cache_ttl, dedicated_worker, ws_error_handler_muted, priority, restart_unless_cancelled, delete_after_use, timeout, concurrency_key, visible_to_runner_only, no_main_func, codebase, has_preprocessor) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::text::json, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -37,7 +37,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -71,10 +72,11 @@
|
||||
"Varchar",
|
||||
"Bool",
|
||||
"Bool",
|
||||
"Varchar"
|
||||
"Varchar",
|
||||
"Bool"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "8e7ff45c5378c3a3406ba94dc0653afa5d28c072203617c598caefaaf1bafcfb"
|
||||
"hash": "b49b1eaf58e62063c7a03039d0c36e65991b1d21a3306390fb1c7ca38babafe3"
|
||||
}
|
||||
23
backend/.sqlx/query-b57a188ca137162a2848ebf81fa3aeca9a14ac628c61a358e2c6612c57249b0f.json
generated
Normal file
23
backend/.sqlx/query-b57a188ca137162a2848ebf81fa3aeca9a14ac628c61a358e2c6612c57249b0f.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1 AND path = $2)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "exists",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "b57a188ca137162a2848ebf81fa3aeca9a14ac628c61a358e2c6612c57249b0f"
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(\n JSONB_SET(flow_status, ARRAY['modules', $1::TEXT], $2), ARRAY['step'], $3)\n WHERE id = $4",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Jsonb",
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b64c7f3b483c74c51aecda65664c36d9686112182dbf35651e494da739b922f9"
|
||||
}
|
||||
@@ -32,6 +32,11 @@
|
||||
"ordinal": 5,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "format_extension",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -45,6 +50,7 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
|
||||
15
backend/.sqlx/query-c14009d133956710f4435a5984c18b9517e256978512f014e1bf5c270f499772.json
generated
Normal file
15
backend/.sqlx/query-c14009d133956710f4435a5984c18b9517e256978512f014e1bf5c270f499772.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE queue\n SET flow_status = JSONB_SET(flow_status, ARRAY['preprocessor_module'], $1)\n WHERE id = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Jsonb",
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c14009d133956710f4435a5984c18b9517e256978512f014e1bf5c270f499772"
|
||||
}
|
||||
37
backend/.sqlx/query-c229744534f17f7622c3dee21bb1e7292ff17e6dffe58e80e53bff8baade07c8.json
generated
Normal file
37
backend/.sqlx/query-c229744534f17f7622c3dee21bb1e7292ff17e6dffe58e80e53bff8baade07c8.json
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO http_trigger (workspace_id, path, route_path, route_path_key, script_path, is_flow, is_async, requires_auth, http_method, edited_by, email, edited_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, now())",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Varchar",
|
||||
"Bool",
|
||||
"Bool",
|
||||
"Bool",
|
||||
{
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "c229744534f17f7622c3dee21bb1e7292ff17e6dffe58e80e53bff8baade07c8"
|
||||
}
|
||||
28
backend/.sqlx/query-cf1cef7e0fe2e7e3db96b0ec005360361b9eec023a6fc2a4a7a917f59d86af4d.json
generated
Normal file
28
backend/.sqlx/query-cf1cef7e0fe2e7e3db96b0ec005360361b9eec023a6fc2a4a7a917f59d86af4d.json
generated
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT name, format_extension FROM resource_type WHERE format_extension IS NOT NULL AND (workspace_id = $1 OR workspace_id = 'admins')",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "name",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "format_extension",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "cf1cef7e0fe2e7e3db96b0ec005360361b9eec023a6fc2a4a7a917f59d86af4d"
|
||||
}
|
||||
@@ -77,7 +77,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
23
backend/.sqlx/query-d600a0ad953ed131952d9c46deb8f65143894f86517f2b5b2d51bc9a2857695c.json
generated
Normal file
23
backend/.sqlx/query-d600a0ad953ed131952d9c46deb8f65143894f86517f2b5b2d51bc9a2857695c.json
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT (scalar_int)::int FROM job_stats WHERE job_id = $1 AND workspace_id = $2 AND metric_id = 'progress_perc'",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "scalar_int",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "d600a0ad953ed131952d9c46deb8f65143894f86517f2b5b2d51bc9a2857695c"
|
||||
}
|
||||
15
backend/.sqlx/query-dc9a906d6c6156a84fccf4e3a2a7c08d8ed4984409b669162f0a1fc1aa48e188.json
generated
Normal file
15
backend/.sqlx/query-dc9a906d6c6156a84fccf4e3a2a7c08d8ed4984409b669162f0a1fc1aa48e188.json
generated
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM http_trigger WHERE workspace_id = $1 AND path = $2",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "dc9a906d6c6156a84fccf4e3a2a7c08d8ed4984409b669162f0a1fc1aa48e188"
|
||||
}
|
||||
@@ -32,6 +32,11 @@
|
||||
"ordinal": 5,
|
||||
"name": "created_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "format_extension",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -43,6 +48,7 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT (flow_status->'step')::integer as step, jsonb_array_length(flow_status->'modules') as len FROM queue WHERE id = $1",
|
||||
"query": "SELECT (flow_status->'step')::integer as step, jsonb_array_length(flow_status->'modules') as len FROM queue WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -24,5 +24,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "f80e94176224ef23416da99b26ad5c330d65016fb93345b054cbb63a4bf37fc8"
|
||||
"hash": "f9e0e35b4789a4da89f7bb21fa6b250fd64ee0e0b299471979db5ff8ee906929"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "select hash, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout from script where path = $1 AND workspace_id = $2 AND\n created_at = (SELECT max(created_at) FROM script WHERE path = $1 AND workspace_id = $2 AND\n deleted = false AND lock IS not NULL AND lock_error_logs IS NULL)",
|
||||
"query": "select hash, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor from script where path = $1 AND workspace_id = $2 AND\n created_at = (SELECT max(created_at) FROM script WHERE path = $1 AND workspace_id = $2 AND\n deleted = false AND lock IS not NULL AND lock_error_logs IS NULL)",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -56,7 +56,8 @@
|
||||
"mssql",
|
||||
"php",
|
||||
"bunnative",
|
||||
"rust"
|
||||
"rust",
|
||||
"ansible"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -81,6 +82,11 @@
|
||||
"ordinal": 10,
|
||||
"name": "timeout",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "has_preprocessor",
|
||||
"type_info": "Bool"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -100,8 +106,9 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "e1c715020f1efb00123171edfb6173bfeaaa95d4f870240e42b76e5df304ce99"
|
||||
"hash": "fc7ac95d8d5f4532a2b0e50f84c1e273d25543401639a68f868e1e4fd8b0640a"
|
||||
}
|
||||
87
backend/.sqlx/query-fe4f91ca7e179e58041a5c0b1a36015175e9301c01a99e8f2b82cb853349a183.json
generated
Normal file
87
backend/.sqlx/query-fe4f91ca7e179e58041a5c0b1a36015175e9301c01a99e8f2b82cb853349a183.json
generated
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT path, script_path, is_flow, route_path, workspace_id, is_async, requires_auth, edited_by, email, http_method as \"http_method: _\" FROM http_trigger",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "is_flow",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "route_path",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "workspace_id",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "is_async",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "requires_auth",
|
||||
"type_info": "Bool"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "edited_by",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "http_method: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "http_method",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "fe4f91ca7e179e58041a5c0b1a36015175e9301c01a99e8f2b82cb853349a183"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO resource_type\n (workspace_id, name, schema, description, created_by, edited_at)\n VALUES ($1, $2, $3, $4, $5, now())",
|
||||
"query": "INSERT INTO resource_type\n (workspace_id, name, schema, description, created_by, format_extension, edited_at)\n VALUES ($1, $2, $3, $4, $5, $6, now())",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -9,10 +9,11 @@
|
||||
"Varchar",
|
||||
"Jsonb",
|
||||
"Text",
|
||||
"Varchar",
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "d249343a1d9fce2f7ca9e6e447eb32d7d11b61acdab80dda24db4a9ba3e1f7e6"
|
||||
"hash": "ffedbb3a2676a6d7b71f81f89109a02a8dba90d40144e942527f8a3fc36dfbc1"
|
||||
}
|
||||
302
backend/Cargo.lock
generated
302
backend/Cargo.lock
generated
@@ -177,9 +177,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356"
|
||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
@@ -229,9 +229,9 @@ checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
|
||||
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
@@ -696,9 +696,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.82"
|
||||
version = "0.1.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
|
||||
checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -823,9 +823,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sso"
|
||||
version = "1.42.0"
|
||||
version = "1.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27bf24cd0d389daa923e974b0e7c38daf308fc21e963c049f57980235017175e"
|
||||
checksum = "70a9d27ed1c12b1140c47daf1bc541606c43fdafd918c4797d520db0043ceef2"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -845,9 +845,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-ssooidc"
|
||||
version = "1.43.0"
|
||||
version = "1.44.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b43b3220f1c46ac0e9dcc0a97d94b93305dacb36d1dd393996300c6b9b74364"
|
||||
checksum = "44514a6ca967686cde1e2a1b81df6ef1883d0e3e570da8d8bc5c491dcb6fc29b"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -867,9 +867,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sts"
|
||||
version = "1.42.0"
|
||||
version = "1.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1c46924fb1add65bba55636e12812cae2febf68c0f37361766f627ddcca91ce"
|
||||
checksum = "cd7a4d279762a35b9df97209f6808b95d4fe78547fe2316b4d200a0283960c5a"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-runtime",
|
||||
@@ -1056,9 +1056,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
|
||||
checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
@@ -1083,7 +1083,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 1.0.1",
|
||||
"tokio",
|
||||
"tower 0.4.13",
|
||||
"tower 0.5.1",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -1091,9 +1091,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
|
||||
checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
@@ -1104,7 +1104,7 @@ dependencies = [
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"sync_wrapper 0.1.2",
|
||||
"sync_wrapper 1.0.1",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -1505,9 +1505,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.7.1"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
|
||||
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
|
||||
|
||||
[[package]]
|
||||
name = "bytes-utils"
|
||||
@@ -1609,9 +1609,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.18"
|
||||
version = "1.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||
checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -1735,9 +1735,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.17"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac"
|
||||
checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -1745,9 +1745,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.17"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73"
|
||||
checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1757,9 +1757,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.13"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
|
||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -2795,7 +2795,7 @@ dependencies = [
|
||||
"rustls-webpki 0.102.8",
|
||||
"serde",
|
||||
"tokio",
|
||||
"webpki-roots 0.26.5",
|
||||
"webpki-roots 0.26.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4313,9 +4313,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
version = "0.1.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
@@ -4523,9 +4523,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.70"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -4670,9 +4670,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.158"
|
||||
version = "0.2.159"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
@@ -4710,7 +4710,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"redox_syscall 0.5.3",
|
||||
"redox_syscall 0.5.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4892,7 +4892,7 @@ dependencies = [
|
||||
"smtp-proto",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.0",
|
||||
"webpki-roots 0.26.5",
|
||||
"webpki-roots 0.26.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5025,9 +5025,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
|
||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"stable_deref_trait",
|
||||
@@ -5058,16 +5058,6 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@@ -5452,7 +5442,7 @@ dependencies = [
|
||||
"md-5 0.10.6",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"quick-xml 0.36.1",
|
||||
"quick-xml 0.36.2",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.12.7",
|
||||
"ring 0.17.8",
|
||||
@@ -5682,7 +5672,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.5.3",
|
||||
"redox_syscall 0.5.5",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
@@ -6001,9 +5991,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.30"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
@@ -6022,9 +6012,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
|
||||
checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce"
|
||||
|
||||
[[package]]
|
||||
name = "postgres-native-tls"
|
||||
@@ -6059,9 +6049,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "postgres-types"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9"
|
||||
checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f"
|
||||
dependencies = [
|
||||
"array-init",
|
||||
"bit-vec",
|
||||
@@ -6130,7 +6120,7 @@ version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
|
||||
dependencies = [
|
||||
"toml_edit 0.22.20",
|
||||
"toml_edit 0.22.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6384,9 +6374,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.36.1"
|
||||
version = "0.36.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc"
|
||||
checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
@@ -6394,9 +6384,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quick_cache"
|
||||
version = "0.6.6"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ec0b6fed0a0ff01fa82d0c8982389375dd59c72dae84d4f8a15b1a894c273f7"
|
||||
checksum = "7d7c94f8935a9df96bb6380e8592c70edf497a643f94bd23b2f76b399385dbf4"
|
||||
dependencies = [
|
||||
"ahash 0.8.11",
|
||||
"equivalent",
|
||||
@@ -6633,9 +6623,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.3"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||
checksum = "62871f2d65009c0256aed1b9cfeeb8ac272833c404e13d53d400cd0dad7a2ac0"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
@@ -7425,9 +7415,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.11.1"
|
||||
version = "2.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf"
|
||||
checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -7765,9 +7755,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
@@ -8061,7 +8051,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid 1.10.0",
|
||||
"webpki-roots 0.26.5",
|
||||
"webpki-roots 0.26.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9029,9 +9019,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.41"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909"
|
||||
checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
@@ -9071,18 +9061,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.63"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
||||
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.63"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
|
||||
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -9325,9 +9315,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-postgres"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3"
|
||||
checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"byteorder",
|
||||
@@ -9443,7 +9433,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.20",
|
||||
"toml_edit 0.22.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9470,15 +9460,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.20"
|
||||
version = "0.22.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||
dependencies = [
|
||||
"indexmap 2.5.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow 0.6.18",
|
||||
"winnow 0.6.19",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9507,7 +9497,6 @@ dependencies = [
|
||||
"tokio",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9516,8 +9505,14 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"pin-project-lite",
|
||||
"sync_wrapper 0.1.2",
|
||||
"tokio",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9934,9 +9929,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id"
|
||||
version = "0.3.4"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f"
|
||||
checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id-start"
|
||||
@@ -9952,9 +9947,9 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
@@ -9976,21 +9971,21 @@ checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.13"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_categories"
|
||||
@@ -10000,9 +9995,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2"
|
||||
version = "1.2.2"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "addeebf294df7922a1164f729fb27ebbbcea99cc32b3bf08afab62757f707677"
|
||||
checksum = "d1673eca9782c84de5f81b82e4109dcfb3611c8ba0d52930ec4a9478f547b2dd"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"unicode_names2_generator",
|
||||
@@ -10010,9 +10005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2_generator"
|
||||
version = "1.2.2"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f444b8bba042fe3c1251ffaca35c603f2dc2ccc08d595c65a8c4f76f3e8426c0"
|
||||
checksum = "b91e5b84611016120197efd7dc93ef76774f4e084cd73c9fb3ea4a86c570c56e"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"log",
|
||||
@@ -10054,7 +10049,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
"webpki-roots 0.26.5",
|
||||
"webpki-roots 0.26.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10211,20 +10206,19 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -10237,9 +10231,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.43"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed"
|
||||
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -10249,9 +10243,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -10259,9 +10253,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -10272,19 +10266,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.93"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.43"
|
||||
version = "0.3.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68497a05fb21143a08a7d24fc81763384a3072ee43c44e86aad1744d6adef9d9"
|
||||
checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"minicov",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
@@ -10293,9 +10286,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.43"
|
||||
version = "0.3.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b8220be1fa9e4c889b30fd207d4906657e7e90b12e0e6b0c8b8d8709f5de021"
|
||||
checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -10326,9 +10319,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.70"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
|
||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -10352,9 +10345,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.5"
|
||||
version = "0.26.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a"
|
||||
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
@@ -10389,7 +10382,7 @@ version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
|
||||
dependencies = [
|
||||
"redox_syscall 0.5.3",
|
||||
"redox_syscall 0.5.5",
|
||||
"wasite",
|
||||
"web-sys",
|
||||
]
|
||||
@@ -10433,7 +10426,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -10475,7 +10468,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -10509,6 +10502,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
"mail-parser",
|
||||
"matchit",
|
||||
"mime_guess",
|
||||
"native-tls",
|
||||
"object_store",
|
||||
@@ -10559,7 +10553,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
@@ -10577,7 +10571,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
@@ -10590,7 +10584,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@@ -10634,7 +10628,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-git-sync"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"rsmq_async",
|
||||
@@ -10649,7 +10643,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-indexer"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -10670,7 +10664,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"serde",
|
||||
@@ -10679,7 +10673,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10691,7 +10685,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -10703,7 +10697,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10715,7 +10709,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-php"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.13.0",
|
||||
@@ -10726,7 +10720,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.13.0",
|
||||
@@ -10737,7 +10731,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -10755,7 +10749,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-rust"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -10772,7 +10766,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10784,7 +10778,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -10802,7 +10796,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.15",
|
||||
@@ -10818,11 +10812,22 @@ dependencies = [
|
||||
"windmill-parser-rust",
|
||||
"windmill-parser-sql",
|
||||
"windmill-parser-ts",
|
||||
"windmill-parser-yaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-yaml"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde_json",
|
||||
"windmill-parser",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -10855,7 +10860,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-sql-datatype-parser-wasm"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
@@ -10865,7 +10870,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -10933,7 +10938,9 @@ dependencies = [
|
||||
"windmill-parser-rust",
|
||||
"windmill-parser-sql",
|
||||
"windmill-parser-ts",
|
||||
"windmill-parser-yaml",
|
||||
"windmill-queue",
|
||||
"yaml-rust",
|
||||
"zstd 0.12.4",
|
||||
]
|
||||
|
||||
@@ -11135,9 +11142,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.18"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
|
||||
checksum = "c52ac009d615e79296318c1bcce2d422aaca15ad08515e344feeda07df67a587"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -11193,6 +11200,15 @@ dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -23,10 +23,11 @@ members = [
|
||||
"./parsers/windmill-parser-py",
|
||||
"./parsers/windmill-parser-py-imports",
|
||||
"./parsers/windmill-sql-datatype-parser-wasm",
|
||||
"./parsers/windmill-parser-yaml",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.394.2"
|
||||
version = "1.399.0"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -118,6 +119,7 @@ windmill-parser-py = { path = "./parsers/windmill-parser-py" }
|
||||
windmill-parser-py-imports = { path = "./parsers/windmill-parser-py-imports" }
|
||||
windmill-parser-go = { path = "./parsers/windmill-parser-go" }
|
||||
windmill-parser-rust = { path = "./parsers/windmill-parser-rust" }
|
||||
windmill-parser-yaml = { path = "./parsers/windmill-parser-yaml" }
|
||||
windmill-parser-bash = { path = "./parsers/windmill-parser-bash" }
|
||||
windmill-parser-sql = { path = "./parsers/windmill-parser-sql" }
|
||||
windmill-parser-graphql = { path = "./parsers/windmill-parser-graphql" }
|
||||
@@ -219,7 +221,7 @@ rsmq_async = { version = "5.1.5" }
|
||||
gosyn = "0.2.6"
|
||||
bytes = "1.4.0"
|
||||
gethostname = "0.4.3"
|
||||
wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen = "=0.2.92"
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
convert_case = "0.6.0"
|
||||
@@ -250,6 +252,7 @@ indexmap = { version = "2.2.5", features = ["serde"]}
|
||||
tokio-native-tls = "^0"
|
||||
openssl = "=0.10"
|
||||
mail-parser = "^0"
|
||||
matchit = "=0.7.3"
|
||||
|
||||
datafusion = "39.0.0"
|
||||
object_store = { version = "0.10.0", features = ["aws", "azure"] }
|
||||
@@ -277,3 +280,4 @@ toml = "0.7"
|
||||
syn = { version = "2.0.74", features = ["full"] }
|
||||
quote = "1.0.36"
|
||||
regex-lite = "0.1.6"
|
||||
yaml-rust = "0.4.5"
|
||||
|
||||
@@ -1 +1 @@
|
||||
3d8ce9f1f15de94a40a0c349c7769598041a0d8a
|
||||
3d37b6c31155265d8d026ae9d6ced0b433078f87
|
||||
@@ -0,0 +1 @@
|
||||
-- Add down migration script here
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Add up migration script here
|
||||
ALTER TYPE SCRIPT_LANG ADD VALUE IF NOT EXISTS 'ansible';
|
||||
UPDATE config set config = jsonb_set(config, '{worker_tags}', config->'worker_tags' || '["ansible"]'::jsonb) where name = 'worker__default' and config @> '{"worker_tags": ["deno", "python3", "go", "bash", "powershell", "dependency", "flow", "hub", "other", "bun", "php", "rust"]}'::jsonb AND NOT config->'worker_tags' @> '"ansible"'::jsonb;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Add down migration script here
|
||||
ALTER TABLE resource_type
|
||||
DROP COLUMN format_extension;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Add up migration script here
|
||||
ALTER TABLE resource_type
|
||||
ADD COLUMN format_extension VARCHAR(20);
|
||||
7
backend/migrations/20240917172503_job_routing.down.sql
Normal file
7
backend/migrations/20240917172503_job_routing.down.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- Add down migration script here
|
||||
DROP TABLE http_trigger;
|
||||
DROP TYPE http_method;
|
||||
|
||||
ALTER TABLE script DROP COLUMN has_preprocessor;
|
||||
|
||||
DROP FUNCTION prevent_route_path_change();
|
||||
61
backend/migrations/20240917172503_job_routing.up.sql
Normal file
61
backend/migrations/20240917172503_job_routing.up.sql
Normal file
@@ -0,0 +1,61 @@
|
||||
-- Add up migration script here
|
||||
CREATE TYPE http_method AS ENUM ('get', 'post', 'put', 'delete', 'patch');
|
||||
|
||||
CREATE TABLE http_trigger (
|
||||
path VARCHAR(255) NOT NULL,
|
||||
route_path VARCHAR(255) NOT NULL,
|
||||
route_path_key VARCHAR(255) NOT NULL,
|
||||
script_path VARCHAR(255) NOT NULL,
|
||||
is_flow BOOLEAN NOT NULL,
|
||||
workspace_id VARCHAR(50) NOT NULL,
|
||||
edited_by VARCHAR(50) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
edited_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
extra_perms JSONB NOT NULL DEFAULT '{}',
|
||||
is_async BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
requires_auth BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
http_method http_method NOT NULL,
|
||||
PRIMARY KEY (path, workspace_id)
|
||||
);
|
||||
|
||||
|
||||
GRANT SELECT, UPDATE ON http_trigger TO windmill_user;
|
||||
GRANT ALL ON http_trigger TO windmill_admin;
|
||||
|
||||
ALTER TABLE http_trigger ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY see_folder_extra_perms_user_select ON http_trigger FOR SELECT TO windmill_user
|
||||
USING (SPLIT_PART(http_trigger.path, '/', 1) = 'f' AND SPLIT_PART(http_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_read'), ',')::text[]));
|
||||
CREATE POLICY see_folder_extra_perms_user_update ON http_trigger FOR UPDATE TO windmill_user
|
||||
USING (SPLIT_PART(http_trigger.path, '/', 1) = 'f' AND SPLIT_PART(http_trigger.path, '/', 2) = any(regexp_split_to_array(current_setting('session.folders_write'), ',')::text[]));
|
||||
|
||||
|
||||
CREATE POLICY see_extra_perms_user_select ON http_trigger FOR SELECT TO windmill_user
|
||||
USING (extra_perms ? CONCAT('u/', current_setting('session.user')));
|
||||
CREATE POLICY see_extra_perms_user_update ON http_trigger FOR UPDATE TO windmill_user
|
||||
USING ((extra_perms ->> CONCAT('u/', current_setting('session.user')))::boolean);
|
||||
|
||||
CREATE POLICY see_extra_perms_groups_select ON http_trigger FOR SELECT TO windmill_user
|
||||
USING (extra_perms ?| regexp_split_to_array(current_setting('session.pgroups'), ',')::text[]);
|
||||
CREATE POLICY see_extra_perms_groups_update ON http_trigger FOR UPDATE TO windmill_user
|
||||
USING (exists(
|
||||
SELECT key, value FROM jsonb_each_text(extra_perms)
|
||||
WHERE SPLIT_PART(key, '/', 1) = 'g' AND key = ANY(regexp_split_to_array(current_setting('session.pgroups'), ',')::text[])
|
||||
AND value::boolean));
|
||||
|
||||
CREATE OR REPLACE FUNCTION prevent_route_path_change()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF CURRENT_USER <> 'windmill_admin' AND NEW.route_path <> OLD.route_path THEN
|
||||
RAISE EXCEPTION 'Modification of route_path is only allowed by admins';
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER check_route_path_change
|
||||
BEFORE UPDATE ON http_trigger
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION prevent_route_path_change();
|
||||
|
||||
ALTER TABLE script ADD COLUMN has_preprocessor BOOLEAN;
|
||||
@@ -0,0 +1 @@
|
||||
-- Add down migration script here
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Add up migration script here
|
||||
INSERT INTO global_settings (name, value)
|
||||
SELECT 'smtp_settings', config
|
||||
FROM config
|
||||
WHERE name = 'server'
|
||||
ON CONFLICT (name) DO UPDATE SET value = excluded.value;
|
||||
|
||||
DELETE FROM config WHERE name = 'server';
|
||||
@@ -16,7 +16,13 @@ pub fn parse_bash_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_bash_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing bash script".to_string()))
|
||||
}
|
||||
@@ -26,7 +32,13 @@ pub fn parse_powershell_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_powershell_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing powershell script".to_string()))
|
||||
}
|
||||
@@ -173,7 +185,8 @@ non_required="${5:-}"
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ pub fn parse_go_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Ok(MainArgSignature {
|
||||
@@ -49,6 +50,7 @@ pub fn parse_go_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -241,7 +243,8 @@ func main(x int, y string, z bool, l []string, o struct { Name string `json:"nam
|
||||
oidx: None
|
||||
},
|
||||
],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,13 @@ pub fn parse_graphql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_graphql_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -119,7 +125,8 @@ query($i: Int, $arr: [String]!, $wahoo: String = "wahoo") {
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ pub fn parse_php_signature(
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Ok(MainArgSignature {
|
||||
@@ -89,6 +90,7 @@ pub fn parse_php_signature(
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -159,7 +161,8 @@ function main(string $input1 = \"hey\", bool $input2 = false, int $input3 = 3, f
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -63,9 +63,17 @@ pub fn parse_python_signature(
|
||||
) -> anyhow::Result<MainArgSignature> {
|
||||
let main_name = override_main.unwrap_or("main".to_string());
|
||||
|
||||
let has_preprocessor = !filter_non_main(code, "preprocessor").is_empty();
|
||||
|
||||
let filtered_code = filter_non_main(code, &main_name);
|
||||
if filtered_code.is_empty() {
|
||||
return Err(anyhow::anyhow!("No main function found".to_string(),));
|
||||
return Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: Some(has_preprocessor),
|
||||
});
|
||||
}
|
||||
let ast = Suite::parse(&filtered_code, "main.py")
|
||||
.map_err(|e| anyhow::anyhow!("Error parsing code: {}", e.to_string()))?;
|
||||
@@ -119,6 +127,7 @@ pub fn parse_python_signature(
|
||||
})
|
||||
.collect(),
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(has_preprocessor),
|
||||
})
|
||||
} else {
|
||||
Ok(MainArgSignature {
|
||||
@@ -126,6 +135,7 @@ pub fn parse_python_signature(
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: Some(has_preprocessor),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -325,6 +335,7 @@ def main(test1: str, name: datetime.datetime = datetime.now(), byte: bytes = byt
|
||||
},
|
||||
],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -389,6 +400,7 @@ def main(test1: str,
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -448,6 +460,7 @@ def main(test1: str,
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -491,6 +504,7 @@ def main(test1: Literal["foo", "bar"], test2: List[Literal["foo", "bar"]]): retu
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -521,6 +535,59 @@ def main(test1: DynSelect_foo): return
|
||||
oidx: None
|
||||
}],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_sig_6() -> anyhow::Result<()> {
|
||||
let code = r#"
|
||||
|
||||
import os
|
||||
|
||||
def hello(): return
|
||||
|
||||
"#;
|
||||
//println!("{}", serde_json::to_string()?);
|
||||
assert_eq!(
|
||||
parse_python_signature(code, None)?,
|
||||
MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_python_sig_7() -> anyhow::Result<()> {
|
||||
let code = r#"
|
||||
|
||||
import os
|
||||
|
||||
def preprocessor(): return
|
||||
|
||||
def main(): return
|
||||
|
||||
|
||||
|
||||
"#;
|
||||
//println!("{}", serde_json::to_string()?);
|
||||
assert_eq!(
|
||||
parse_python_signature(code, None)?,
|
||||
MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(true)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ pub fn parse_rust_signature(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Ok(MainArgSignature {
|
||||
@@ -36,6 +37,7 @@ pub fn parse_rust_signature(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -455,10 +457,7 @@ fn main(
|
||||
assert_eq!(ret.args[2].typ, Typ::Str(None));
|
||||
|
||||
assert_eq!(ret.args[3].name, "my_string_vec");
|
||||
assert_eq!(
|
||||
ret.args[3].otyp,
|
||||
Some("Vec < String >".to_string())
|
||||
);
|
||||
assert_eq!(ret.args[3].otyp, Some("Vec < String >".to_string()));
|
||||
assert_eq!(ret.args[3].typ, Typ::List(Box::new(Typ::Str(None))));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,13 @@ pub fn parse_mysql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_mysql_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -30,7 +36,13 @@ pub fn parse_pgsql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_pg_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -40,7 +52,13 @@ pub fn parse_bigquery_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_bigquery_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -50,7 +68,13 @@ pub fn parse_snowflake_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_snowflake_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -60,7 +84,13 @@ pub fn parse_mssql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let parsed = parse_mssql_file(&code)?;
|
||||
if let Some(x) = parsed {
|
||||
let args = x;
|
||||
Ok(MainArgSignature { star_args: false, star_kwargs: false, args, no_main_func: None })
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("Error parsing sql".to_string()))
|
||||
}
|
||||
@@ -570,7 +600,8 @@ SELECT * FROM table WHERE token=$1::TEXT AND image=$2::BIGINT
|
||||
oidx: Some(2),
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -618,7 +649,8 @@ SELECT $2::TEXT;
|
||||
oidx: Some(3),
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -744,7 +776,8 @@ SELECT ?, ?;
|
||||
oidx: None,
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -791,7 +824,8 @@ SELECT :param2;
|
||||
oidx: None,
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -830,7 +864,8 @@ SELECT @token;
|
||||
oidx: None,
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -877,7 +912,8 @@ SELECT ?;
|
||||
oidx: None,
|
||||
}
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
@@ -924,7 +960,8 @@ SELECT @p2;
|
||||
oidx: None,
|
||||
},
|
||||
],
|
||||
no_main_func: None
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -159,6 +159,14 @@ pub fn parse_deno_signature(
|
||||
})?
|
||||
.body;
|
||||
|
||||
let has_preprocessor = ast.iter().any(|x| match x {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
|
||||
decl: Decl::Fn(FnDecl { ident: Ident { sym, .. }, .. }),
|
||||
..
|
||||
})) => &sym.to_string() == "preprocessor",
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let main_name = main_override.unwrap_or("main".to_string());
|
||||
let params = ast.into_iter().find_map(|x| match x {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
|
||||
@@ -178,6 +186,7 @@ pub fn parse_deno_signature(
|
||||
.map(|x| parse_param(x, &cm, skip_dflt, &mut c))
|
||||
.collect::<anyhow::Result<Vec<Arg>>>()?,
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(has_preprocessor),
|
||||
};
|
||||
Ok(r)
|
||||
} else {
|
||||
@@ -186,6 +195,7 @@ pub fn parse_deno_signature(
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: Some(true),
|
||||
has_preprocessor: Some(has_preprocessor),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ ts-parser = [ "dep:windmill-parser-ts"]
|
||||
php-parser = [ "dep:windmill-parser-php"]
|
||||
rust-parser = [ "dep:windmill-parser-rust"]
|
||||
graphql-parser = [ "dep:windmill-parser-graphql"]
|
||||
ansible-parser = [ "dep:windmill-parser-yaml"]
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
@@ -37,6 +38,7 @@ windmill-parser-ts = { workspace = true, optional = true }
|
||||
windmill-parser-php = { workspace = true, optional = true }
|
||||
windmill-parser-graphql = { workspace = true, optional = true }
|
||||
windmill-parser-rust = { workspace = true, optional = true }
|
||||
windmill-parser-yaml = { workspace = true, optional = true }
|
||||
wasm-bindgen.workspace = true
|
||||
serde_json.workspace = true
|
||||
getrandom = { workspace = true, features = ["js"] }
|
||||
|
||||
50
backend/parsers/windmill-parser-wasm/build-pkgs-mac.sh
Executable file
50
backend/parsers/windmill-parser-wasm/build-pkgs-mac.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
set -eou pipefail
|
||||
|
||||
# full pkg
|
||||
OUT_DIR="pkg"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --all-features \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
|
||||
# bun and deno
|
||||
OUT_DIR="pkg-ts"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "ts-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-ts"/' $OUT_DIR/package.json
|
||||
|
||||
# sql languages, graphql and bash/powershell, since they all use regex
|
||||
OUT_DIR="pkg-regex"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR \
|
||||
--features "sql-parser,graphql-parser,bash-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-regex"/' $OUT_DIR/package.json
|
||||
|
||||
# python
|
||||
OUT_DIR="pkg-py"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "py-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-py"/' $OUT_DIR/package.json
|
||||
|
||||
# go
|
||||
OUT_DIR="pkg-go"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "go-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-go"/' $OUT_DIR/package.json
|
||||
|
||||
# php
|
||||
OUT_DIR="pkg-php"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "php-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-php"/' $OUT_DIR/package.json
|
||||
|
||||
# rust
|
||||
OUT_DIR="pkg-rust"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "rust-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-rust"/' $OUT_DIR/package.json
|
||||
|
||||
# ansible
|
||||
OUT_DIR="pkg-yaml"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "ansible-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i '' 's/"windmill-parser-wasm"/"windmill-parser-wasm-yaml"/' $OUT_DIR/package.json
|
||||
@@ -42,3 +42,9 @@ OUT_DIR="pkg-rust"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "rust-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i 's/"windmill-parser-wasm"/"windmill-parser-wasm-rust"/' $OUT_DIR/package.json
|
||||
|
||||
# ansible
|
||||
OUT_DIR="pkg-yaml"
|
||||
wasm-pack build --release --target web --out-dir $OUT_DIR --features "ansible-parser" \
|
||||
-Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort
|
||||
sed -i 's/"windmill-parser-wasm"/"windmill-parser-wasm-yaml"/' $OUT_DIR/package.json
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -eou pipefail
|
||||
|
||||
deno task wasmbuild --out ../../../cli/wasm/ -p windmill-parser-wasm
|
||||
deno task wasmbuild --out ../../../cli/wasm/ -p windmill-parser-wasm --all-features
|
||||
|
||||
126
backend/parsers/windmill-parser-wasm/lib/windmill_parser_wasm.generated.d.ts
vendored
Normal file
126
backend/parsers/windmill-parser-wasm/lib/windmill_parser_wasm.generated.d.ts
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// deno-lint-ignore-file
|
||||
// deno-fmt-ignore-file
|
||||
|
||||
export interface InstantiateResult {
|
||||
instance: WebAssembly.Instance;
|
||||
exports: {
|
||||
parse_deno: typeof parse_deno;
|
||||
parse_outputs: typeof parse_outputs;
|
||||
parse_ts_imports: typeof parse_ts_imports;
|
||||
parse_bash: typeof parse_bash;
|
||||
parse_powershell: typeof parse_powershell;
|
||||
parse_go: typeof parse_go;
|
||||
parse_python: typeof parse_python;
|
||||
parse_sql: typeof parse_sql;
|
||||
parse_mysql: typeof parse_mysql;
|
||||
parse_bigquery: typeof parse_bigquery;
|
||||
parse_snowflake: typeof parse_snowflake;
|
||||
parse_mssql: typeof parse_mssql;
|
||||
parse_db_resource: typeof parse_db_resource;
|
||||
parse_graphql: typeof parse_graphql;
|
||||
parse_php: typeof parse_php;
|
||||
parse_rust: typeof parse_rust
|
||||
};
|
||||
}
|
||||
|
||||
/** Gets if the Wasm module has been instantiated. */
|
||||
export function isInstantiated(): boolean;
|
||||
|
||||
/** Options for instantiating a Wasm instance. */
|
||||
export interface InstantiateOptions {
|
||||
/** Optional url to the Wasm file to instantiate. */
|
||||
url?: URL;
|
||||
/** Callback to decompress the raw Wasm file bytes before instantiating. */
|
||||
decompress?: (bytes: Uint8Array) => Uint8Array;
|
||||
}
|
||||
|
||||
/** Instantiates an instance of the Wasm module returning its functions.
|
||||
* @remarks It is safe to call this multiple times and once successfully
|
||||
* loaded it will always return a reference to the same object. */
|
||||
export function instantiate(opts?: InstantiateOptions): Promise<InstantiateResult["exports"]>;
|
||||
|
||||
/** Instantiates an instance of the Wasm module along with its exports.
|
||||
* @remarks It is safe to call this multiple times and once successfully
|
||||
* loaded it will always return a reference to the same object. */
|
||||
export function instantiateWithInstance(opts?: InstantiateOptions): Promise<InstantiateResult>;
|
||||
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_deno(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_outputs(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_ts_imports(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_bash(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_powershell(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_go(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_python(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_sql(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_mysql(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_bigquery(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_snowflake(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_mssql(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export function parse_db_resource(code: string): string | undefined;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_graphql(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_php(code: string): string;
|
||||
/**
|
||||
* @param {string} code
|
||||
* @returns {string}
|
||||
*/
|
||||
export function parse_rust(code: string): string;
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -21,3 +21,6 @@ popd
|
||||
|
||||
pushd "pkg-rust" && npm publish ${args}
|
||||
popd
|
||||
|
||||
pushd "pkg-yaml" && npm publish ${args}
|
||||
popd
|
||||
|
||||
@@ -17,8 +17,12 @@ fn wrap_sig(r: anyhow::Result<MainArgSignature>) -> String {
|
||||
|
||||
#[cfg(feature = "ts-parser")]
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_deno(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_ts::parse_deno_signature(code, false, None))
|
||||
pub fn parse_deno(code: &str, main_override: Option<String>) -> String {
|
||||
wrap_sig(windmill_parser_ts::parse_deno_signature(
|
||||
code,
|
||||
false,
|
||||
main_override,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "ts-parser")]
|
||||
@@ -65,8 +69,11 @@ pub fn parse_go(code: &str) -> String {
|
||||
|
||||
#[cfg(feature = "py-parser")]
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_python(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_py::parse_python_signature(code, None))
|
||||
pub fn parse_python(code: &str, main_override: Option<String>) -> String {
|
||||
wrap_sig(windmill_parser_py::parse_python_signature(
|
||||
code,
|
||||
main_override,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "sql-parser")]
|
||||
@@ -122,3 +129,9 @@ pub fn parse_php(code: &str) -> String {
|
||||
pub fn parse_rust(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_rust::parse_rust_signature(code))
|
||||
}
|
||||
|
||||
#[cfg(feature = "ansible-parser")]
|
||||
#[wasm_bindgen]
|
||||
pub fn parse_ansible(code: &str) -> String {
|
||||
wrap_sig(windmill_parser_yaml::parse_ansible_sig(code))
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@ export function main(test1?: string, test2: string = \"burkina\",
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -215,7 +216,8 @@ export function main(test2 = \"burkina\",
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -264,7 +266,8 @@ export function main(foo: FooBar, {a, b}: FooBar, {c, d}: FooBar = {a: \"foo\",
|
||||
oidx: None
|
||||
}
|
||||
],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -294,7 +297,8 @@ export function main(foo: (\"foo\" | \"bar\")[]) {
|
||||
has_default: false,
|
||||
oidx: None
|
||||
}],
|
||||
no_main_func: Some(false)
|
||||
no_main_func: Some(false),
|
||||
has_preprocessor: Some(false)
|
||||
}
|
||||
);
|
||||
|
||||
@@ -434,6 +438,7 @@ Write-Output 'Testing...'
|
||||
}
|
||||
],
|
||||
no_main_func: None,
|
||||
has_preprocessor: None
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
15
backend/parsers/windmill-parser-yaml/Cargo.toml
Normal file
15
backend/parsers/windmill-parser-yaml/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "windmill-parser-yaml"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "windmill_parser_yaml"
|
||||
path = "./src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
yaml-rust.workspace = true
|
||||
windmill-parser.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
482
backend/parsers/windmill-parser-yaml/src/lib.rs
Normal file
482
backend/parsers/windmill-parser-yaml/src/lib.rs
Normal file
@@ -0,0 +1,482 @@
|
||||
use anyhow::anyhow;
|
||||
use serde_json::json;
|
||||
use windmill_parser::{Arg, MainArgSignature, ObjectProperty, Typ};
|
||||
use yaml_rust::{Yaml, YamlEmitter, YamlLoader};
|
||||
|
||||
pub fn parse_ansible_sig(inner_content: &str) -> anyhow::Result<MainArgSignature> {
|
||||
let docs = YamlLoader::load_from_str(inner_content)
|
||||
.map_err(|e| anyhow!("Failed to parse yaml: {}", e))?;
|
||||
|
||||
if docs.len() < 2 {
|
||||
return Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args: vec![],
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
});
|
||||
}
|
||||
|
||||
let mut args = vec![];
|
||||
if let Yaml::Hash(doc) = &docs[0] {
|
||||
for (key, value) in doc {
|
||||
match key {
|
||||
Yaml::String(key) if key == "extra_vars" => {
|
||||
if let Yaml::Hash(v) = &value {
|
||||
for (key, arg) in v {
|
||||
if let Yaml::String(arg_name) = key {
|
||||
// if not then it is a static resource or var, so skip
|
||||
// it will be fetched by the worker
|
||||
if let ArgTyp::Typ(typ) = parse_ansible_arg_typ(arg) {
|
||||
let default = get_default_for_typ(&arg);
|
||||
args.push(Arg {
|
||||
name: arg_name.to_string(),
|
||||
otyp: None,
|
||||
typ,
|
||||
has_default: default.is_some(),
|
||||
default,
|
||||
oidx: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Yaml::String(key) if key == "inventory" => {
|
||||
for inv in parse_inventories(value)? {
|
||||
if inv.pinned_resource.is_some() {
|
||||
continue;
|
||||
}
|
||||
args.push(Arg {
|
||||
name: inv.name,
|
||||
otyp: None,
|
||||
typ: Typ::Resource(inv.resource_type.unwrap_or("Unknown".to_string())),
|
||||
has_default: inv.default.is_some(),
|
||||
default: inv.default.map(|v| json!(format!("$res:{}", v))),
|
||||
oidx: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(MainArgSignature {
|
||||
star_args: false,
|
||||
star_kwargs: false,
|
||||
args,
|
||||
no_main_func: None,
|
||||
has_preprocessor: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_default_for_typ(arg: &Yaml) -> Option<serde_json::Value> {
|
||||
if let Yaml::Hash(arg) = arg {
|
||||
if let Some(def) = arg.get(&Yaml::String("default".to_string())) {
|
||||
if let Some(Yaml::String(typ)) = arg.get(&Yaml::String("type".to_string())) {
|
||||
if let Yaml::String(path) = def {
|
||||
if typ.as_str() == "windmill_resource" {
|
||||
return Some(serde_json::Value::String(format!("$res:{}", path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(yaml_to_json(def));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
enum ArgTyp {
|
||||
Typ(Typ),
|
||||
StaticVar(String),
|
||||
StaticResource(String),
|
||||
}
|
||||
|
||||
fn parse_ansible_arg_typ(arg: &Yaml) -> ArgTyp {
|
||||
if let Yaml::Hash(a) = arg {
|
||||
if let Some(Yaml::String(typ)) = a.get(&Yaml::String("type".to_string())) {
|
||||
if typ.as_str() == "windmill_variable" {
|
||||
if let Some(Yaml::String(variable_path)) =
|
||||
a.get(&Yaml::String("variable".to_string()))
|
||||
{
|
||||
return ArgTyp::StaticVar(variable_path.to_string());
|
||||
}
|
||||
}
|
||||
if typ.as_str() == "windmill_resource" {
|
||||
if let Some(Yaml::String(resource_path)) =
|
||||
a.get(&Yaml::String("resource".to_string()))
|
||||
{
|
||||
return ArgTyp::StaticResource(resource_path.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ArgTyp::Typ(parse_ansible_typ(arg))
|
||||
}
|
||||
|
||||
fn parse_ansible_typ(arg: &Yaml) -> Typ {
|
||||
if let Yaml::Hash(arg) = arg {
|
||||
if let Some(Yaml::String(typ)) = arg.get(&Yaml::String("type".to_string())) {
|
||||
match typ.as_ref() {
|
||||
"boolean" => Typ::Bool,
|
||||
"integer" => Typ::Int,
|
||||
"number" => Typ::Float,
|
||||
"string" => {
|
||||
if let Some(Yaml::String(fmt)) = arg.get(&Yaml::String("format".to_string())) {
|
||||
match fmt.as_ref() {
|
||||
"date-time" | "datetime" => Typ::Datetime,
|
||||
"email" => Typ::Email,
|
||||
_ => Typ::Str(None),
|
||||
}
|
||||
} else {
|
||||
Typ::Str(None)
|
||||
}
|
||||
}
|
||||
"object" => {
|
||||
if let Some(Yaml::Hash(props)) =
|
||||
arg.get(&Yaml::String("properties".to_string()))
|
||||
{
|
||||
let mut prop_vec = vec![];
|
||||
for (key, value) in props {
|
||||
if let Yaml::String(key) = key {
|
||||
prop_vec.push(ObjectProperty {
|
||||
key: key.clone(),
|
||||
typ: Box::new(parse_ansible_typ(value)),
|
||||
})
|
||||
}
|
||||
}
|
||||
Typ::Object(prop_vec)
|
||||
} else {
|
||||
Typ::Object(vec![])
|
||||
}
|
||||
}
|
||||
"array" => {
|
||||
if let Some(items) = arg.get(&Yaml::String("items".to_string())) {
|
||||
Typ::List(Box::new(parse_ansible_typ(items)))
|
||||
} else {
|
||||
Typ::List(Box::new(Typ::Unknown))
|
||||
}
|
||||
}
|
||||
"windmill_resource" => {
|
||||
if let Some(Yaml::String(res_name)) =
|
||||
arg.get(&Yaml::String("resource_type".to_string()))
|
||||
{
|
||||
Typ::Resource(res_name.clone())
|
||||
} else {
|
||||
Typ::Resource("".to_string())
|
||||
}
|
||||
}
|
||||
_ => Typ::Unknown,
|
||||
}
|
||||
} else {
|
||||
Typ::Unknown
|
||||
}
|
||||
} else {
|
||||
Typ::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnsiblePlaybookOptions {
|
||||
// There are a lot more options
|
||||
// TODO: Add the options as customers require them
|
||||
// Add it here and then on the executors cmd_options
|
||||
pub verbosity: Option<String>,
|
||||
pub forks: Option<i64>,
|
||||
pub timeout: Option<i64>,
|
||||
pub flush_cache: Option<()>,
|
||||
pub force_handlers: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileResource {
|
||||
pub resource_path: String,
|
||||
pub target_path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnsibleInventory {
|
||||
pub default: Option<String>,
|
||||
pub name: String,
|
||||
resource_type: Option<String>,
|
||||
pub pinned_resource: Option<String>,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AnsibleRequirements {
|
||||
pub python_reqs: Vec<String>,
|
||||
pub collections: Option<String>,
|
||||
pub file_resources: Vec<FileResource>,
|
||||
pub inventories: Vec<AnsibleInventory>,
|
||||
pub vars: Vec<(String, String)>,
|
||||
pub resources: Vec<(String, String)>,
|
||||
pub options: AnsiblePlaybookOptions,
|
||||
}
|
||||
|
||||
fn parse_inventories(inventory_yaml: &Yaml) -> anyhow::Result<Vec<AnsibleInventory>> {
|
||||
if let Yaml::Array(arr) = inventory_yaml {
|
||||
let mut ret = vec![];
|
||||
for (i, inv) in arr.iter().enumerate() {
|
||||
if let Yaml::Hash(inv) = inv {
|
||||
let resource_type = inv
|
||||
.get(&Yaml::String("resource_type".to_string()))
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
let windmill_path = inv
|
||||
.get(&Yaml::String("default".to_string()))
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
let name = if i == 0 {
|
||||
"inventory.ini".to_string()
|
||||
} else {
|
||||
format!("inventory-{}.ini", i)
|
||||
};
|
||||
|
||||
let name = inv
|
||||
.get(&Yaml::String("name".to_string()))
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or(name.as_str())
|
||||
.to_string();
|
||||
|
||||
let pin = inv
|
||||
.get(&Yaml::String("resource".to_string()))
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
ret.push(AnsibleInventory {
|
||||
default: windmill_path,
|
||||
name,
|
||||
resource_type,
|
||||
pinned_resource: pin,
|
||||
});
|
||||
}
|
||||
}
|
||||
return Ok(ret);
|
||||
}
|
||||
return Err(anyhow!("Invalid inventory definition"));
|
||||
}
|
||||
|
||||
pub fn parse_ansible_reqs(
|
||||
inner_content: &str,
|
||||
) -> anyhow::Result<(String, Option<AnsibleRequirements>, String)> {
|
||||
let mut logs = String::new();
|
||||
let docs = YamlLoader::load_from_str(inner_content)
|
||||
.map_err(|e| anyhow!("Failed to parse yaml: {}", e))?;
|
||||
|
||||
if docs.len() < 2 {
|
||||
return Ok((logs, None, inner_content.to_string()));
|
||||
}
|
||||
|
||||
let opts = AnsiblePlaybookOptions {
|
||||
verbosity: None,
|
||||
forks: None,
|
||||
timeout: None,
|
||||
flush_cache: None,
|
||||
force_handlers: None,
|
||||
};
|
||||
let mut ret = AnsibleRequirements {
|
||||
python_reqs: vec![],
|
||||
collections: None,
|
||||
file_resources: vec![],
|
||||
inventories: vec![],
|
||||
vars: vec![],
|
||||
resources: vec![],
|
||||
options: opts,
|
||||
};
|
||||
|
||||
if let Yaml::Hash(doc) = &docs[0] {
|
||||
for (key, value) in doc {
|
||||
match key {
|
||||
Yaml::String(key) if key == "dependencies" => {
|
||||
if let Yaml::Hash(deps) = value {
|
||||
if let Some(galaxy_requirements) =
|
||||
deps.get(&Yaml::String("galaxy".to_string()))
|
||||
{
|
||||
let mut out_str = String::new();
|
||||
let mut emitter = YamlEmitter::new(&mut out_str);
|
||||
emitter.dump(galaxy_requirements)?;
|
||||
ret.collections = Some(out_str);
|
||||
}
|
||||
if let Some(Yaml::Array(py_reqs)) =
|
||||
deps.get(&Yaml::String("python".to_string()))
|
||||
{
|
||||
ret.python_reqs = py_reqs
|
||||
.iter()
|
||||
.map(|d| d.as_str().map(|s| s.to_string()))
|
||||
.filter_map(|x| x)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
Yaml::String(key) if key == "file_resources" => {
|
||||
if let Yaml::Array(file_resources) = value {
|
||||
let resources: anyhow::Result<Vec<FileResource>> =
|
||||
file_resources.iter().map(parse_file_resource).collect();
|
||||
ret.file_resources.append(&mut resources?);
|
||||
}
|
||||
}
|
||||
Yaml::String(key) if key == "extra_vars" => {
|
||||
if let Yaml::Hash(v) = &value {
|
||||
for (key, arg) in v {
|
||||
if let Yaml::String(arg_name) = key {
|
||||
match parse_ansible_arg_typ(arg) {
|
||||
ArgTyp::StaticVar(p) => {
|
||||
ret.vars
|
||||
.push((arg_name.to_string(), format!("$var:{}", p)));
|
||||
}
|
||||
ArgTyp::StaticResource(p) => {
|
||||
ret.resources
|
||||
.push((arg_name.to_string(), format!("$res:{}", p)));
|
||||
}
|
||||
ArgTyp::Typ(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Yaml::String(key) if key == "inventory" => {
|
||||
ret.inventories = parse_inventories(value)?;
|
||||
}
|
||||
Yaml::String(key) if key == "options" => {
|
||||
if let Yaml::Array(opts) = &value {
|
||||
ret.options = parse_ansible_options(opts);
|
||||
}
|
||||
}
|
||||
Yaml::String(key) => logs.push_str(&format!("\nUnknown field `{}`. Ignoring", key)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut out_str = String::new();
|
||||
let mut emitter = YamlEmitter::new(&mut out_str);
|
||||
|
||||
for i in 1..docs.len() {
|
||||
emitter.dump(&docs[i])?;
|
||||
}
|
||||
Ok((logs, Some(ret), out_str))
|
||||
}
|
||||
|
||||
fn parse_ansible_options(opts: &Vec<Yaml>) -> AnsiblePlaybookOptions {
|
||||
let mut ret = AnsiblePlaybookOptions {
|
||||
verbosity: None,
|
||||
forks: None,
|
||||
timeout: None,
|
||||
flush_cache: None,
|
||||
force_handlers: None,
|
||||
};
|
||||
for opt in opts {
|
||||
if let Yaml::String(o) = opt {
|
||||
match o.as_str() {
|
||||
"flush_cache" => {
|
||||
ret.flush_cache = Some(());
|
||||
}
|
||||
"force_handlers" => {
|
||||
ret.force_handlers = Some(());
|
||||
}
|
||||
s if count_consecutive_vs(s) > 0 => {
|
||||
ret.verbosity = Some("v".repeat(count_consecutive_vs(s).min(6)));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if let Yaml::Hash(m) = opt {
|
||||
if let Some((Yaml::String(name), value)) = m.iter().last() {
|
||||
match name.as_str() {
|
||||
"forks" => {
|
||||
if let Yaml::Integer(count) = value {
|
||||
ret.forks = Some(*count);
|
||||
}
|
||||
}
|
||||
"timeout" => {
|
||||
if let Yaml::Integer(timeout) = value {
|
||||
ret.timeout = Some(*timeout);
|
||||
}
|
||||
}
|
||||
"verbosity" => {
|
||||
if let Yaml::String(verbosity) = value {
|
||||
let c = count_consecutive_vs(verbosity);
|
||||
if c > 0 && c <= 6 {
|
||||
ret.verbosity = Some("v".repeat(c.min(6)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
fn count_consecutive_vs(s: &str) -> usize {
|
||||
let mut max_count = 0;
|
||||
let mut current_count = 0;
|
||||
|
||||
for c in s.chars() {
|
||||
if c == 'v' {
|
||||
current_count += 1;
|
||||
if current_count == 6 {
|
||||
return 6; // Stop early if we reach 6
|
||||
}
|
||||
} else {
|
||||
current_count = 0; // Reset count if the character is not 'v'
|
||||
}
|
||||
max_count = max_count.max(current_count);
|
||||
}
|
||||
|
||||
max_count
|
||||
}
|
||||
|
||||
fn parse_file_resource(yaml: &Yaml) -> anyhow::Result<FileResource> {
|
||||
if let Yaml::Hash(f) = yaml {
|
||||
if let Some(Yaml::String(resource_path)) = f.get(&Yaml::String("resource".to_string())) {
|
||||
let target_path = f
|
||||
.get(&Yaml::String("target".to_string()))
|
||||
.and_then(|x| x.as_str())
|
||||
.map(|x| x.to_string())
|
||||
.ok_or(anyhow!(
|
||||
"No `target` provided for file resource {}. Please input a target relative path for the ansible playbook to see this file.",
|
||||
resource_path
|
||||
))?;
|
||||
return Ok(FileResource { resource_path: resource_path.clone(), target_path });
|
||||
}
|
||||
return Err(anyhow!(
|
||||
"File resource should have a `resource` field, linking to a text file resource"
|
||||
));
|
||||
}
|
||||
return Err(anyhow!("Invalid file resource: Should be a dictionary."));
|
||||
}
|
||||
|
||||
fn yaml_to_json(yaml: &Yaml) -> serde_json::Value {
|
||||
match yaml {
|
||||
Yaml::Array(arr) => {
|
||||
let json_array: Vec<serde_json::Value> = arr.into_iter().map(yaml_to_json).collect();
|
||||
serde_json::Value::Array(json_array)
|
||||
}
|
||||
Yaml::Hash(hash) => {
|
||||
let json_object = hash
|
||||
.into_iter()
|
||||
.map(|(k, v)| {
|
||||
let key = match k {
|
||||
Yaml::String(s) => s.clone(),
|
||||
_ => k.as_str().unwrap_or("").to_string(),
|
||||
};
|
||||
(key, yaml_to_json(v))
|
||||
})
|
||||
.collect();
|
||||
serde_json::Value::Object(json_object)
|
||||
}
|
||||
Yaml::String(s) => serde_json::Value::String(s.to_string()),
|
||||
Yaml::Integer(i) => serde_json::Value::Number(i.clone().into()),
|
||||
Yaml::Real(r) => serde_json::Value::Number(r.parse().unwrap_or(0.into())),
|
||||
Yaml::Boolean(b) => serde_json::Value::Bool(*b),
|
||||
Yaml::Null => serde_json::Value::Null,
|
||||
_ => serde_json::Value::Null,
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ pub struct MainArgSignature {
|
||||
pub star_kwargs: bool,
|
||||
pub args: Vec<Arg>,
|
||||
pub no_main_func: Option<bool>,
|
||||
pub has_preprocessor: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||
@@ -153,7 +154,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_mixed_delimiters() {
|
||||
assert_eq!(to_snake_case("test-Case_with Spaces"), "test_case_with_spaces");
|
||||
assert_eq!(
|
||||
to_snake_case("test-Case_with Spaces"),
|
||||
"test_case_with_spaces"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
use anyhow::Context;
|
||||
use git_version::git_version;
|
||||
use monitor::{send_current_log_file_to_object_store, send_logs_to_object_store};
|
||||
use monitor::{
|
||||
reload_timeout_wait_result_setting, send_current_log_file_to_object_store,
|
||||
send_logs_to_object_store,
|
||||
};
|
||||
use rand::Rng;
|
||||
use sqlx::{postgres::PgListener, Pool, Postgres};
|
||||
use std::{
|
||||
@@ -35,7 +38,7 @@ use windmill_common::{
|
||||
JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, NPM_CONFIG_REGISTRY_SETTING,
|
||||
OAUTH_SETTING, PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
|
||||
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
|
||||
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING,
|
||||
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
|
||||
},
|
||||
scripts::ScriptLang,
|
||||
stats_ee::schedule_stats,
|
||||
@@ -74,7 +77,7 @@ use crate::monitor::{
|
||||
reload_critical_error_channels_setting, reload_extra_pip_index_url_setting,
|
||||
reload_hub_base_url_setting, reload_job_default_timeout_setting, reload_jwt_secret_setting,
|
||||
reload_license_key, reload_npm_config_registry_setting, reload_pip_index_url_setting,
|
||||
reload_retention_period_setting, reload_scim_token_setting, reload_server_config,
|
||||
reload_retention_period_setting, reload_scim_token_setting, reload_smtp_config,
|
||||
reload_worker_config,
|
||||
};
|
||||
|
||||
@@ -173,7 +176,7 @@ async fn cache_hub_scripts(file_path: Option<String>) -> anyhow::Result<()> {
|
||||
None,
|
||||
&job_dir,
|
||||
"cache_init",
|
||||
windmill_worker::get_common_bun_proc_envs("").await,
|
||||
windmill_worker::get_common_bun_proc_envs(None).await,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
@@ -371,6 +374,7 @@ async fn windmill_main() -> anyhow::Result<()> {
|
||||
// migration code to avoid break
|
||||
windmill_api::migrate_db(&db).await?;
|
||||
}
|
||||
|
||||
let (killpill_tx, mut killpill_rx) = tokio::sync::broadcast::channel::<()>(2);
|
||||
let mut monitor_killpill_rx = killpill_tx.subscribe();
|
||||
let server_killpill_rx = killpill_tx.subscribe();
|
||||
@@ -562,9 +566,7 @@ Windmill Community Edition {GIT_VERSION}
|
||||
"notify_config_change" => {
|
||||
match n.payload() {
|
||||
"server" if server_mode => {
|
||||
tracing::info!("Server config change detected: {}", n.payload());
|
||||
|
||||
reload_server_config(&db).await;
|
||||
tracing::error!("Server config change detected but server config is obsolete: {}", n.payload());
|
||||
},
|
||||
a@ _ if worker_mode && a == format!("worker__{}", *WORKER_GROUP) => {
|
||||
tracing::info!("Worker config change detected: {}", n.payload());
|
||||
@@ -608,6 +610,12 @@ Windmill Community Edition {GIT_VERSION}
|
||||
tracing::error!("Error loading default tag per workspace workspaces: {e:#}");
|
||||
}
|
||||
}
|
||||
SMTP_SETTING => {
|
||||
reload_smtp_config(&db).await;
|
||||
},
|
||||
TIMEOUT_WAIT_RESULT_SETTING => {
|
||||
reload_timeout_wait_result_setting(&db).await
|
||||
},
|
||||
RETENTION_PERIOD_SECS_SETTING => {
|
||||
reload_retention_period_setting(&db).await
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@ use tokio::{
|
||||
#[cfg(feature = "embedding")]
|
||||
use windmill_api::embeddings::update_embeddings_db;
|
||||
use windmill_api::{
|
||||
jobs::TIMEOUT_WAIT_RESULT,
|
||||
oauth2_ee::{build_oauth_clients, OAuthClient},
|
||||
DEFAULT_BODY_LIMIT, IS_SECURE, OAUTH_CLIENTS, REQUEST_SIZE_LIMIT, SAML_METADATA, SCIM_TOKEN,
|
||||
};
|
||||
@@ -40,17 +41,17 @@ use windmill_common::{
|
||||
KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, NPM_CONFIG_REGISTRY_SETTING, OAUTH_SETTING,
|
||||
PIP_INDEX_URL_SETTING, REQUEST_SIZE_LIMIT_SETTING,
|
||||
REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING,
|
||||
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING,
|
||||
SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, TIMEOUT_WAIT_RESULT_SETTING,
|
||||
},
|
||||
jobs::QueuedJob,
|
||||
oauth2::REQUIRE_PREEXISTING_USER_FOR_OAUTH,
|
||||
server::load_server_config,
|
||||
server::load_smtp_config,
|
||||
tracing_init::JSON_FMT,
|
||||
users::truncate_token,
|
||||
utils::{now_from_db, rd_string, report_critical_error, Mode},
|
||||
worker::{
|
||||
load_worker_config, make_pull_query, make_suspended_pull_query, reload_custom_tags_setting,
|
||||
DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, SERVER_CONFIG, WORKER_CONFIG,
|
||||
DEFAULT_TAGS_PER_WORKSPACE, DEFAULT_TAGS_WORKSPACES, SMTP_CONFIG, WORKER_CONFIG,
|
||||
WORKER_GROUP,
|
||||
},
|
||||
BASE_URL, CRITICAL_ERROR_CHANNELS, DB, DEFAULT_HUB_BASE_URL, HUB_BASE_URL, JOB_RETENTION_SECS,
|
||||
@@ -172,8 +173,9 @@ pub async fn initial_load(
|
||||
reload_s3_cache_setting(&db).await;
|
||||
}
|
||||
|
||||
reload_smtp_config(&db).await;
|
||||
|
||||
if server_mode {
|
||||
reload_server_config(&db).await;
|
||||
reload_retention_period_setting(&db).await;
|
||||
reload_request_size(&db).await;
|
||||
reload_saml_metadata_setting(&db).await;
|
||||
@@ -698,6 +700,15 @@ pub async fn reload_scim_token_setting(db: &DB) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn reload_timeout_wait_result_setting(db: &DB) {
|
||||
reload_option_setting_with_tracing(
|
||||
db,
|
||||
TIMEOUT_WAIT_RESULT_SETTING,
|
||||
"TIMEOUT_WAIT_RESULT",
|
||||
TIMEOUT_WAIT_RESULT.clone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
pub async fn reload_saml_metadata_setting(db: &DB) {
|
||||
reload_option_setting_with_tracing(
|
||||
db,
|
||||
@@ -1045,7 +1056,7 @@ pub async fn monitor_db(
|
||||
|
||||
let worker_groups_alerts_f = async {
|
||||
#[cfg(feature = "enterprise")]
|
||||
if server_mode {
|
||||
if server_mode && !initial_load {
|
||||
worker_groups_alerts(&db).await;
|
||||
}
|
||||
};
|
||||
@@ -1129,14 +1140,14 @@ pub async fn expose_queue_metrics(db: &Pool<Postgres>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn reload_server_config(db: &Pool<Postgres>) {
|
||||
let config = load_server_config(&db).await;
|
||||
if let Err(e) = config {
|
||||
tracing::error!("Error reloading server config: {:?}", e)
|
||||
pub async fn reload_smtp_config(db: &Pool<Postgres>) {
|
||||
let smtp_config = load_smtp_config(&db).await;
|
||||
if let Err(e) = smtp_config {
|
||||
tracing::error!("Error reloading smtp config: {:?}", e)
|
||||
} else {
|
||||
let mut wc = SERVER_CONFIG.write().await;
|
||||
tracing::info!("Reloading server config...");
|
||||
*wc = config.unwrap()
|
||||
let mut wc = SMTP_CONFIG.write().await;
|
||||
tracing::info!("Reloading smtp config...");
|
||||
*wc = smtp_config.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1912,6 +1912,109 @@ def main():
|
||||
assert_eq!(result, serde_json::json!("test-workspace"));
|
||||
}
|
||||
|
||||
#[sqlx::test(fixtures("base"))]
|
||||
async fn test_bun_job_datetime(db: Pool<Postgres>) {
|
||||
initialize_tracing().await;
|
||||
let server = ApiServer::start(db.clone()).await;
|
||||
let port = server.addr.port();
|
||||
|
||||
let content = r#"
|
||||
export async function main(a: Date) {
|
||||
return typeof a;
|
||||
}
|
||||
"#
|
||||
.to_owned();
|
||||
|
||||
let result = RunJob::from(JobPayload::Code(RawCode {
|
||||
hash: None,
|
||||
content,
|
||||
path: None,
|
||||
lock: None,
|
||||
language: ScriptLang::Bun,
|
||||
custom_concurrency_key: None,
|
||||
concurrent_limit: None,
|
||||
concurrency_time_window_s: None,
|
||||
cache_ttl: None,
|
||||
dedicated_worker: None,
|
||||
}))
|
||||
.arg("a", json!("2024-09-24T10:00:00.000Z"))
|
||||
.run_until_complete(&db, port)
|
||||
.await
|
||||
.json_result()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result, serde_json::json!("object"));
|
||||
}
|
||||
|
||||
#[sqlx::test(fixtures("base"))]
|
||||
async fn test_deno_job_datetime(db: Pool<Postgres>) {
|
||||
initialize_tracing().await;
|
||||
let server = ApiServer::start(db.clone()).await;
|
||||
let port = server.addr.port();
|
||||
|
||||
let content = r#"
|
||||
export async function main(a: Date) {
|
||||
return typeof a;
|
||||
}
|
||||
"#
|
||||
.to_owned();
|
||||
|
||||
let result = RunJob::from(JobPayload::Code(RawCode {
|
||||
hash: None,
|
||||
content,
|
||||
path: None,
|
||||
lock: None,
|
||||
language: ScriptLang::Deno,
|
||||
custom_concurrency_key: None,
|
||||
concurrent_limit: None,
|
||||
concurrency_time_window_s: None,
|
||||
cache_ttl: None,
|
||||
dedicated_worker: None,
|
||||
}))
|
||||
.arg("a", json!("2024-09-24T10:00:00.000Z"))
|
||||
.run_until_complete(&db, port)
|
||||
.await
|
||||
.json_result()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result, serde_json::json!("object"));
|
||||
}
|
||||
|
||||
#[sqlx::test(fixtures("base"))]
|
||||
async fn test_python_job_datetime_and_bytes(db: Pool<Postgres>) {
|
||||
initialize_tracing().await;
|
||||
let server = ApiServer::start(db.clone()).await;
|
||||
let port = server.addr.port();
|
||||
|
||||
let content = r#"
|
||||
from datetime import datetime
|
||||
def main(a: datetime, b: bytes):
|
||||
return (isinstance(a, datetime), isinstance(b, bytes))
|
||||
"#
|
||||
.to_owned();
|
||||
|
||||
let result = RunJob::from(JobPayload::Code(RawCode {
|
||||
hash: None,
|
||||
content,
|
||||
path: None,
|
||||
lock: None,
|
||||
language: ScriptLang::Python3,
|
||||
custom_concurrency_key: None,
|
||||
concurrent_limit: None,
|
||||
concurrency_time_window_s: None,
|
||||
cache_ttl: None,
|
||||
dedicated_worker: None,
|
||||
}))
|
||||
.arg("a", json!("2024-09-24T10:00:00.000Z"))
|
||||
.arg("b", json!("dGVzdA=="))
|
||||
.run_until_complete(&db, port)
|
||||
.await
|
||||
.json_result()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result, serde_json::json!([true, true]));
|
||||
}
|
||||
|
||||
#[sqlx::test(fixtures("base"))]
|
||||
async fn test_empty_loop_1(db: Pool<Postgres>) {
|
||||
initialize_tracing().await;
|
||||
@@ -2734,7 +2837,8 @@ async fn test_flow_lock_all(db: Pool<Postgres>) {
|
||||
language: windmill_api_client::types::RawScriptLanguage::Go | windmill_api_client::types::RawScriptLanguage::Python3 | windmill_api_client::types::RawScriptLanguage::Deno,
|
||||
lock: Some(ref lock),
|
||||
..
|
||||
}) if lock.len() > 0)
|
||||
}) if lock.len() > 0),
|
||||
"{:?}", m.value
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -3293,6 +3397,7 @@ async fn run_deployed_relative_imports(
|
||||
visible_to_runner_only: None,
|
||||
no_main_func: None,
|
||||
codebase: None,
|
||||
has_preprocessor: None,
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -3323,6 +3428,7 @@ async fn run_deployed_relative_imports(
|
||||
dedicated_worker: None,
|
||||
language,
|
||||
priority: None,
|
||||
apply_preprocessor: false,
|
||||
})
|
||||
.push(&db2)
|
||||
.await;
|
||||
|
||||
@@ -94,6 +94,7 @@ object_store = { workspace = true, optional = true}
|
||||
openidconnect = { workspace = true, optional = true}
|
||||
url = { workspace = true, optional = true}
|
||||
jsonwebtoken = { workspace = true }
|
||||
matchit.workspace = true
|
||||
|
||||
pin-project.workspace = true
|
||||
crc.workspace = true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.394.2
|
||||
version: 1.399.0
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
@@ -742,6 +742,35 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/settings/test_critical_channels:
|
||||
post:
|
||||
summary: test critical channels
|
||||
operationId: testCriticalChannels
|
||||
tags:
|
||||
- setting
|
||||
requestBody:
|
||||
description: test critical channel payload
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
slack_channel:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: status
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
/settings/test_license_key:
|
||||
post:
|
||||
summary: test license key
|
||||
@@ -3088,6 +3117,22 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/resources/file_resource_type_to_file_ext_map:
|
||||
get:
|
||||
summary: get map from resource type to format extension
|
||||
operationId: fileResourceTypeToFileExtMap
|
||||
tags:
|
||||
- resource
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
responses:
|
||||
"200":
|
||||
description: map from resource type to file ext
|
||||
content:
|
||||
application/json:
|
||||
schema: {}
|
||||
|
||||
|
||||
/w/{workspace}/resources/type/delete/{path}:
|
||||
delete:
|
||||
summary: delete resource_type
|
||||
@@ -4166,6 +4211,11 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: skip_preprocessor
|
||||
description: skip the preprocessor
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/ParentJob"
|
||||
- $ref: "#/components/parameters/WorkerTag"
|
||||
- $ref: "#/components/parameters/CacheTtl"
|
||||
@@ -5312,6 +5362,11 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: skip_preprocessor
|
||||
description: skip the preprocessor
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/ParentJob"
|
||||
- $ref: "#/components/parameters/WorkerTag"
|
||||
- $ref: "#/components/parameters/NewJobId"
|
||||
@@ -5420,6 +5475,11 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: skip_preprocessor
|
||||
description: skip the preprocessor
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- $ref: "#/components/parameters/ParentJob"
|
||||
- $ref: "#/components/parameters/WorkerTag"
|
||||
- $ref: "#/components/parameters/CacheTtl"
|
||||
@@ -5993,6 +6053,10 @@ paths:
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: get_progress
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
|
||||
responses:
|
||||
"200":
|
||||
@@ -6012,6 +6076,8 @@ paths:
|
||||
type: integer
|
||||
mem_peak:
|
||||
type: integer
|
||||
progress:
|
||||
type: integer
|
||||
flow_status:
|
||||
$ref: "#/components/schemas/WorkflowStatusRecord"
|
||||
|
||||
@@ -6800,6 +6866,190 @@ paths:
|
||||
"201":
|
||||
description: default error handler set
|
||||
|
||||
|
||||
/w/{workspace}/http_triggers/create:
|
||||
post:
|
||||
summary: create http trigger
|
||||
operationId: createHttpTrigger
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: new http trigger
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/NewHttpTrigger"
|
||||
responses:
|
||||
"201":
|
||||
description: http trigger created
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/http_triggers/update/{path}:
|
||||
post:
|
||||
summary: update http trigger
|
||||
operationId: updateHttpTrigger
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
requestBody:
|
||||
description: updated trigger
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EditHttpTrigger"
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger updated
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/http_triggers/delete/{path}:
|
||||
delete:
|
||||
summary: delete http trigger
|
||||
operationId: deleteHttpTrigger
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger deleted
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/http_triggers/get/{path}:
|
||||
get:
|
||||
summary: get http trigger
|
||||
operationId: getHttpTrigger
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HttpTrigger"
|
||||
|
||||
|
||||
/w/{workspace}/http_triggers/list:
|
||||
get:
|
||||
summary: list http triggers
|
||||
operationId: listHttpTriggers
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
required: true
|
||||
- $ref: "#/components/parameters/Page"
|
||||
- $ref: "#/components/parameters/PerPage"
|
||||
- name: path
|
||||
description: filter by path
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: is_flow
|
||||
in: query
|
||||
schema:
|
||||
type: boolean
|
||||
- name: path_start
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger list
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/HttpTrigger"
|
||||
|
||||
|
||||
/w/{workspace}/http_triggers/exists/{path}:
|
||||
get:
|
||||
summary: does http trigger exists
|
||||
operationId: existsHttpTrigger
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
responses:
|
||||
"200":
|
||||
description: http trigger exists
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
|
||||
/w/{workspace}/http_triggers/route_exists:
|
||||
post:
|
||||
summary: does route exists
|
||||
operationId: existsRoute
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
requestBody:
|
||||
description: route exists request
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
route_path:
|
||||
type: string
|
||||
http_method:
|
||||
type: string
|
||||
enum: ["get", "post", "put", "delete", "patch"]
|
||||
required:
|
||||
- kind
|
||||
- route_path
|
||||
- http_method
|
||||
responses:
|
||||
"200":
|
||||
description: route exists
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
|
||||
/w/{workspace}/http_triggers/used:
|
||||
get:
|
||||
summary: whether http triggers are used
|
||||
operationId: used
|
||||
tags:
|
||||
- http_trigger
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
responses:
|
||||
"200":
|
||||
description: whether http triggers are used
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: boolean
|
||||
|
||||
/groups/list:
|
||||
get:
|
||||
summary: list instance groups
|
||||
@@ -7626,6 +7876,7 @@ paths:
|
||||
folder,
|
||||
app,
|
||||
raw_app,
|
||||
http_trigger,
|
||||
]
|
||||
responses:
|
||||
"200":
|
||||
@@ -7662,6 +7913,7 @@ paths:
|
||||
folder,
|
||||
app,
|
||||
raw_app,
|
||||
http_trigger,
|
||||
]
|
||||
requestBody:
|
||||
description: acl to add
|
||||
@@ -7709,6 +7961,7 @@ paths:
|
||||
folder,
|
||||
app,
|
||||
raw_app,
|
||||
http_trigger,
|
||||
]
|
||||
requestBody:
|
||||
description: acl to add
|
||||
@@ -8347,6 +8600,38 @@ paths:
|
||||
application/json:
|
||||
schema: {}
|
||||
|
||||
/w/{workspace}/job_helpers/load_table_count/{path}:
|
||||
get:
|
||||
summary: Load the table row count
|
||||
operationId: loadTableRowCount
|
||||
tags:
|
||||
- helpers
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/Path"
|
||||
- name: search_col
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: search_term
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: storage
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Table count
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: number
|
||||
|
||||
/w/{workspace}/job_helpers/load_csv_preview/{path}:
|
||||
get:
|
||||
summary: Load a preview of a csv file
|
||||
@@ -8615,6 +8900,52 @@ paths:
|
||||
items:
|
||||
$ref: "#/components/schemas/TimeseriesMetric"
|
||||
|
||||
/w/{workspace}/job_metrics/set_progress/{id}:
|
||||
post:
|
||||
summary: set job metrics
|
||||
operationId: setJobProgress
|
||||
tags:
|
||||
- metrics
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/JobId"
|
||||
requestBody:
|
||||
description: parameters for statistics retrieval
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
percent:
|
||||
type: integer
|
||||
flow_job_id:
|
||||
type: string
|
||||
format: uuid
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: Job progress updated
|
||||
content:
|
||||
application/json:
|
||||
schema: {}
|
||||
|
||||
/w/{workspace}/job_metrics/get_progress/{id}:
|
||||
get:
|
||||
summary: get job progress
|
||||
operationId: getJobProgress
|
||||
tags:
|
||||
- metrics
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/JobId"
|
||||
responses:
|
||||
"200":
|
||||
description: job progress between 0 and 99
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: integer
|
||||
/service_logs/list_files:
|
||||
get:
|
||||
summary: list log files ordered by timestamp
|
||||
@@ -8679,7 +9010,6 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
/concurrency_groups/list:
|
||||
get:
|
||||
summary: List all concurrency groups
|
||||
@@ -9279,6 +9609,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
kind:
|
||||
type: string
|
||||
@@ -9321,6 +9652,8 @@ components:
|
||||
type: boolean
|
||||
codebase:
|
||||
type: string
|
||||
has_preprocessor:
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- hash
|
||||
@@ -9338,6 +9671,7 @@ components:
|
||||
- kind
|
||||
- starred
|
||||
- no_main_func
|
||||
- has_preprocessor
|
||||
|
||||
|
||||
NewScript:
|
||||
@@ -9378,6 +9712,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
kind:
|
||||
type: string
|
||||
@@ -9418,6 +9753,8 @@ components:
|
||||
type: boolean
|
||||
codebase:
|
||||
type: string
|
||||
has_preprocessor:
|
||||
type: boolean
|
||||
required:
|
||||
- path
|
||||
- summary
|
||||
@@ -9596,6 +9933,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
email:
|
||||
type: string
|
||||
@@ -9712,6 +10050,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
is_skipped:
|
||||
type: boolean
|
||||
@@ -10216,6 +10555,9 @@ components:
|
||||
no_main_func:
|
||||
type: boolean
|
||||
nullable: true
|
||||
has_preprocessor:
|
||||
type: boolean
|
||||
nullable: true
|
||||
required:
|
||||
- star_args
|
||||
- start_kwargs
|
||||
@@ -10223,6 +10565,7 @@ components:
|
||||
- type
|
||||
- error
|
||||
- no_main_func
|
||||
- has_preprocessor
|
||||
|
||||
Preview:
|
||||
type: object
|
||||
@@ -10252,6 +10595,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
tag:
|
||||
type: string
|
||||
@@ -10399,6 +10743,8 @@ components:
|
||||
edited_at:
|
||||
type: string
|
||||
format: date-time
|
||||
format_extension:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
|
||||
@@ -10609,6 +10955,122 @@ components:
|
||||
- is_flow
|
||||
- args
|
||||
|
||||
HttpTrigger:
|
||||
type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
edited_by:
|
||||
type: string
|
||||
edited_at:
|
||||
type: string
|
||||
format: date-time
|
||||
script_path:
|
||||
type: string
|
||||
route_path:
|
||||
type: string
|
||||
is_flow:
|
||||
type: boolean
|
||||
extra_perms:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: boolean
|
||||
email:
|
||||
type: string
|
||||
workspace_id:
|
||||
type: string
|
||||
http_method:
|
||||
type: string
|
||||
enum:
|
||||
- get
|
||||
- post
|
||||
- put
|
||||
- delete
|
||||
- patch
|
||||
is_async:
|
||||
type: boolean
|
||||
requires_auth:
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- path
|
||||
- edited_by
|
||||
- edited_at
|
||||
- script_path
|
||||
- route_path
|
||||
- extra_perms
|
||||
- is_flow
|
||||
- email
|
||||
- workspace_id
|
||||
- is_async
|
||||
- requires_auth
|
||||
- http_method
|
||||
|
||||
NewHttpTrigger:
|
||||
type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
script_path:
|
||||
type: string
|
||||
route_path:
|
||||
type: string
|
||||
is_flow:
|
||||
type: boolean
|
||||
http_method:
|
||||
type: string
|
||||
enum:
|
||||
- get
|
||||
- post
|
||||
- put
|
||||
- delete
|
||||
- patch
|
||||
is_async:
|
||||
type: boolean
|
||||
requires_auth:
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- path
|
||||
- script_path
|
||||
- route_path
|
||||
- is_flow
|
||||
- is_async
|
||||
- requires_auth
|
||||
- http_method
|
||||
|
||||
EditHttpTrigger:
|
||||
type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
script_path:
|
||||
type: string
|
||||
route_path:
|
||||
type: string
|
||||
is_flow:
|
||||
type: boolean
|
||||
http_method:
|
||||
type: string
|
||||
enum:
|
||||
- get
|
||||
- post
|
||||
- put
|
||||
- delete
|
||||
- patch
|
||||
is_async:
|
||||
type: boolean
|
||||
requires_auth:
|
||||
type: boolean
|
||||
required:
|
||||
- path
|
||||
- script_path
|
||||
- is_flow
|
||||
- kind
|
||||
- is_async
|
||||
- requires_auth
|
||||
- http_method
|
||||
|
||||
Group:
|
||||
type: object
|
||||
properties:
|
||||
@@ -11395,6 +11857,7 @@ components:
|
||||
bun,
|
||||
php,
|
||||
rust,
|
||||
ansible,
|
||||
]
|
||||
required:
|
||||
- raw_code
|
||||
|
||||
@@ -609,7 +609,7 @@ async fn create_app(
|
||||
}
|
||||
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM raw_app WHERE path = $1 AND workspace_id = $2)",
|
||||
"SELECT EXISTS(SELECT 1 FROM app WHERE path = $1 AND workspace_id = $2)",
|
||||
&app.path,
|
||||
w_id
|
||||
)
|
||||
|
||||
@@ -144,7 +144,7 @@ async fn get_concurrent_intervals(
|
||||
Query(iq): Query<ExtendedJobsParams>,
|
||||
Query(lq): Query<ListCompletedQuery>,
|
||||
) -> JsonResult<ExtendedJobs> {
|
||||
check_scopes(&authed, || format!("listjobs"))?;
|
||||
check_scopes(&authed, || format!("jobs:listjobs"))?;
|
||||
|
||||
if lq.success.is_some() && lq.running.is_some_and(|x| x) {
|
||||
return Err(error::Error::BadRequest(
|
||||
|
||||
@@ -1258,6 +1258,7 @@ mod tests {
|
||||
delete_after_use: None,
|
||||
continue_on_error: None,
|
||||
})),
|
||||
preprocessor_module: None,
|
||||
same_worker: false,
|
||||
concurrent_limit: None,
|
||||
concurrency_time_window_s: None,
|
||||
@@ -1330,7 +1331,8 @@ mod tests {
|
||||
"expr": "previous.isEmpty()",
|
||||
"skip_if_stopped": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"preprocessor_module": Option::<String>::None
|
||||
});
|
||||
assert_eq!(dbg!(serde_json::json!(fv)), dbg!(expect));
|
||||
}
|
||||
|
||||
@@ -23,6 +23,19 @@ use windmill_common::{
|
||||
utils::{not_found_if_none, StripPath},
|
||||
};
|
||||
|
||||
const KINDS: [&str; 10] = [
|
||||
"script",
|
||||
"group_",
|
||||
"resource",
|
||||
"schedule",
|
||||
"variable",
|
||||
"flow",
|
||||
"folder",
|
||||
"app",
|
||||
"raw_app",
|
||||
"http_trigger",
|
||||
];
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
.route("/get/*path", get(get_granular_acls))
|
||||
@@ -49,6 +62,11 @@ async fn add_granular_acl(
|
||||
let (kind, path) = path
|
||||
.split_once('/')
|
||||
.ok_or_else(|| Error::BadRequest("Invalid path or kind".to_string()))?;
|
||||
|
||||
if !KINDS.contains(&kind) {
|
||||
return Err(Error::BadRequest("Invalid kind".to_string()));
|
||||
}
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
let identifier = if kind == "group_" || kind == "folder" {
|
||||
@@ -69,9 +87,10 @@ async fn add_granular_acl(
|
||||
}
|
||||
|
||||
let obj_o = sqlx::query_scalar::<_, serde_json::Value>(&format!(
|
||||
"UPDATE {kind} SET extra_perms = jsonb_set(extra_perms, '{{\"{owner}\"}}', to_jsonb($1), \
|
||||
true) WHERE {identifier} = $2 AND workspace_id = $3 RETURNING extra_perms"
|
||||
"UPDATE {kind} SET extra_perms = jsonb_set(extra_perms, $1, to_jsonb($2), \
|
||||
true) WHERE {identifier} = $3 AND workspace_id = $4 RETURNING extra_perms"
|
||||
))
|
||||
.bind(vec![owner])
|
||||
.bind(write.unwrap_or(false))
|
||||
.bind(path)
|
||||
.bind(&w_id)
|
||||
@@ -158,6 +177,10 @@ async fn remove_granular_acl(
|
||||
.split_once('/')
|
||||
.ok_or_else(|| Error::BadRequest("Invalid path or kind".to_string()))?;
|
||||
|
||||
if !KINDS.contains(&kind) {
|
||||
return Err(Error::BadRequest("Invalid kind".to_string()));
|
||||
}
|
||||
|
||||
if !authed.is_admin {
|
||||
if kind == "folder" {
|
||||
crate::folders::require_is_owner(&authed, path)?;
|
||||
@@ -267,6 +290,10 @@ async fn get_granular_acls(
|
||||
.split_once('/')
|
||||
.ok_or_else(|| Error::BadRequest("Invalid path or kind".to_string()))?;
|
||||
|
||||
if !KINDS.contains(&kind) {
|
||||
return Err(Error::BadRequest("Invalid kind".to_string()));
|
||||
}
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
let identifier = if kind == "group_" { "name" } else { "path" };
|
||||
|
||||
651
backend/windmill-api/src/http_triggers.rs
Normal file
651
backend/windmill-api/src/http_triggers.rs
Normal file
@@ -0,0 +1,651 @@
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use http::{HeaderMap, StatusCode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sql_builder::{bind::Bind, SqlBuilder};
|
||||
use sqlx::prelude::FromRow;
|
||||
use std::collections::HashMap;
|
||||
use tower_http::cors::CorsLayer;
|
||||
use windmill_audit::{audit_ee::audit_log, ActionKind};
|
||||
use windmill_common::{
|
||||
auth::fetch_authed_from_permissioned_as,
|
||||
db::UserDB,
|
||||
error::{self, JsonResult},
|
||||
users::username_to_permissioned_as,
|
||||
utils::{not_found_if_none, paginate, require_admin, Pagination, StripPath},
|
||||
worker::{to_raw_value, CLOUD_HOSTED},
|
||||
};
|
||||
use windmill_queue::PushArgsOwned;
|
||||
|
||||
use crate::{
|
||||
db::{ApiAuthed, DB},
|
||||
jobs::{
|
||||
run_flow_by_path_inner, run_script_by_path_inner, run_wait_result_flow_by_path_internal,
|
||||
run_wait_result_script_by_path_internal, RunJobQuery,
|
||||
},
|
||||
users::OptAuthed,
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ROUTE_PATH_KEY_RE: regex::Regex = regex::Regex::new(r"/:\w+").unwrap();
|
||||
}
|
||||
|
||||
pub fn routes_global_service() -> Router {
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods([
|
||||
http::Method::GET,
|
||||
http::Method::POST,
|
||||
http::Method::DELETE,
|
||||
http::Method::PUT,
|
||||
http::Method::PATCH,
|
||||
])
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(tower_http::cors::Any);
|
||||
Router::new()
|
||||
.route(
|
||||
"/*path",
|
||||
get(route_job)
|
||||
.post(route_job)
|
||||
.delete(route_job)
|
||||
.put(route_job)
|
||||
.patch(route_job)
|
||||
.head(|| async { "" }),
|
||||
)
|
||||
.layer(cors)
|
||||
}
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
.route("/create", post(create_trigger))
|
||||
.route("/list", get(list_triggers))
|
||||
.route("/get/*path", get(get_trigger))
|
||||
.route("/update/*path", post(update_trigger))
|
||||
.route("/delete/*path", delete(delete_trigger))
|
||||
.route("/exists/*path", get(exists_trigger))
|
||||
.route("/used", get(used))
|
||||
.route("/route_exists", post(exists_route))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, sqlx::Type)]
|
||||
#[sqlx(type_name = "HTTP_METHOD", rename_all = "lowercase")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
enum HttpMethod {
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Patch,
|
||||
}
|
||||
|
||||
impl From<HttpMethod> for http::Method {
|
||||
fn from(method: HttpMethod) -> Self {
|
||||
match method {
|
||||
HttpMethod::Get => http::Method::GET,
|
||||
HttpMethod::Post => http::Method::POST,
|
||||
HttpMethod::Put => http::Method::PUT,
|
||||
HttpMethod::Delete => http::Method::DELETE,
|
||||
HttpMethod::Patch => http::Method::PATCH,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NewTrigger {
|
||||
path: String,
|
||||
route_path: String,
|
||||
script_path: String,
|
||||
is_flow: bool,
|
||||
is_async: bool,
|
||||
requires_auth: bool,
|
||||
http_method: HttpMethod,
|
||||
}
|
||||
|
||||
#[derive(FromRow, Serialize)]
|
||||
struct Trigger {
|
||||
workspace_id: String,
|
||||
path: String,
|
||||
route_path: String,
|
||||
route_path_key: String,
|
||||
script_path: String,
|
||||
is_flow: bool,
|
||||
edited_by: String,
|
||||
email: String,
|
||||
edited_at: chrono::DateTime<chrono::Utc>,
|
||||
extra_perms: serde_json::Value,
|
||||
is_async: bool,
|
||||
requires_auth: bool,
|
||||
http_method: HttpMethod,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct EditTrigger {
|
||||
path: String,
|
||||
route_path: Option<String>,
|
||||
script_path: String,
|
||||
is_flow: bool,
|
||||
is_async: bool,
|
||||
requires_auth: bool,
|
||||
http_method: HttpMethod,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ListTriggerQuery {
|
||||
pub page: Option<usize>,
|
||||
pub per_page: Option<usize>,
|
||||
pub path: Option<String>,
|
||||
pub is_flow: Option<bool>,
|
||||
pub path_start: Option<String>,
|
||||
}
|
||||
|
||||
async fn list_triggers(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path(w_id): Path<String>,
|
||||
Query(lst): Query<ListTriggerQuery>,
|
||||
) -> error::JsonResult<Vec<Trigger>> {
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let (per_page, offset) = paginate(Pagination { per_page: lst.per_page, page: lst.page });
|
||||
let mut sqlb = SqlBuilder::select_from("http_trigger")
|
||||
.field("*")
|
||||
.order_by("edited_at", true)
|
||||
.and_where("workspace_id = ?".bind(&w_id))
|
||||
.offset(offset)
|
||||
.limit(per_page)
|
||||
.clone();
|
||||
if let Some(path) = lst.path {
|
||||
sqlb.and_where_eq("script_path", "?".bind(&path));
|
||||
}
|
||||
if let Some(is_flow) = lst.is_flow {
|
||||
sqlb.and_where_eq("is_flow", "?".bind(&is_flow));
|
||||
}
|
||||
if let Some(path_start) = &lst.path_start {
|
||||
sqlb.and_where_like_left("path", path_start);
|
||||
}
|
||||
let sql = sqlb
|
||||
.sql()
|
||||
.map_err(|e| error::Error::InternalErr(e.to_string()))?;
|
||||
let rows = sqlx::query_as::<_, Trigger>(&sql)
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(Json(rows))
|
||||
}
|
||||
|
||||
async fn get_trigger(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> error::JsonResult<Trigger> {
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let path = path.to_path();
|
||||
let trigger = sqlx::query_as!(
|
||||
Trigger,
|
||||
r#"SELECT workspace_id, path, route_path, route_path_key, script_path, is_flow, http_method as "http_method: _", edited_by, email, edited_at, extra_perms, is_async, requires_auth
|
||||
FROM http_trigger
|
||||
WHERE workspace_id = $1 AND path = $2"#,
|
||||
w_id,
|
||||
path,
|
||||
)
|
||||
.fetch_optional(&mut *tx)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
let trigger = not_found_if_none(trigger, "Trigger", path)?;
|
||||
|
||||
Ok(Json(trigger))
|
||||
}
|
||||
|
||||
async fn create_trigger(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path(w_id): Path<String>,
|
||||
Json(ct): Json<NewTrigger>,
|
||||
) -> error::Result<(StatusCode, String)> {
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
|
||||
let route_path_key = ROUTE_PATH_KEY_RE.replace_all(ct.route_path.as_str(), ":key");
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
sqlx::query!(
|
||||
"INSERT INTO http_trigger (workspace_id, path, route_path, route_path_key, script_path, is_flow, is_async, requires_auth, http_method, edited_by, email, edited_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, now())",
|
||||
w_id,
|
||||
ct.path,
|
||||
ct.route_path,
|
||||
&route_path_key,
|
||||
ct.script_path,
|
||||
ct.is_flow,
|
||||
ct.is_async,
|
||||
ct.requires_auth,
|
||||
ct.http_method as HttpMethod,
|
||||
&authed.username,
|
||||
&authed.email
|
||||
)
|
||||
.execute(&mut *tx).await?;
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"http_triggers.create",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
Some(ct.path.as_str()),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok((StatusCode::CREATED, format!("{}", ct.path)))
|
||||
}
|
||||
|
||||
async fn update_trigger(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
Json(ct): Json<EditTrigger>,
|
||||
) -> error::Result<String> {
|
||||
let path = path.to_path();
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
if authed.is_admin {
|
||||
if ct.route_path.is_none() {
|
||||
return Err(error::Error::BadRequest(
|
||||
"route_path is required".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let route_path_key =
|
||||
ROUTE_PATH_KEY_RE.replace_all(ct.route_path.as_ref().unwrap().as_str(), ":key");
|
||||
|
||||
sqlx::query!(
|
||||
"UPDATE http_trigger
|
||||
SET route_path = $1, route_path_key = $2, script_path = $3, path = $4, is_flow = $5, http_method = $6, edited_by = $7, email = $8, is_async = $9, requires_auth = $10, edited_at = now()
|
||||
WHERE workspace_id = $11 AND path = $12",
|
||||
ct.route_path,
|
||||
&route_path_key,
|
||||
ct.script_path,
|
||||
ct.path,
|
||||
ct.is_flow,
|
||||
ct.http_method as HttpMethod,
|
||||
&authed.username,
|
||||
&authed.email,
|
||||
ct.is_async,
|
||||
ct.requires_auth,
|
||||
w_id,
|
||||
path,
|
||||
)
|
||||
.execute(&mut *tx).await?;
|
||||
} else {
|
||||
sqlx::query!(
|
||||
"UPDATE http_trigger SET script_path = $1, path = $2, is_flow = $3, http_method = $4, edited_by = $5, email = $6, is_async = $7, requires_auth = $8, edited_at = now()
|
||||
WHERE workspace_id = $9 AND path = $10",
|
||||
ct.script_path,
|
||||
ct.path,
|
||||
ct.is_flow,
|
||||
ct.http_method as HttpMethod,
|
||||
&authed.username,
|
||||
&authed.email,
|
||||
ct.is_async,
|
||||
ct.requires_auth,
|
||||
w_id,
|
||||
path,
|
||||
)
|
||||
.execute(&mut *tx).await?;
|
||||
}
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"http_triggers.update",
|
||||
ActionKind::Create,
|
||||
&w_id,
|
||||
Some(path),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(path.to_string())
|
||||
}
|
||||
|
||||
async fn delete_trigger(
|
||||
authed: ApiAuthed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> error::Result<String> {
|
||||
require_admin(authed.is_admin, &authed.username)?;
|
||||
let path = path.to_path();
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
sqlx::query!(
|
||||
"DELETE FROM http_trigger WHERE workspace_id = $1 AND path = $2",
|
||||
w_id,
|
||||
path,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
&authed,
|
||||
"http_triggers.delete",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
Some(path),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(format!("HTTP trigger {path} deleted"))
|
||||
}
|
||||
|
||||
async fn used(Extension(db): Extension<DB>, Path(w_id): Path<String>) -> JsonResult<bool> {
|
||||
let used = sqlx::query_scalar!(
|
||||
r#"SELECT EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1)"#,
|
||||
w_id,
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
Ok(Json(used))
|
||||
}
|
||||
|
||||
async fn exists_trigger(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> JsonResult<bool> {
|
||||
let path = path.to_path();
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM http_trigger WHERE path = $1 AND workspace_id = $2)",
|
||||
path,
|
||||
w_id,
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
Ok(Json(exists))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RouteExists {
|
||||
route_path: String,
|
||||
http_method: HttpMethod,
|
||||
}
|
||||
|
||||
async fn exists_route(
|
||||
Extension(db): Extension<DB>,
|
||||
Path(w_id): Path<String>,
|
||||
Json(RouteExists { route_path, http_method }): Json<RouteExists>,
|
||||
) -> JsonResult<bool> {
|
||||
let route_path_key = ROUTE_PATH_KEY_RE.replace_all(route_path.as_str(), ":key");
|
||||
let exists = if *CLOUD_HOSTED {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM http_trigger WHERE route_path_key = $1 AND workspace_id = $2 AND http_method = $3)",
|
||||
&route_path_key,
|
||||
w_id,
|
||||
http_method as HttpMethod
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM http_trigger WHERE route_path_key = $1 AND http_method = $2)",
|
||||
&route_path_key,
|
||||
http_method as HttpMethod
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false)
|
||||
};
|
||||
Ok(Json(exists))
|
||||
}
|
||||
|
||||
struct TriggerRoute {
|
||||
path: String,
|
||||
script_path: String,
|
||||
is_flow: bool,
|
||||
route_path: String,
|
||||
workspace_id: String,
|
||||
is_async: bool,
|
||||
requires_auth: bool,
|
||||
edited_by: String,
|
||||
email: String,
|
||||
http_method: HttpMethod,
|
||||
}
|
||||
|
||||
async fn fetch_api_authed(
|
||||
username: String,
|
||||
email: String,
|
||||
w_id: &str,
|
||||
db: &DB,
|
||||
username_override: String,
|
||||
) -> error::Result<ApiAuthed> {
|
||||
let permissioned_as = username_to_permissioned_as(username.as_str());
|
||||
let authed =
|
||||
fetch_authed_from_permissioned_as(permissioned_as, email.clone(), w_id, db).await?;
|
||||
Ok(ApiAuthed {
|
||||
username: username,
|
||||
email: email,
|
||||
is_admin: authed.is_admin,
|
||||
is_operator: authed.is_operator,
|
||||
groups: authed.groups,
|
||||
folders: authed.folders,
|
||||
scopes: authed.scopes,
|
||||
username_override: Some(username_override),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_http_route_trigger(
|
||||
route_path: &str,
|
||||
opt_authed: Option<ApiAuthed>,
|
||||
db: &DB,
|
||||
user_db: UserDB,
|
||||
) -> error::Result<(TriggerRoute, String, HashMap<String, String>, ApiAuthed)> {
|
||||
let (mut triggers, route_path) = if *CLOUD_HOSTED {
|
||||
let mut splitted = route_path.split("/");
|
||||
let w_id = splitted.next().ok_or_else(|| {
|
||||
error::Error::BadRequest("Missing workspace id in route path".to_string())
|
||||
})?;
|
||||
let route_path = StripPath(splitted.collect::<Vec<_>>().join("/"));
|
||||
let triggers = sqlx::query_as!(
|
||||
TriggerRoute,
|
||||
r#"SELECT path, script_path, is_flow, route_path, workspace_id, is_async, requires_auth, edited_by, email, http_method as "http_method: _" FROM http_trigger WHERE workspace_id = $1"#,
|
||||
w_id
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await?;
|
||||
(triggers, route_path)
|
||||
} else {
|
||||
let triggers = sqlx::query_as!(
|
||||
TriggerRoute,
|
||||
r#"SELECT path, script_path, is_flow, route_path, workspace_id, is_async, requires_auth, edited_by, email, http_method as "http_method: _" FROM http_trigger"#,
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await?;
|
||||
(triggers, StripPath(route_path.to_string()))
|
||||
};
|
||||
|
||||
let mut router = matchit::Router::new();
|
||||
|
||||
for (idx, trigger) in triggers.iter().enumerate() {
|
||||
let route_path = trigger.route_path.clone();
|
||||
router.insert(route_path.as_str(), idx).unwrap_or_else(|e| {
|
||||
tracing::warn!(
|
||||
"Failed to consider http trigger route {}: {:?}",
|
||||
route_path,
|
||||
e,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
let trigger_idx = router.at(route_path.0.as_str()).ok();
|
||||
|
||||
let matchit::Match { value: trigger_idx, params } =
|
||||
not_found_if_none(trigger_idx, "Trigger", route_path.0.as_str())?;
|
||||
|
||||
let trigger = triggers.remove(trigger_idx.to_owned());
|
||||
|
||||
let params: HashMap<String, String> = params
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect();
|
||||
|
||||
let username_override = if trigger.requires_auth {
|
||||
if let Some(authed) = opt_authed {
|
||||
// check that the user has access to the trigger
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM http_trigger WHERE workspace_id = $1 AND path = $2)",
|
||||
trigger.workspace_id,
|
||||
trigger.path
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
tx.commit().await?;
|
||||
if exists {
|
||||
Some(authed.display_username().to_owned())
|
||||
} else {
|
||||
return Err(error::Error::NotAuthorized("Unauthorized".to_string()));
|
||||
}
|
||||
} else {
|
||||
return Err(error::Error::NotAuthorized(
|
||||
"Requires authentication".to_string(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let authed = fetch_api_authed(
|
||||
trigger.edited_by.clone(),
|
||||
trigger.email.clone(),
|
||||
&trigger.workspace_id,
|
||||
&db,
|
||||
username_override.unwrap_or("anonymous".to_string()),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok((trigger, route_path.0, params, authed))
|
||||
}
|
||||
|
||||
async fn route_job(
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(rsmq): Extension<Option<rsmq_async::MultiplexedRsmq>>,
|
||||
Path(route_path): Path<StripPath>,
|
||||
OptAuthed(opt_authed): OptAuthed,
|
||||
Query(query): Query<HashMap<String, String>>,
|
||||
method: http::Method,
|
||||
headers: HeaderMap,
|
||||
mut args: PushArgsOwned,
|
||||
) -> impl IntoResponse {
|
||||
let route_path = route_path.to_path();
|
||||
let (trigger, called_path, params, authed) =
|
||||
match get_http_route_trigger(route_path, opt_authed, &db, user_db.clone()).await {
|
||||
Ok(trigger) => trigger,
|
||||
Err(e) => return e.into_response(),
|
||||
};
|
||||
let headers = headers
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
|
||||
.collect::<HashMap<String, String>>();
|
||||
let extra = args.extra.get_or_insert_with(HashMap::new);
|
||||
extra.insert(
|
||||
"wm_trigger".to_string(),
|
||||
to_raw_value(&serde_json::json!({
|
||||
"kind": "http",
|
||||
"http": {
|
||||
"route": trigger.route_path,
|
||||
"path": called_path,
|
||||
"method": method.to_string().to_lowercase(),
|
||||
"params": params,
|
||||
"query": query,
|
||||
"headers": headers
|
||||
},
|
||||
})),
|
||||
);
|
||||
let http_method = http::Method::from(trigger.http_method);
|
||||
|
||||
if http_method != method {
|
||||
return error::Error::BadRequest("Invalid HTTP method".to_string()).into_response();
|
||||
}
|
||||
|
||||
let label_prefix = Some(format!(
|
||||
"http-{}-{}-",
|
||||
http_method.as_str().to_lowercase(),
|
||||
trigger.route_path
|
||||
));
|
||||
|
||||
let run_query = RunJobQuery::default();
|
||||
|
||||
if trigger.is_flow {
|
||||
if trigger.is_async {
|
||||
run_flow_by_path_inner(
|
||||
authed,
|
||||
db,
|
||||
user_db,
|
||||
rsmq,
|
||||
trigger.workspace_id.clone(),
|
||||
StripPath(trigger.script_path.to_owned()),
|
||||
run_query,
|
||||
args,
|
||||
label_prefix,
|
||||
)
|
||||
.await
|
||||
.into_response()
|
||||
} else {
|
||||
run_wait_result_flow_by_path_internal(
|
||||
db,
|
||||
run_query,
|
||||
StripPath(trigger.script_path.to_owned()),
|
||||
authed,
|
||||
rsmq,
|
||||
user_db,
|
||||
args,
|
||||
trigger.workspace_id.clone(),
|
||||
label_prefix,
|
||||
)
|
||||
.await
|
||||
.into_response()
|
||||
}
|
||||
} else {
|
||||
if trigger.is_async {
|
||||
run_script_by_path_inner(
|
||||
authed,
|
||||
db,
|
||||
user_db,
|
||||
rsmq,
|
||||
trigger.workspace_id.clone(),
|
||||
StripPath(trigger.script_path.to_owned()),
|
||||
run_query,
|
||||
args,
|
||||
label_prefix,
|
||||
)
|
||||
.await
|
||||
.into_response()
|
||||
} else {
|
||||
run_wait_result_script_by_path_internal(
|
||||
db,
|
||||
run_query,
|
||||
StripPath(trigger.script_path.to_owned()),
|
||||
authed,
|
||||
rsmq,
|
||||
user_db,
|
||||
trigger.workspace_id.clone(),
|
||||
args,
|
||||
label_prefix,
|
||||
)
|
||||
.await
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
use crate::db::DB;
|
||||
|
||||
use axum::{extract::Path, routing::post, Extension, Json, Router};
|
||||
use axum::{
|
||||
extract::Path,
|
||||
routing::{get, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use uuid::Uuid;
|
||||
use windmill_common::{
|
||||
error,
|
||||
job_metrics::{JobStatsRecord, MetricKind},
|
||||
error::{self, Error},
|
||||
job_metrics::{
|
||||
record_metric, register_metric_for_job, JobStatsRecord, MetricKind, MetricNumericValue,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
@@ -15,7 +21,16 @@ pub fn workspaced_service() -> Router {
|
||||
.allow_headers([http::header::CONTENT_TYPE, http::header::AUTHORIZATION])
|
||||
.allow_origin(Any);
|
||||
|
||||
Router::new().route("/get/:id", post(get_job_metrics).layer(cors.clone()))
|
||||
Router::new()
|
||||
.route("/get/:id", post(get_job_metrics).layer(cors.clone()))
|
||||
.route(
|
||||
"/set_progress/:id",
|
||||
post(set_job_progress).layer(cors.clone()),
|
||||
)
|
||||
.route(
|
||||
"/get_progress/:id",
|
||||
get(get_job_progress).layer(cors.clone()),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -137,6 +152,93 @@ async fn get_job_metrics(
|
||||
let response = JobStatsResponse { metrics_metadata, scalar_metrics, timeseries_metrics };
|
||||
Ok(Json(response))
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct JobProgressSetRequest {
|
||||
percent: i32,
|
||||
/// Optional parent flow id
|
||||
/// Used to modify flow status
|
||||
/// Specifically `progress` field in corresponding FlowStatusModule in `InProgress` state
|
||||
flow_job_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
async fn set_job_progress(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, job_id)): Path<(String, Uuid)>,
|
||||
Json(JobProgressSetRequest { percent, flow_job_id }): Json<JobProgressSetRequest>,
|
||||
) -> error::JsonResult<()> {
|
||||
// If flow_job_id exists, than we should modify flow_status of corresponding module
|
||||
// Individual jobs and flows are handled differently
|
||||
if let Some(flow_job_id) = flow_job_id {
|
||||
// TODO: Return error if trying to set completed job?
|
||||
sqlx::query!(
|
||||
"UPDATE queue
|
||||
SET flow_status = JSONB_SET(flow_status, ARRAY['modules', flow_status->>'step', 'progress'], $1)
|
||||
WHERE id = $2",
|
||||
serde_json::json!(percent.clamp(0, 99)),
|
||||
flow_job_id
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let record_progress = || {
|
||||
record_metric(
|
||||
&db,
|
||||
w_id.clone(),
|
||||
job_id,
|
||||
"progress_perc".to_owned(),
|
||||
MetricNumericValue::Integer(percent),
|
||||
)
|
||||
};
|
||||
|
||||
// Try to record
|
||||
if let Err(err) = record_progress().await {
|
||||
if matches!(err, Error::MetricNotFound(..)) {
|
||||
// Register
|
||||
// TODO: Reset progress after job is finished (in case it reruns same job)?
|
||||
_ = register_metric_for_job(
|
||||
&db,
|
||||
w_id.clone(),
|
||||
job_id,
|
||||
"progress_perc".to_string(),
|
||||
MetricKind::ScalarInt,
|
||||
Some("Job Execution Progress (%)".to_owned()),
|
||||
)
|
||||
.await?;
|
||||
// Retry recording progress
|
||||
record_progress().await.map_err(|err| {
|
||||
// If for some reason it still returns same error, this error will be converted to BadRequest and returned
|
||||
if let Error::MetricNotFound(body) = err {
|
||||
Error::BadRequest(body)
|
||||
} else {
|
||||
err
|
||||
}
|
||||
})?;
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
return Ok(Json(()));
|
||||
}
|
||||
|
||||
async fn get_job_progress(
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, job_id)): Path<(String, Uuid)>,
|
||||
) -> error::JsonResult<Option<i32>> {
|
||||
let progress: Option<Option<i32>> = sqlx::query_scalar!(
|
||||
"SELECT (scalar_int)::int FROM job_stats WHERE job_id = $1 AND workspace_id = $2 AND metric_id = 'progress_perc'",
|
||||
job_id, w_id)
|
||||
.fetch_optional(&db)
|
||||
.await?;
|
||||
|
||||
let respond_value = if let Some(Some(progress)) = progress {
|
||||
Some(progress.clamp(0, 99))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Json(respond_value))
|
||||
}
|
||||
|
||||
fn timeseries_sample<T: Copy>(
|
||||
from: Option<chrono::DateTime<chrono::Utc>>,
|
||||
|
||||
@@ -33,6 +33,7 @@ use crate::add_webhook_allowed_origin;
|
||||
use crate::concurrency_groups::join_concurrency_key;
|
||||
use crate::db::ApiAuthed;
|
||||
|
||||
use crate::users::get_scope_tags;
|
||||
use crate::utils::content_plain;
|
||||
use crate::{
|
||||
db::DB,
|
||||
@@ -58,7 +59,7 @@ use tower_http::cors::{Any, CorsLayer};
|
||||
use urlencoding::encode;
|
||||
use windmill_audit::audit_ee::{audit_log, AuditAuthor};
|
||||
use windmill_audit::ActionKind;
|
||||
use windmill_common::worker::{to_raw_value, CUSTOM_TAGS_PER_WORKSPACE, SERVER_CONFIG};
|
||||
use windmill_common::worker::{to_raw_value, CUSTOM_TAGS_PER_WORKSPACE};
|
||||
use windmill_common::{
|
||||
db::UserDB,
|
||||
error::{self, to_anyhow, Error},
|
||||
@@ -556,9 +557,10 @@ pub async fn get_path_tag_limits_cache_for_hash<'c, R: rsmq_async::RsmqConnectio
|
||||
Option<i16>,
|
||||
Option<bool>,
|
||||
Option<i32>,
|
||||
Option<bool>,
|
||||
)> {
|
||||
let script = sqlx::query!(
|
||||
"select path, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout from script where hash = $1 AND workspace_id = $2",
|
||||
"select path, tag, concurrency_key, concurrent_limit, concurrency_time_window_s, cache_ttl, language as \"language: ScriptLang\", dedicated_worker, priority, delete_after_use, timeout, has_preprocessor from script where hash = $1 AND workspace_id = $2",
|
||||
hash,
|
||||
w_id
|
||||
)
|
||||
@@ -583,6 +585,7 @@ pub async fn get_path_tag_limits_cache_for_hash<'c, R: rsmq_async::RsmqConnectio
|
||||
script.priority,
|
||||
script.delete_after_use,
|
||||
script.timeout,
|
||||
script.has_preprocessor,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -1058,6 +1061,7 @@ pub struct RunJobQuery {
|
||||
pub tag: Option<String>,
|
||||
pub timeout: Option<i32>,
|
||||
pub cache_ttl: Option<i32>,
|
||||
pub skip_preprocessor: Option<bool>,
|
||||
}
|
||||
|
||||
impl RunJobQuery {
|
||||
@@ -1245,13 +1249,18 @@ pub fn list_queue_jobs_query(
|
||||
lq: &ListQueueQuery,
|
||||
fields: &[&str],
|
||||
join_outstanding_wait_times: bool,
|
||||
tags: Option<Vec<&str>>,
|
||||
) -> SqlBuilder {
|
||||
let sqlb = SqlBuilder::select_from("queue")
|
||||
let mut sqlb = SqlBuilder::select_from("queue")
|
||||
.fields(fields)
|
||||
.order_by("created_at", lq.order_desc.unwrap_or(true))
|
||||
.limit(1000)
|
||||
.clone();
|
||||
|
||||
if let Some(tags) = tags {
|
||||
sqlb.and_where_in("tag", &tags.iter().map(|x| quote(x)).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
filter_list_queue_query(sqlb, lq, w_id, join_outstanding_wait_times)
|
||||
}
|
||||
|
||||
@@ -1307,6 +1316,7 @@ async fn list_queue_jobs(
|
||||
"workspace_id",
|
||||
],
|
||||
false,
|
||||
get_scope_tags(&authed),
|
||||
)
|
||||
.sql()?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
@@ -1495,6 +1505,10 @@ async fn list_filtered_uuids(
|
||||
|
||||
sqlb.and_where_is_null("schedule_path");
|
||||
|
||||
if let Some(tags) = get_scope_tags(&authed) {
|
||||
sqlb.and_where_in("tag", &tags.iter().map(|x| quote(x)).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
sqlb = filter_list_queue_query(sqlb, &lq, w_id.as_str(), false);
|
||||
|
||||
let sql = sqlb.query()?;
|
||||
@@ -1554,7 +1568,7 @@ async fn list_jobs(
|
||||
Query(lq): Query<ListCompletedQuery>,
|
||||
Extension(_api_list_jobs_query_duration): Extension<Option<Histo>>,
|
||||
) -> error::JsonResult<Vec<Job>> {
|
||||
check_scopes(&authed, || format!("listjobs"))?;
|
||||
check_scopes(&authed, || format!("jobs:listjobs"))?;
|
||||
|
||||
let (per_page, offset) = paginate(pagination);
|
||||
let lqc = lq.clone();
|
||||
@@ -1572,6 +1586,7 @@ async fn list_jobs(
|
||||
&ListCompletedQuery { order_desc: Some(true), ..lqc },
|
||||
UnifiedJob::completed_job_fields(),
|
||||
true,
|
||||
get_scope_tags(&authed),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
@@ -1587,6 +1602,7 @@ async fn list_jobs(
|
||||
&ListQueueQuery { order_desc: Some(true), ..lq.into() },
|
||||
UnifiedJob::queued_job_fields(),
|
||||
true,
|
||||
get_scope_tags(&authed),
|
||||
);
|
||||
|
||||
if let Some(sqlc) = sqlc {
|
||||
@@ -1637,7 +1653,7 @@ pub async fn resume_suspended_flow_as_owner(
|
||||
Path((_w_id, flow_id)): Path<(String, Uuid)>,
|
||||
QueryOrBody(value): QueryOrBody<serde_json::Value>,
|
||||
) -> error::Result<StatusCode> {
|
||||
check_scopes(&authed, || format!("resumeflow"))?;
|
||||
check_scopes(&authed, || format!("jobs:resumeflow"))?;
|
||||
let value = value.unwrap_or(serde_json::Value::Null);
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
@@ -2784,14 +2800,18 @@ pub async fn run_flow_by_path_inner(
|
||||
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
let (tag, dedicated_worker) = sqlx::query!(
|
||||
"SELECT tag, dedicated_worker from flow WHERE path = $1 and workspace_id = $2",
|
||||
let (tag, dedicated_worker, has_preprocessor) = sqlx::query!(
|
||||
"SELECT tag, dedicated_worker, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor
|
||||
FROM flow
|
||||
LEFT JOIN flow_version
|
||||
ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]
|
||||
WHERE flow.path = $1 and flow.workspace_id = $2",
|
||||
flow_path,
|
||||
w_id
|
||||
)
|
||||
.fetch_optional(&mut tx)
|
||||
.await?
|
||||
.map(|x| (x.tag, x.dedicated_worker))
|
||||
.map(|x| (x.tag, x.dedicated_worker, x.has_preprocessor))
|
||||
.ok_or_else(|| {
|
||||
Error::NotFound(format!(
|
||||
"flow not found at path {flow_path} in workspace {w_id}"
|
||||
@@ -2807,7 +2827,12 @@ pub async fn run_flow_by_path_inner(
|
||||
&db,
|
||||
tx,
|
||||
&w_id,
|
||||
JobPayload::Flow { path: flow_path.to_string(), dedicated_worker },
|
||||
JobPayload::Flow {
|
||||
path: flow_path.to_string(),
|
||||
dedicated_worker,
|
||||
apply_preprocessor: !run_query.skip_preprocessor.unwrap_or(false)
|
||||
&& has_preprocessor.unwrap_or(false),
|
||||
},
|
||||
PushArgs { args: &args.args, extra: args.extra },
|
||||
&label_prefix
|
||||
.map(|x| x + authed.display_username())
|
||||
@@ -2973,7 +2998,7 @@ pub async fn run_script_by_path_inner(
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
let (job_payload, tag, _delete_after_use, timeout) =
|
||||
script_path_to_payload(script_path, &mut tx, &w_id).await?;
|
||||
script_path_to_payload(script_path, &mut tx, &w_id, run_query.skip_preprocessor).await?;
|
||||
let scheduled_for = run_query.get_scheduled_for(&db).await?;
|
||||
|
||||
let tag = run_query.tag.clone().or(tag);
|
||||
@@ -3049,7 +3074,15 @@ pub async fn run_workflow_as_code(
|
||||
None,
|
||||
run_query.timeout,
|
||||
),
|
||||
JobKind::Script => script_path_to_payload(job.script_path(), &mut tx, &w_id).await?,
|
||||
JobKind::Script => {
|
||||
script_path_to_payload(
|
||||
job.script_path(),
|
||||
&mut tx,
|
||||
&w_id,
|
||||
run_query.skip_preprocessor,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
_ => return Err(anyhow::anyhow!("Not supported").into()),
|
||||
};
|
||||
|
||||
@@ -3145,6 +3178,17 @@ impl Drop for Guard {
|
||||
}
|
||||
}
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref TIMEOUT_WAIT_RESULT: Arc<RwLock<Option<u64>>> = Arc::new(RwLock::new(
|
||||
std::env::var("TIMEOUT_WAIT_RESULT")
|
||||
.ok()
|
||||
.and_then(|x| x.parse::<u64>().ok())
|
||||
));
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct WindmillCompositeResult {
|
||||
windmill_status_code: Option<u16>,
|
||||
@@ -3159,7 +3203,7 @@ async fn run_wait_result(
|
||||
username: &str,
|
||||
) -> error::Result<Response> {
|
||||
let mut result = None;
|
||||
let timeout = SERVER_CONFIG.read().await.timeout_wait_result.clone();
|
||||
let timeout = TIMEOUT_WAIT_RESULT.read().await.clone().unwrap_or(600);
|
||||
let timeout_ms = if timeout <= 0 {
|
||||
2000
|
||||
} else {
|
||||
@@ -3451,7 +3495,7 @@ pub async fn run_wait_result_job_by_path_get(
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
let (job_payload, tag, delete_after_use, timeout) =
|
||||
script_path_to_payload(script_path, &mut tx, &w_id).await?;
|
||||
script_path_to_payload(script_path, &mut tx, &w_id, run_query.skip_preprocessor).await?;
|
||||
|
||||
let tag = run_query.tag.clone().or(tag);
|
||||
check_tag_available_for_workspace(&w_id, &tag).await?;
|
||||
@@ -3527,7 +3571,7 @@ pub async fn run_wait_result_flow_by_path_get(
|
||||
let args = PushArgsOwned { extra: Some(payload_args), args: HashMap::new() };
|
||||
|
||||
run_wait_result_flow_by_path_internal(
|
||||
db, run_query, flow_path, authed, rsmq, user_db, args, w_id,
|
||||
db, run_query, flow_path, authed, rsmq, user_db, args, w_id, None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -3553,11 +3597,12 @@ pub async fn run_wait_result_script_by_path(
|
||||
user_db,
|
||||
w_id,
|
||||
args,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn run_wait_result_script_by_path_internal(
|
||||
pub async fn run_wait_result_script_by_path_internal(
|
||||
db: sqlx::Pool<Postgres>,
|
||||
run_query: RunJobQuery,
|
||||
script_path: StripPath,
|
||||
@@ -3566,6 +3611,7 @@ async fn run_wait_result_script_by_path_internal(
|
||||
user_db: UserDB,
|
||||
w_id: String,
|
||||
args: PushArgsOwned,
|
||||
label_prefix: Option<String>,
|
||||
) -> error::Result<Response> {
|
||||
check_queue_too_long(&db, QUEUE_LIMIT_WAIT_RESULT.or(run_query.queue_limit)).await?;
|
||||
let script_path = script_path.to_path();
|
||||
@@ -3574,7 +3620,7 @@ async fn run_wait_result_script_by_path_internal(
|
||||
let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into();
|
||||
|
||||
let (job_payload, tag, delete_after_use, timeout) =
|
||||
script_path_to_payload(script_path, &mut tx, &w_id).await?;
|
||||
script_path_to_payload(script_path, &mut tx, &w_id, run_query.skip_preprocessor).await?;
|
||||
|
||||
let tag = run_query.tag.clone().or(tag);
|
||||
check_tag_available_for_workspace(&w_id, &tag).await?;
|
||||
@@ -3587,7 +3633,9 @@ async fn run_wait_result_script_by_path_internal(
|
||||
&w_id,
|
||||
job_payload,
|
||||
PushArgs { args: &args.args, extra: args.extra },
|
||||
authed.display_username(),
|
||||
&label_prefix
|
||||
.map(|x| x + authed.display_username())
|
||||
.unwrap_or_else(|| authed.display_username().to_string()),
|
||||
&authed.email,
|
||||
username_to_permissioned_as(&authed.username),
|
||||
None,
|
||||
@@ -3644,6 +3692,7 @@ pub async fn run_wait_result_script_by_hash(
|
||||
priority,
|
||||
delete_after_use,
|
||||
timeout,
|
||||
has_preprocessor,
|
||||
) = get_path_tag_limits_cache_for_hash(&mut tx, &w_id, hash).await?;
|
||||
if let Some(run_query_cache_ttl) = run_query.cache_ttl {
|
||||
cache_ttl = Some(run_query_cache_ttl);
|
||||
@@ -3669,6 +3718,8 @@ pub async fn run_wait_result_script_by_hash(
|
||||
language,
|
||||
dedicated_worker,
|
||||
priority,
|
||||
apply_preprocessor: !run_query.skip_preprocessor.unwrap_or(false)
|
||||
&& has_preprocessor.unwrap_or(false),
|
||||
},
|
||||
PushArgs { args: &args.args, extra: args.extra },
|
||||
authed.display_username(),
|
||||
@@ -3712,12 +3763,12 @@ pub async fn run_wait_result_flow_by_path(
|
||||
check_license_key_valid().await?;
|
||||
|
||||
run_wait_result_flow_by_path_internal(
|
||||
db, run_query, flow_path, authed, rsmq, user_db, args, w_id,
|
||||
db, run_query, flow_path, authed, rsmq, user_db, args, w_id, None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn run_wait_result_flow_by_path_internal(
|
||||
pub async fn run_wait_result_flow_by_path_internal(
|
||||
db: sqlx::Pool<Postgres>,
|
||||
run_query: RunJobQuery,
|
||||
flow_path: StripPath,
|
||||
@@ -3726,6 +3777,7 @@ async fn run_wait_result_flow_by_path_internal(
|
||||
user_db: UserDB,
|
||||
args: PushArgsOwned,
|
||||
w_id: String,
|
||||
label_prefix: Option<String>,
|
||||
) -> error::Result<Response> {
|
||||
check_queue_too_long(&db, run_query.queue_limit).await?;
|
||||
|
||||
@@ -3736,8 +3788,8 @@ async fn run_wait_result_flow_by_path_internal(
|
||||
|
||||
let scheduled_for = run_query.get_scheduled_for(&db).await?;
|
||||
|
||||
let (tag, dedicated_worker, early_return) = sqlx::query!(
|
||||
"SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return
|
||||
let (tag, dedicated_worker, early_return, has_preprocessor) = sqlx::query!(
|
||||
"SELECT tag, dedicated_worker, flow_version.value->>'early_return' as early_return, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor
|
||||
FROM flow
|
||||
LEFT JOIN flow_version
|
||||
ON flow_version.id = flow.versions[array_upper(flow.versions, 1)]
|
||||
@@ -3747,7 +3799,7 @@ async fn run_wait_result_flow_by_path_internal(
|
||||
)
|
||||
.fetch_optional(&mut tx)
|
||||
.await?
|
||||
.map(|x| (x.tag, x.dedicated_worker, x.early_return))
|
||||
.map(|x| (x.tag, x.dedicated_worker, x.early_return, x.has_preprocessor))
|
||||
.ok_or_else(|| {
|
||||
Error::NotFound(format!(
|
||||
"flow not found at path {flow_path} in workspace {w_id}"
|
||||
@@ -3763,9 +3815,16 @@ async fn run_wait_result_flow_by_path_internal(
|
||||
&db,
|
||||
tx,
|
||||
&w_id,
|
||||
JobPayload::Flow { path: flow_path.to_string(), dedicated_worker },
|
||||
JobPayload::Flow {
|
||||
path: flow_path.to_string(),
|
||||
dedicated_worker,
|
||||
apply_preprocessor: !run_query.skip_preprocessor.unwrap_or(false)
|
||||
&& has_preprocessor.unwrap_or(false),
|
||||
},
|
||||
PushArgs { args: &args.args, extra: args.extra },
|
||||
authed.display_username(),
|
||||
&label_prefix
|
||||
.map(|x| x + authed.display_username())
|
||||
.unwrap_or_else(|| authed.display_username().to_string()),
|
||||
&authed.email,
|
||||
username_to_permissioned_as(&authed.username),
|
||||
scheduled_for,
|
||||
@@ -3801,7 +3860,7 @@ async fn run_preview_script(
|
||||
#[cfg(feature = "enterprise")]
|
||||
check_license_key_valid().await?;
|
||||
|
||||
check_scopes(&authed, || format!("runscript"))?;
|
||||
check_scopes(&authed, || format!("jobs:runscript"))?;
|
||||
if authed.is_operator {
|
||||
return Err(error::Error::NotAuthorized(
|
||||
"Operators cannot run preview jobs for security reasons".to_string(),
|
||||
@@ -3871,7 +3930,7 @@ async fn run_bundle_preview_script(
|
||||
|
||||
check_license_key_valid().await?;
|
||||
|
||||
check_scopes(&authed, || format!("runscript"))?;
|
||||
check_scopes(&authed, || format!("jobs:runscript"))?;
|
||||
if authed.is_operator {
|
||||
return Err(error::Error::NotAuthorized(
|
||||
"Operators cannot run preview jobs for security reasons".to_string(),
|
||||
@@ -4202,6 +4261,7 @@ async fn add_batch_jobs(
|
||||
_priority,
|
||||
_delete_after_use,
|
||||
timeout,
|
||||
_,
|
||||
) = get_latest_deployed_hash_for_path(&db, &w_id, &path).await?;
|
||||
(
|
||||
Some(script_hash),
|
||||
@@ -4228,7 +4288,11 @@ async fn add_batch_jobs(
|
||||
JobPayload::RawFlow { value: fv.clone(), path: None, restarted_from: None }
|
||||
} else {
|
||||
if let Some(path) = batch_info.path.as_ref() {
|
||||
JobPayload::Flow { path: path.to_string(), dedicated_worker: None }
|
||||
JobPayload::Flow {
|
||||
path: path.to_string(),
|
||||
dedicated_worker: None,
|
||||
apply_preprocessor: false,
|
||||
}
|
||||
} else {
|
||||
Err(anyhow::anyhow!(
|
||||
"Path is required if no value is not provided"
|
||||
@@ -4352,7 +4416,7 @@ async fn run_preview_flow_job(
|
||||
Query(run_query): Query<RunJobQuery>,
|
||||
Json(raw_flow): Json<PreviewFlow>,
|
||||
) -> error::Result<(StatusCode, String)> {
|
||||
check_scopes(&authed, || format!("runflow"))?;
|
||||
check_scopes(&authed, || format!("jobs:runflow"))?;
|
||||
if authed.is_operator {
|
||||
return Err(error::Error::NotAuthorized(
|
||||
"Operators cannot run preview jobs for security reasons".to_string(),
|
||||
@@ -4450,6 +4514,7 @@ pub async fn run_job_by_hash_inner(
|
||||
priority,
|
||||
_delete_after_use, // not taken into account in async endpoints
|
||||
timeout,
|
||||
has_preprocessor,
|
||||
) = get_path_tag_limits_cache_for_hash(&mut tx, &w_id, hash).await?;
|
||||
check_scopes(&authed, || format!("run:script/{path}"))?;
|
||||
if let Some(run_query_cache_ttl) = run_query.cache_ttl {
|
||||
@@ -4475,6 +4540,8 @@ pub async fn run_job_by_hash_inner(
|
||||
language,
|
||||
dedicated_worker,
|
||||
priority,
|
||||
apply_preprocessor: !run_query.skip_preprocessor.unwrap_or(false)
|
||||
&& has_preprocessor.unwrap_or(false),
|
||||
},
|
||||
PushArgs { args: &args.args, extra: args.extra },
|
||||
&label_prefix
|
||||
@@ -4507,6 +4574,7 @@ pub async fn run_job_by_hash_inner(
|
||||
pub struct JobUpdateQuery {
|
||||
pub running: bool,
|
||||
pub log_offset: i32,
|
||||
pub get_progress: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -4516,6 +4584,7 @@ pub struct JobUpdate {
|
||||
pub new_logs: Option<String>,
|
||||
pub log_offset: Option<i32>,
|
||||
pub mem_peak: Option<i32>,
|
||||
pub progress: Option<i32>,
|
||||
pub flow_status: Option<Box<serde_json::value::RawValue>>,
|
||||
}
|
||||
|
||||
@@ -4583,7 +4652,7 @@ async fn get_job_update(
|
||||
OptAuthed(opt_authed): OptAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, job_id)): Path<(String, Uuid)>,
|
||||
Query(JobUpdateQuery { running, log_offset }): Query<JobUpdateQuery>,
|
||||
Query(JobUpdateQuery { running, log_offset, get_progress }): Query<JobUpdateQuery>,
|
||||
) -> error::JsonResult<JobUpdate> {
|
||||
let record = sqlx::query_as::<_, JobUpdateRow>(
|
||||
"SELECT running, substr(concat(coalesce(queue.logs, ''), job_logs.logs), greatest($1 - job_logs.log_offset, 0)) as logs, mem_peak,
|
||||
@@ -4599,6 +4668,20 @@ async fn get_job_update(
|
||||
.fetch_optional(&db)
|
||||
.await?;
|
||||
|
||||
let progress: Option<i32> = if get_progress == Some(true){
|
||||
sqlx::query_scalar!(
|
||||
"SELECT scalar_int FROM job_stats WHERE workspace_id = $1 AND job_id = $2 AND metric_id = $3",
|
||||
&w_id,
|
||||
job_id,
|
||||
"progress_perc"
|
||||
|
||||
)
|
||||
.fetch_optional(&db)
|
||||
.await?.and_then(|inner| inner)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(record) = record {
|
||||
if opt_authed.is_none() && record.created_by != "anonymous" {
|
||||
return Err(Error::BadRequest(
|
||||
@@ -4616,6 +4699,7 @@ async fn get_job_update(
|
||||
completed: None,
|
||||
new_logs: record.logs,
|
||||
mem_peak: record.mem_peak,
|
||||
progress,
|
||||
flow_status: record
|
||||
.flow_status
|
||||
.map(|x: sqlx::types::Json<Box<RawValue>>| x.0),
|
||||
@@ -4648,6 +4732,7 @@ async fn get_job_update(
|
||||
log_offset: record.log_offset,
|
||||
new_logs: record.logs,
|
||||
mem_peak: record.mem_peak,
|
||||
progress,
|
||||
flow_status: record
|
||||
.flow_status
|
||||
.map(|x: sqlx::types::Json<Box<RawValue>>| x.0),
|
||||
@@ -4771,14 +4856,19 @@ pub fn list_completed_jobs_query(
|
||||
lq: &ListCompletedQuery,
|
||||
fields: &[&str],
|
||||
join_outstanding_wait_times: bool,
|
||||
tags: Option<Vec<&str>>,
|
||||
) -> SqlBuilder {
|
||||
let sqlb = SqlBuilder::select_from("completed_job")
|
||||
let mut sqlb = SqlBuilder::select_from("completed_job")
|
||||
.fields(fields)
|
||||
.order_by("created_at", lq.order_desc.unwrap_or(true))
|
||||
.offset(offset)
|
||||
.limit(per_page)
|
||||
.clone();
|
||||
|
||||
if let Some(tags) = tags {
|
||||
sqlb.and_where_in("tag", &tags.iter().map(|x| quote(x)).collect::<Vec<_>>());
|
||||
}
|
||||
|
||||
filter_list_completed_query(sqlb, lq, w_id, join_outstanding_wait_times)
|
||||
}
|
||||
#[derive(Deserialize, Clone)]
|
||||
@@ -4823,7 +4913,7 @@ async fn list_completed_jobs(
|
||||
Query(pagination): Query<Pagination>,
|
||||
Query(lq): Query<ListCompletedQuery>,
|
||||
) -> error::JsonResult<Vec<ListableCompletedJob>> {
|
||||
check_scopes(&authed, || format!("listjobs"))?;
|
||||
check_scopes(&authed, || format!("jobs:listjobs"))?;
|
||||
|
||||
let (per_page, offset) = paginate(pagination);
|
||||
|
||||
@@ -4865,6 +4955,7 @@ async fn list_completed_jobs(
|
||||
"'CompletedJob' as type",
|
||||
],
|
||||
false,
|
||||
get_scope_tags(&authed),
|
||||
)
|
||||
.sql()?;
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
@@ -5089,7 +5180,7 @@ async fn delete_completed_job<'a>(
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path((w_id, id)): Path<(String, Uuid)>,
|
||||
) -> error::Result<Response> {
|
||||
check_scopes(&authed, || format!("deletejob"))?;
|
||||
check_scopes(&authed, || format!("jobs:deletejob"))?;
|
||||
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user