diff --git a/.github/DockerfileBackendTests b/.github/DockerfileBackendTests index 355e840ccb..5792e5753b 100644 --- a/.github/DockerfileBackendTests +++ b/.github/DockerfileBackendTests @@ -1,22 +1,6 @@ -ARG DEBIAN_IMAGE=debian:bookworm-slim ARG RUST_IMAGE=rust:1.80-slim-bookworm ARG PYTHON_IMAGE=python:3.11.4-slim-bookworm -FROM ${DEBIAN_IMAGE} as downloader - -ARG TARGETPLATFORM - -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.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 - FROM ${RUST_IMAGE} as builder @@ -31,7 +15,7 @@ ENV SQLX_OFFLINE=true RUN mkdir -p /frontend/build RUN apt-get update \ - && apt-get install -y ca-certificates tzdata libpq5 cmake\ + && apt-get install -y ca-certificates tzdata libpq5 cmake unzip\ make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \ libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libxml2-dev \ libxmlsec1-dev libffi-dev liblzma-dev mecab-ipadic-utf8 libgdbm-dev libc6-dev git libprotobuf-dev libnl-route-3-dev \ @@ -56,13 +40,14 @@ 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.27 /usr/local/bin/bun /usr/bin/bun +COPY --from=oven/bun:1.1.30 /usr/local/bin/bun /usr/bin/bun +ARG TARGETPLATFORM -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 curl -Lsf https://github.com/denoland/deno/releases/download/v2.0.0/deno-x86_64-unknown-linux-gnu.zip -o deno.zip +# RUN [ "$TARGETPLATFORM" == "linux/arm64" ] && curl -Lsf https://github.com/denoland/deno/releases/download/v2.0.0/deno-aarch64-unknown-linux-gnu.zip -o deno.zip || true -COPY --from=downloader --chmod=755 /deno /usr/bin/deno +RUN unzip deno.zip && rm deno.zip && mv deno /usr/bin/deno RUN apt-get update \ && apt-get install -y postgresql-client --allow-unauthenticated diff --git a/.github/workflows/backend-test.yml b/.github/workflows/backend-test.yml index bedd324f9e..cbcf40ebe6 100644 --- a/.github/workflows/backend-test.yml +++ b/.github/workflows/backend-test.yml @@ -41,6 +41,10 @@ jobs: - name: cargo test timeout-minutes: 15 run: + /usr/bin/deno --version && + /usr/bin/bun -v && + go version && + /usr/local/bin/python3 --version && mkdir frontend/build && cd backend && touch windmill-api/openapi-deref.yaml && DATABASE_URL=postgres://postgres:changeme@postgres:5432/windmill diff --git a/.github/workflows/build-publish-rh-image.yml b/.github/workflows/build-publish-rh-image.yml new file mode 100644 index 0000000000..b957ac5148 --- /dev/null +++ b/.github/workflows/build-publish-rh-image.yml @@ -0,0 +1,128 @@ +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +name: Build and publish windmill for RHEL9 +on: + workflow_dispatch + +permissions: write-all + +jobs: + build_ee: + runs-on: ubicloud + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Read EE repo commit hash + run: | + echo "ee_repo_ref=$(cat ./backend/ee-repo-ref.txt)" >> "$GITHUB_ENV" + + - uses: actions/checkout@v4 + with: + repository: windmill-labs/windmill-ee-private + path: ./windmill-ee-private + ref: ${{ env.ee_repo_ref }} + token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }} + fetch-depth: 0 + + # - name: Set up Docker Buildx + # uses: docker/setup-buildx-action@v2 + - uses: depot/setup-action@v1 + + - name: Docker meta + id: meta-ee-public + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-rhel9 + flavor: | + latest=false + tags: | + type=sha + + - name: Login to registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Substitute EE code + run: | + ./backend/substitute_ee_code.sh --copy --dir ./windmill-ee-private + + - name: Copy RHEL9 Dockerfile + run: | + cp ./docker/RHEL9/Dockerfile ./Dockerfile + + - name: Build and push publicly ee amd64 + uses: depot/build-push-action@v1 + with: + context: . + platforms: linux/amd64 + push: true + build-args: | + features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core + secrets: | + rh_username=${{ secrets.RH_USERNAME }} + rh_password=${{ secrets.RH_PASSWORD }} + tags: | + ${{ steps.meta-ee-public.outputs.tags }}-amd64 + labels: | + ${{ steps.meta-ee-public.outputs.labels }}-amd64 + org.opencontainers.image.licenses=Windmill-Enterprise-License + + - name: Build and push publicly ee arm64 + uses: depot/build-push-action@v1 + with: + context: . + platforms: linux/arm64 + push: true + build-args: | + features=enterprise,enterprise_saml,stripe,embedding,parquet,prometheus,openidconnect,cloud,jemalloc,deno_core + secrets: | + rh_username=${{ secrets.RH_USERNAME }} + rh_password=${{ secrets.RH_PASSWORD }} + tags: | + ${{ steps.meta-ee-public.outputs.tags }}-arm64 + labels: | + ${{ steps.meta-ee-public.outputs.labels }}-arm64 + org.opencontainers.image.licenses=Windmill-Enterprise-License + + - uses: shrink/actions-docker-extract@v3 + id: extract-ee-amd64 + with: + image: ${{ steps.meta-ee-public.outputs.tags}}-amd64 + path: "/windmill/target/release/windmill" + + - uses: shrink/actions-docker-extract@v3 + id: extract-ee-arm64 + with: + image: ${{ steps.meta-ee-public.outputs.tags}}-arm64 + path: "/windmill/target/release/windmill" + + - name: Rename binary with corresponding architecture + run: | + mv "${{ steps.extract-ee-amd64.outputs.destination }}/windmill" "${{ steps.extract-ee-amd64.outputs.destination }}/windmill-ee-amd64-rhel9" + mv "${{ steps.extract-ee-arm64.outputs.destination }}/windmill" "${{ steps.extract-ee-arm64.outputs.destination }}/windmill-ee-arm64-rhel9" + + - uses: actions/upload-artifact@v4 + with: + name: RHEL9-amd64 build + path: ${{ steps.extract-ee-amd64.outputs.destination }}/windmill-ee-amd64-rhel9 + + - uses: actions/upload-artifact@v4 + with: + name: RHEL9-arm64 build + path: ${{ steps.extract-ee-arm64.outputs.destination }}/windmill-ee-arm64-rhel9 + + # - name: Attach binary to release + # uses: softprops/action-gh-release@v2 + # if: startsWith(github.ref, 'refs/tags/') + # with: + # files: | + # ${{ steps.extract-ee-arm64.outputs.destination }}/windmill-ee-arm64-rhel9 + # ${{ steps.extract-ee-amd64.outputs.destination }}/windmill-ee-amd64-rhel9 diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 7089a870c9..f0928cbd33 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -394,7 +394,7 @@ jobs: verify_ee_image_vulnerabilities: runs-on: ubicloud needs: [tag_latest_ee] - # if: ${{ startsWith(github.ref, 'refs/tags/') }} + if: ${{ startsWith(github.ref, 'refs/tags/') }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -589,8 +589,6 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-cuda - flavor: | - latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -635,8 +633,6 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-slim - flavor: | - latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -680,8 +676,6 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-slim - flavor: | - latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -726,8 +720,6 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-full - flavor: | - latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} @@ -771,8 +763,6 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee-full - flavor: | - latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} diff --git a/CHANGELOG.md b/CHANGELOG.md index dfb6a7a657..218c4a4842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,70 @@ # Changelog +## [1.409.2](https://github.com/windmill-labs/windmill/compare/v1.409.1...v1.409.2) (2024-10-16) + + +### Bug Fixes + +* add extra args support for exception to bun scripts ([1466da3](https://github.com/windmill-labs/windmill/commit/1466da3999add0238b9c42ca13df52194f082fc0)) +* fix script persistence in url + add support for extra error args in python ([3174024](https://github.com/windmill-labs/windmill/commit/3174024d8e6ecbe9f8c9e1ea055d611f652c0057)) + +## [1.409.1](https://github.com/windmill-labs/windmill/compare/v1.409.0...v1.409.1) (2024-10-16) + + +### Bug Fixes + +* **apidocs:** fix generated openapi files ([d24e153](https://github.com/windmill-labs/windmill/commit/d24e1530655d27ffda9bb4c19471dc1431124cc2)) +* **git-sync:** propagate update of folders with git sync ([6abb346](https://github.com/windmill-labs/windmill/commit/6abb346013da4a907a860713a8a67642985b8025)) + +## [1.409.0](https://github.com/windmill-labs/windmill/compare/v1.408.1...v1.409.0) (2024-10-16) + + +### Features + +* **frontend:** unify all triggers UX and simplify flow settings ([#4259](https://github.com/windmill-labs/windmill/issues/4259)) ([91a3d06](https://github.com/windmill-labs/windmill/commit/91a3d065298cce7a882464fa0cd31d8f1ae9dda2)) +* Scroll to element in virtual list when clicking on graph point ([#4532](https://github.com/windmill-labs/windmill/issues/4532)) ([7126ba1](https://github.com/windmill-labs/windmill/commit/7126ba12c7eb52d2cfbe8d83311b5592a5707bce)) +* **sso:** adding the ability to define a custom display name for sso ([#4529](https://github.com/windmill-labs/windmill/issues/4529)) ([99c5b3e](https://github.com/windmill-labs/windmill/commit/99c5b3ecdacb1158c2cba5b891c4c3b8b70c3b6a)) + + +### Bug Fixes + +* Add indexer backup lock to fit the deployment model ([#4531](https://github.com/windmill-labs/windmill/issues/4531)) ([411bce7](https://github.com/windmill-labs/windmill/commit/411bce7e13aabfa53db80d55261ea4511f6d1ae9)) +* **app:** accept connecting to non yet existing state output for convenience ([9eb1ecc](https://github.com/windmill-labs/windmill/commit/9eb1ecc9f3017e2f4284a827a2bcd21f36b1b8ac)) +* **app:** improve absolute url handling in download button and downloadFile ([dcdbf1a](https://github.com/windmill-labs/windmill/commit/dcdbf1afb4d5a18e00b9bbb1eb0bef129ea5667f)) +* **app:** make s3 uploads persistent across tabs change ([c3b536b](https://github.com/windmill-labs/windmill/commit/c3b536b1b8069898131768867a187b186b21e537)) +* canceled jobs button reporting 0 jobs cancelled ([#4534](https://github.com/windmill-labs/windmill/issues/4534)) ([e736572](https://github.com/windmill-labs/windmill/commit/e736572db10929ae5e123c4f6cef73b8e90fc29b)) +* **python-client:** improve get_job_status for running jobs ([a8c4ea2](https://github.com/windmill-labs/windmill/commit/a8c4ea2334d2535fa7d5d43f58d65565afe8f3e5)) +* **ui:** dark mode support for queue metrics based critical alert ([#4535](https://github.com/windmill-labs/windmill/issues/4535)) ([f38b3d1](https://github.com/windmill-labs/windmill/commit/f38b3d14e8092ae58817511aea91a4e77725ead6)) + +## [1.408.1](https://github.com/windmill-labs/windmill/compare/v1.408.0...v1.408.1) (2024-10-12) + + +### Bug Fixes + +* fix deno cache --allow-import on deno 2 ([42fe31f](https://github.com/windmill-labs/windmill/commit/42fe31f804c9e6643cd90167494e45270831e013)) + +## [1.408.0](https://github.com/windmill-labs/windmill/compare/v1.407.2...v1.408.0) (2024-10-12) + + +### Features + +* **app builder:** file download helper ([#4511](https://github.com/windmill-labs/windmill/issues/4511)) ([f82f091](https://github.com/windmill-labs/windmill/commit/f82f09129096cfff975370d8bb7b6d832a2b8f9f)) + + +### Bug Fixes + +* **cli:** handle case where 'toString' is a schema field ([568cc66](https://github.com/windmill-labs/windmill/commit/568cc66932fb0470f5e89de7b02d94dba4050638)) +* **frontend:** s3 file uploader works on public apps too ([982dde2](https://github.com/windmill-labs/windmill/commit/982dde2b9dfe6d9eda300c683af729d97a03cb4d)) +* **frontend:** set unused schema property fields to null ([be11240](https://github.com/windmill-labs/windmill/commit/be112408e7c4601314726e9517c37daaeaa1bf09)) +* improve workflow as code row-lock on db to handle more concurrency ([d2c4d3f](https://github.com/windmill-labs/windmill/commit/d2c4d3fa207379cb0b8ac180f6ccc759045580e8)) + +## [1.407.2](https://github.com/windmill-labs/windmill/compare/v1.407.1...v1.407.2) (2024-10-10) + + +### Bug Fixes + +* improve default properties of new nodes of flows (suspend, branchone, branchall) ([d9bdc5a](https://github.com/windmill-labs/windmill/commit/d9bdc5a5b08dd4d0381304656af097315398c9d4)) + ## [1.407.1](https://github.com/windmill-labs/windmill/compare/v1.407.0...v1.407.1) (2024-10-10) diff --git a/Dockerfile b/Dockerfile index a896a87b26..505cf61d50 100644 --- a/Dockerfile +++ b/Dockerfile @@ -177,7 +177,7 @@ COPY --from=builder /windmill/target/release/windmill ${APP}/windmill COPY --from=denoland/deno:2.0.0 --chmod=755 /usr/bin/deno /usr/bin/deno -COPY --from=oven/bun:1.1.27 /usr/local/bin/bun /usr/bin/bun +COPY --from=oven/bun:1.1.30 /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 diff --git a/backend/.sqlx/query-14abf759dae7ba5c38017ba6001927c6df0653a02b87bcea939066e39ebcf24d.json b/backend/.sqlx/query-14abf759dae7ba5c38017ba6001927c6df0653a02b87bcea939066e39ebcf24d.json new file mode 100644 index 0000000000..29aaf47e88 --- /dev/null +++ b/backend/.sqlx/query-14abf759dae7ba5c38017ba6001927c6df0653a02b87bcea939066e39ebcf24d.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO concurrency_locks (id, last_locked_at, owner)\n VALUES ($1, now(), $2)\n ON CONFLICT (id)\n DO UPDATE SET\n last_locked_at = now(),\n owner = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "14abf759dae7ba5c38017ba6001927c6df0653a02b87bcea939066e39ebcf24d" +} diff --git a/backend/.sqlx/query-1ca5bc2d35c0498b587fd0618434def64233dc4f8fc3344d8d74be8e96ded659.json b/backend/.sqlx/query-1ca5bc2d35c0498b587fd0618434def64233dc4f8fc3344d8d74be8e96ded659.json new file mode 100644 index 0000000000..3a2e44bdba --- /dev/null +++ b/backend/.sqlx/query-1ca5bc2d35c0498b587fd0618434def64233dc4f8fc3344d8d74be8e96ded659.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM schedule WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Bool", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "1ca5bc2d35c0498b587fd0618434def64233dc4f8fc3344d8d74be8e96ded659" +} diff --git a/backend/.sqlx/query-31bc3dcea29be9cc0242771d25a232f173446d29c08fc29ddb8d55294f2c070e.json b/backend/.sqlx/query-31bc3dcea29be9cc0242771d25a232f173446d29c08fc29ddb8d55294f2c070e.json new file mode 100644 index 0000000000..49fc84c349 --- /dev/null +++ b/backend/.sqlx/query-31bc3dcea29be9cc0242771d25a232f173446d29c08fc29ddb8d55294f2c070e.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM http_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Bool", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "31bc3dcea29be9cc0242771d25a232f173446d29c08fc29ddb8d55294f2c070e" +} diff --git a/backend/.sqlx/query-57e270e032e8c04dda7b5c1ca949861756b3ad367a4a500728332a7cb91560a4.json b/backend/.sqlx/query-57e270e032e8c04dda7b5c1ca949861756b3ad367a4a500728332a7cb91560a4.json new file mode 100644 index 0000000000..ccf6b0ad8f --- /dev/null +++ b/backend/.sqlx/query-57e270e032e8c04dda7b5c1ca949861756b3ad367a4a500728332a7cb91560a4.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE concurrency_locks SET\n last_locked_at = now()\n WHERE id = $1 AND owner = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "57e270e032e8c04dda7b5c1ca949861756b3ad367a4a500728332a7cb91560a4" +} diff --git a/backend/.sqlx/query-5fc6b4a4dbb7875bdec76f876c18543435a95b019b20081f52f6ed6f4457e3c7.json b/backend/.sqlx/query-5fc6b4a4dbb7875bdec76f876c18543435a95b019b20081f52f6ed6f4457e3c7.json new file mode 100644 index 0000000000..d4725c224e --- /dev/null +++ b/backend/.sqlx/query-5fc6b4a4dbb7875bdec76f876c18543435a95b019b20081f52f6ed6f4457e3c7.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "5fc6b4a4dbb7875bdec76f876c18543435a95b019b20081f52f6ed6f4457e3c7" +} diff --git a/backend/.sqlx/query-5fd70c70ce52cbc51fa9124cb05f82b5951f17d1b7eade53c6d89253d55f8b9f.json b/backend/.sqlx/query-5fd70c70ce52cbc51fa9124cb05f82b5951f17d1b7eade53c6d89253d55f8b9f.json new file mode 100644 index 0000000000..51f58cb81c --- /dev/null +++ b/backend/.sqlx/query-5fd70c70ce52cbc51fa9124cb05f82b5951f17d1b7eade53c6d89253d55f8b9f.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT owner FROM concurrency_locks WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "owner", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + true + ] + }, + "hash": "5fd70c70ce52cbc51fa9124cb05f82b5951f17d1b7eade53c6d89253d55f8b9f" +} diff --git a/backend/.sqlx/query-a7f5431e3b8960e9dc46fae69dd4391516d8b169186548ec44528c84078b80d8.json b/backend/.sqlx/query-a7f5431e3b8960e9dc46fae69dd4391516d8b169186548ec44528c84078b80d8.json new file mode 100644 index 0000000000..7dc8e3efa7 --- /dev/null +++ b/backend/.sqlx/query-a7f5431e3b8960e9dc46fae69dd4391516d8b169186548ec44528c84078b80d8.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "a7f5431e3b8960e9dc46fae69dd4391516d8b169186548ec44528c84078b80d8" +} diff --git a/backend/.sqlx/query-c060b8bbc5af7d2e7d0aaff64f0f62ec9db58611a99b0ba7f0375638b128ab89.json b/backend/.sqlx/query-c060b8bbc5af7d2e7d0aaff64f0f62ec9db58611a99b0ba7f0375638b128ab89.json new file mode 100644 index 0000000000..1a37220559 --- /dev/null +++ b/backend/.sqlx/query-c060b8bbc5af7d2e7d0aaff64f0f62ec9db58611a99b0ba7f0375638b128ab89.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT schedule FROM schedule WHERE path = $1 AND script_path = $1 AND is_flow = $2 AND workspace_id = $3", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "schedule", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text", + "Bool", + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "c060b8bbc5af7d2e7d0aaff64f0f62ec9db58611a99b0ba7f0375638b128ab89" +} diff --git a/backend/.sqlx/query-34ad8a2a5bd89b9b8e25847a7e5e94ef99e35a178ad6328c1bcde2a6d6f88cb5.json b/backend/.sqlx/query-c624f15f3e321b1eecf123da9bf0b18e8c1d16ef25ffb9d04e5447d0d583d55c.json similarity index 58% rename from backend/.sqlx/query-34ad8a2a5bd89b9b8e25847a7e5e94ef99e35a178ad6328c1bcde2a6d6f88cb5.json rename to backend/.sqlx/query-c624f15f3e321b1eecf123da9bf0b18e8c1d16ef25ffb9d04e5447d0d583d55c.json index 43d0f596ae..edb2fc7f49 100644 --- a/backend/.sqlx/query-34ad8a2a5bd89b9b8e25847a7e5e94ef99e35a178ad6328c1bcde2a6d6f88cb5.json +++ b/backend/.sqlx/query-c624f15f3e321b1eecf123da9bf0b18e8c1d16ef25ffb9d04e5447d0d583d55c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO token\n (token, email, label, expiration, super_admin, scopes)\n VALUES ($1, $2, $3, $4, $5, $6)", + "query": "INSERT INTO token\n (token, email, label, expiration, super_admin, scopes, workspace_id)\n VALUES ($1, $2, $3, $4, $5, $6, $7)", "describe": { "columns": [], "parameters": { @@ -10,10 +10,11 @@ "Varchar", "Timestamptz", "Bool", - "TextArray" + "TextArray", + "Varchar" ] }, "nullable": [] }, - "hash": "34ad8a2a5bd89b9b8e25847a7e5e94ef99e35a178ad6328c1bcde2a6d6f88cb5" + "hash": "c624f15f3e321b1eecf123da9bf0b18e8c1d16ef25ffb9d04e5447d0d583d55c" } diff --git a/backend/.sqlx/query-c7ee7ce64686cef41cebd99ad7ef31572fc1bf12e6ae473fd58fafb025989965.json b/backend/.sqlx/query-c7ee7ce64686cef41cebd99ad7ef31572fc1bf12e6ae473fd58fafb025989965.json new file mode 100644 index 0000000000..7dd454bbbe --- /dev/null +++ b/backend/.sqlx/query-c7ee7ce64686cef41cebd99ad7ef31572fc1bf12e6ae473fd58fafb025989965.json @@ -0,0 +1,59 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "label", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "token_prefix", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "expiration", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "last_used_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "scopes", + "type_info": "TextArray" + }, + { + "ordinal": 6, + "name": "email", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + true, + null, + true, + false, + false, + true, + true + ] + }, + "hash": "c7ee7ce64686cef41cebd99ad7ef31572fc1bf12e6ae473fd58fafb025989965" +} diff --git a/backend/.sqlx/query-cecf1addc4aecb087a14786b2a9165895ca61ef042947c7314f66514d7f29edc.json b/backend/.sqlx/query-cecf1addc4aecb087a14786b2a9165895ca61ef042947c7314f66514d7f29edc.json new file mode 100644 index 0000000000..361f5ebd78 --- /dev/null +++ b/backend/.sqlx/query-cecf1addc4aecb087a14786b2a9165895ca61ef042947c7314f66514d7f29edc.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT last_locked_at\n FROM concurrency_locks\n WHERE id = $1\n FOR UPDATE", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "last_locked_at", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "cecf1addc4aecb087a14786b2a9165895ca61ef042947c7314f66514d7f29edc" +} diff --git a/backend/.sqlx/query-d7a0f19f9e18d2ea49316012375ad78b69292ba091d69880945e42bebe890d66.json b/backend/.sqlx/query-d7a0f19f9e18d2ea49316012375ad78b69292ba091d69880945e42bebe890d66.json new file mode 100644 index 0000000000..f619796a27 --- /dev/null +++ b/backend/.sqlx/query-d7a0f19f9e18d2ea49316012375ad78b69292ba091d69880945e42bebe890d66.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "d7a0f19f9e18d2ea49316012375ad78b69292ba091d69880945e42bebe890d66" +} diff --git a/backend/.sqlx/query-eff32aeac25a75d06f73e08c26dd3fd25f6b85cbea870505751c6a82457ae1da.json b/backend/.sqlx/query-eff32aeac25a75d06f73e08c26dd3fd25f6b85cbea870505751c6a82457ae1da.json new file mode 100644 index 0000000000..2190ea06eb --- /dev/null +++ b/backend/.sqlx/query-eff32aeac25a75d06f73e08c26dd3fd25f6b85cbea870505751c6a82457ae1da.json @@ -0,0 +1,59 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "label", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "token_prefix", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "expiration", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "last_used_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 5, + "name": "scopes", + "type_info": "TextArray" + }, + { + "ordinal": 6, + "name": "email", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + true, + null, + true, + false, + false, + true, + true + ] + }, + "hash": "eff32aeac25a75d06f73e08c26dd3fd25f6b85cbea870505751c6a82457ae1da" +} diff --git a/backend/.sqlx/query-f06e0e4fa358b26792df22fff48b71a6fcfa1e5603ea472892917c1accd1aafb.json b/backend/.sqlx/query-f06e0e4fa358b26792df22fff48b71a6fcfa1e5603ea472892917c1accd1aafb.json new file mode 100644 index 0000000000..71cdfe60bf --- /dev/null +++ b/backend/.sqlx/query-f06e0e4fa358b26792df22fff48b71a6fcfa1e5603ea472892917c1accd1aafb.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "f06e0e4fa358b26792df22fff48b71a6fcfa1e5603ea472892917c1accd1aafb" +} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index f680c30849..b8d7319fb4 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -486,9 +486,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429" +checksum = "103db485efc3e41214fe4fda9f3dbeae2eb9082f48fd236e6095627a9422066e" dependencies = [ "brotli 7.0.0", "bzip2", @@ -650,7 +650,7 @@ dependencies = [ "hex", "hmac", "http-types", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-tls 0.5.0", "serde", "serde_json", @@ -794,14 +794,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] name = "aws-sdk-sso" -version = "1.45.0" +version = "1.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33ae899566f3d395cbf42858e433930682cc9c1889fa89318896082fef45efb" +checksum = "0dc2faec3205d496c7e57eff685dd944203df7ce16a4116d0281c44021788a7b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -821,9 +821,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.46.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39c09e199ebd96b9f860b0fce4b6625f211e064ad7c8693b72ecf7ef03881e0" +checksum = "c93c241f52bc5e0476e259c953234dab7e2a35ee207ee202e86c0095ec4951dc" dependencies = [ "aws-credential-types", "aws-runtime", @@ -843,9 +843,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.45.0" +version = "1.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d95f93a98130389eb6233b9d615249e543f6c24a68ca1f109af9ca5164a8765" +checksum = "b259429be94a3459fa1b00c5684faee118d74f9577cc50aebadc36e507c63b5f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -954,7 +954,7 @@ dependencies = [ "http-body 0.4.6", "http-body 1.0.1", "httparse", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-rustls 0.24.2", "once_cell", "pin-project-lite", @@ -1043,7 +1043,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "itoa", "matchit", @@ -1469,9 +1469,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" dependencies = [ "bytemuck_derive", ] @@ -1599,9 +1599,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -2233,7 +2233,7 @@ dependencies = [ "arrow-array", "arrow-ipc", "arrow-schema", - "async-compression 0.4.13", + "async-compression 0.4.16", "async-trait", "bytes", "bzip2", @@ -2271,7 +2271,7 @@ dependencies = [ "tokio", "tokio-util", "url", - "uuid 1.10.0", + "uuid 1.11.0", "xz2", "zstd 0.13.2", ] @@ -2371,7 +2371,7 @@ dependencies = [ "regex", "sha2 0.10.8", "unicode-segmentation", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -2538,7 +2538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ "serde", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -2645,7 +2645,7 @@ dependencies = [ "error_reporter", "http 1.1.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-rustls 0.27.3", "hyper-util", "ipnet", @@ -2777,7 +2777,7 @@ checksum = "22a1abc6bd8af41aa2496ceceef94f4277092c781a9495c437327a17659553a2" dependencies = [ "deno_core", "deno_native_certs", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-pemfile 2.2.0", "rustls-tokio-stream", "rustls-webpki 0.102.8", @@ -2822,7 +2822,7 @@ dependencies = [ "futures", "serde", "tokio", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -3617,7 +3617,7 @@ dependencies = [ "async-trait", "base64 0.21.7", "dirs-next", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-rustls 0.24.2", "ring 0.16.20", "rustls 0.21.12", @@ -4196,9 +4196,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -4220,9 +4220,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -4247,7 +4247,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.31", "log", "rustls 0.21.12", "rustls-native-certs 0.6.3", @@ -4263,9 +4263,9 @@ checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -4280,7 +4280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.30", + "hyper 0.14.31", "native-tls", "tokio", "tokio-native-tls", @@ -4294,7 +4294,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "native-tls", "tokio", @@ -4313,7 +4313,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -4889,7 +4889,7 @@ dependencies = [ "base64 0.22.1", "gethostname", "mail-builder", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-pki-types", "smtp-proto", "tokio", @@ -5223,7 +5223,7 @@ dependencies = [ "subprocess", "thiserror", "time", - "uuid 1.10.0", + "uuid 1.11.0", "zstd 0.13.2", ] @@ -5438,7 +5438,7 @@ dependencies = [ "chrono", "futures", "humantime", - "hyper 1.4.1", + "hyper 1.5.0", "itertools 0.13.0", "md-5 0.10.6", "parking_lot", @@ -5541,9 +5541,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -5573,9 +5573,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -5742,9 +5742,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "pem" @@ -6021,7 +6021,7 @@ dependencies = [ "postgres-protocol", "serde", "serde_json", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -6132,9 +6132,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -6365,7 +6365,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.0.0", - "rustls 0.23.14", + "rustls 0.23.15", "socket2 0.5.7", "thiserror", "tokio", @@ -6382,7 +6382,7 @@ dependencies = [ "rand 0.8.5", "ring 0.17.8", "rustc-hash 2.0.0", - "rustls 0.23.14", + "rustls 0.23.15", "slab", "thiserror", "tinyvec", @@ -6690,7 +6690,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.31", "hyper-rustls 0.24.2", "hyper-tls 0.5.0", "ipnet", @@ -6728,7 +6728,7 @@ version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ - "async-compression 0.4.13", + "async-compression 0.4.16", "base64 0.22.1", "bytes", "encoding_rs", @@ -6738,7 +6738,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-rustls 0.27.3", "hyper-tls 0.6.0", "hyper-util", @@ -6751,7 +6751,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-native-certs 0.8.0", "rustls-pemfile 2.2.0", "rustls-pki-types", @@ -6844,7 +6844,7 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -7051,9 +7051,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.14" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "log", "once_cell", @@ -7122,9 +7122,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-tokio-stream" @@ -7133,7 +7133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22557157d7395bc30727745b365d923f1ecc230c4c80b176545f3f4f08c46e33" dependencies = [ "futures", - "rustls 0.23.14", + "rustls 0.23.15", "socket2 0.5.7", "tokio", ] @@ -7214,9 +7214,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -7264,7 +7264,7 @@ dependencies = [ "serde", "thiserror", "url", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -7302,7 +7302,7 @@ dependencies = [ "schemars_derive", "serde", "serde_json", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -8016,7 +8016,7 @@ dependencies = [ "once_cell", "paste", "percent-encoding", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-pemfile 2.2.0", "serde", "serde_json", @@ -8028,7 +8028,7 @@ dependencies = [ "tokio-stream", "tracing", "url", - "uuid 1.10.0", + "uuid 1.11.0", "webpki-roots 0.26.6", ] @@ -8112,7 +8112,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", "whoami", ] @@ -8154,7 +8154,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", "whoami", ] @@ -8180,7 +8180,7 @@ dependencies = [ "sqlx-core", "tracing", "url", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -8833,7 +8833,7 @@ dependencies = [ "tempfile", "thiserror", "time", - "uuid 1.10.0", + "uuid 1.11.0", "winapi", ] @@ -9041,7 +9041,7 @@ dependencies = [ "tokio-rustls 0.24.1", "tokio-util", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] @@ -9272,7 +9272,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.14", + "rustls 0.23.15", "rustls-pki-types", "tokio", ] @@ -9472,7 +9472,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" dependencies = [ - "async-compression 0.4.13", + "async-compression 0.4.16", "bitflags 2.6.0", "bytes", "futures-core", @@ -9777,7 +9777,7 @@ checksum = "04f903f293d11f31c0c29e4148f6dc0d033a7f80cebc0282bea147611667d289" dependencies = [ "getrandom 0.2.15", "rand 0.8.5", - "uuid 1.10.0", + "uuid 1.11.0", "web-time", ] @@ -9977,7 +9977,7 @@ dependencies = [ "log", "native-tls", "once_cell", - "rustls 0.23.14", + "rustls 0.23.15", "rustls-pki-types", "serde", "serde_json", @@ -10038,9 +10038,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom 0.2.15", "serde", @@ -10358,7 +10358,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "axum", @@ -10387,7 +10387,7 @@ dependencies = [ "tokio", "tracing", "url", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-api", "windmill-api-client", "windmill-common", @@ -10399,7 +10399,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "argon2", @@ -10426,7 +10426,7 @@ dependencies = [ "hf-hub", "hmac", "http 1.1.0", - "hyper 1.4.1", + "hyper 1.5.0", "itertools 0.13.0", "jsonwebtoken", "lazy_static", @@ -10470,7 +10470,7 @@ dependencies = [ "ulid", "url", "urlencoding", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-audit", "windmill-common", "windmill-git-sync", @@ -10483,7 +10483,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.407.1" +version = "1.409.2" dependencies = [ "base64 0.21.7", "chrono", @@ -10496,12 +10496,12 @@ dependencies = [ "serde", "serde_json", "syn 1.0.109", - "uuid 1.10.0", + "uuid 1.11.0", ] [[package]] name = "windmill-audit" -version = "1.407.1" +version = "1.409.2" dependencies = [ "chrono", "serde", @@ -10514,7 +10514,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "async-stream", @@ -10531,7 +10531,7 @@ dependencies = [ "git-version", "hex", "hmac", - "hyper 1.4.1", + "hyper 1.5.0", "indexmap 2.6.0", "itertools 0.13.0", "lazy_static", @@ -10554,12 +10554,13 @@ dependencies = [ "tracing-flame", "tracing-loki", "tracing-subscriber", - "uuid 1.10.0", + "uuid 1.11.0", + "windmill-macros", ] [[package]] name = "windmill-git-sync" -version = "1.407.1" +version = "1.409.2" dependencies = [ "regex", "rsmq_async", @@ -10567,19 +10568,20 @@ dependencies = [ "serde_json", "sqlx", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-common", "windmill-queue", ] [[package]] name = "windmill-indexer" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "bytes", "chrono", "futures", + "lazy_static", "object_store", "serde", "serde_json", @@ -10589,13 +10591,25 @@ dependencies = [ "tokio", "tokio-tar", "tracing", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-common", ] +[[package]] +name = "windmill-macros" +version = "1.405.5" +dependencies = [ + "itertools 0.10.5", + "lazy_static", + "proc-macro2", + "quote", + "regex", + "syn 2.0.79", +] + [[package]] name = "windmill-parser" -version = "1.407.1" +version = "1.409.2" dependencies = [ "convert_case 0.6.0", "serde", @@ -10604,7 +10618,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "lazy_static", @@ -10616,7 +10630,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "gosyn", @@ -10628,7 +10642,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "lazy_static", @@ -10640,7 +10654,7 @@ dependencies = [ [[package]] name = "windmill-parser-php" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10651,7 +10665,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -10662,7 +10676,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "async-recursion", @@ -10680,7 +10694,7 @@ dependencies = [ [[package]] name = "windmill-parser-rust" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -10697,7 +10711,7 @@ dependencies = [ [[package]] name = "windmill-parser-sql" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "lazy_static", @@ -10709,7 +10723,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "lazy_static", @@ -10727,7 +10741,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "getrandom 0.2.15", @@ -10748,7 +10762,7 @@ dependencies = [ [[package]] name = "windmill-parser-yaml" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "serde_json", @@ -10758,7 +10772,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "async-recursion", @@ -10784,14 +10798,14 @@ dependencies = [ "tokio", "tracing", "ulid", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-audit", "windmill-common", ] [[package]] name = "windmill-sql-datatype-parser-wasm" -version = "1.407.1" +version = "1.409.2" dependencies = [ "wasm-bindgen", "wasm-bindgen-test", @@ -10801,7 +10815,7 @@ dependencies = [ [[package]] name = "windmill-worker" -version = "1.407.1" +version = "1.409.2" dependencies = [ "anyhow", "async-recursion", @@ -10856,7 +10870,7 @@ dependencies = [ "tokio-util", "tracing", "urlencoding", - "uuid 1.10.0", + "uuid 1.11.0", "windmill-audit", "windmill-common", "windmill-git-sync", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index d16a2236c1..c8b68ac1b1 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.407.1" +version = "1.409.2" authors.workspace = true edition.workspace = true @@ -14,6 +14,7 @@ members = [ "./windmill-audit", "./windmill-git-sync", "./windmill-indexer", + "./windmill-macros", "./parsers/windmill-parser", "./parsers/windmill-parser-ts", "./parsers/windmill-parser-wasm", @@ -23,11 +24,11 @@ members = [ "./parsers/windmill-parser-py", "./parsers/windmill-parser-py-imports", "./parsers/windmill-sql-datatype-parser-wasm", - "./parsers/windmill-parser-yaml", + "./parsers/windmill-parser-yaml", "windmill-macros", ] [workspace.package] -version = "1.407.1" +version = "1.409.2" authors = ["Ruben Fiszel "] edition = "2021" @@ -39,6 +40,9 @@ path = "./src/main.rs" opt-level = 0 incremental = true +[profile.release] +lto = "thin" + [features] default = [] enterprise = ["windmill-worker/enterprise", "windmill-queue/enterprise", "windmill-api/enterprise", "windmill-git-sync/enterprise", "windmill-common/prometheus", "windmill-common/enterprise", "windmill-indexer/enterprise"] @@ -113,6 +117,7 @@ windmill-common = { path = "./windmill-common", default-features = false } windmill-audit = { path = "./windmill-audit" } windmill-git-sync = { path = "./windmill-git-sync" } windmill-indexer = {path = "./windmill-indexer"} +windmill-macros = {path = "./windmill-macros"} windmill-parser = { path = "./parsers/windmill-parser" } windmill-parser-ts = { path = "./parsers/windmill-parser-ts" } windmill-parser-py = { path = "./parsers/windmill-parser-py" } @@ -278,6 +283,8 @@ triomphe = "^0" tantivy = "0.22.0" +# Macro-related +proc-macro2 = "1.0" pulldown-cmark = "0.9" toml = "0.7" syn = { version = "2.0.74", features = ["full"] } diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 5912afd498..1472a7591a 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -8e3fbda05392e641c15262924dc0df47cc42d036 \ No newline at end of file +0428068e4fbbd1380a4d8bbaab5c8e7955decdb8 diff --git a/backend/src/main.rs b/backend/src/main.rs index cca4f6f9a4..84deb4e6b5 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -476,7 +476,7 @@ Windmill Community Edition {GIT_VERSION} #[cfg(feature = "tantivy")] let (index_reader, index_writer) = if should_index_jobs { - let (r, w) = windmill_indexer::indexer_ee::init_index().await?; + let (r, w) = windmill_indexer::indexer_ee::init_index(&db).await?; (Some(r), Some(w)) } else { (None, None) diff --git a/backend/tests/worker.rs b/backend/tests/worker.rs index ab008ae4c9..a93c6eef1d 100644 --- a/backend/tests/worker.rs +++ b/backend/tests/worker.rs @@ -2745,7 +2745,7 @@ async fn test_flow_lock_all(db: Pool) { "lock": null, "path": null, "type": "rawscript", - "content": "import * as wmill from \"https://deno.land/x/windmill@v1.50.0/mod.ts\"\n\nexport async function main() {\n return \"Hello\"\n}\n", + "content": "import * as wmill from \"https://deno.land/x/windmill@v1.50.0/mod.ts\"\n\nexport async function main() {\n return wmill\n}\n", "language": "deno", "input_transforms": {} }, diff --git a/backend/windmill-api/openapi-deref.json b/backend/windmill-api/openapi-deref.json index 23e8f019df..db789c2163 100644 --- a/backend/windmill-api/openapi-deref.json +++ b/backend/windmill-api/openapi-deref.json @@ -1,7 +1,7 @@ { "openapi": "3.0.3", "info": { - "version": "1.304.2", + "version": "1.409.0", "title": "Windmill API", "contact": { "name": "Windmill Team", @@ -176,6 +176,22 @@ { "$ref": "#/components/parameters/Operation" }, + { + "name": "operations", + "in": "query", + "description": "comma separated list of exact operations to include", + "schema": { + "type": "string" + } + }, + { + "name": "exclude_operations", + "in": "query", + "description": "comma separated list of operations to exclude", + "schema": { + "type": "string" + } + }, { "$ref": "#/components/parameters/ResourceName" }, @@ -501,6 +517,9 @@ "properties": { "is_super_admin": { "type": "boolean" + }, + "name": { + "type": "string" } } } @@ -660,6 +679,65 @@ } } }, + "/users/overwrite": { + "post": { + "summary": "global overwrite users (require super admin and EE)", + "operationId": "globalUsersOverwrite", + "tags": [ + "user" + ], + "requestBody": { + "description": "List of users", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExportedUser" + } + } + } + } + }, + "responses": { + "200": { + "description": "Success message", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/users/export": { + "get": { + "summary": "global export users (require super admin and EE)", + "operationId": "globalUsersExport", + "tags": [ + "user" + ], + "responses": { + "200": { + "description": "exported users", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExportedUser" + } + } + } + } + } + } + } + }, "/w/{workspace}/users/delete/{username}": { "delete": { "summary": "delete user (require admin privilege)", @@ -1061,6 +1139,49 @@ } } }, + "/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", @@ -1155,6 +1276,103 @@ } } }, + "/settings/latest_key_renewal_attempt": { + "get": { + "summary": "get latest key renewal attempt", + "operationId": "getLatestKeyRenewalAttempt", + "tags": [ + "setting" + ], + "responses": { + "200": { + "description": "status", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "string" + }, + "attempted_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "result", + "attempted_at" + ], + "nullable": true + } + } + } + } + } + } + }, + "/settings/renew_license_key": { + "post": { + "summary": "renew license key", + "operationId": "renewLicenseKey", + "tags": [ + "setting" + ], + "parameters": [ + { + "name": "license_key", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "status", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/settings/customer_portal": { + "post": { + "summary": "create customer portal session", + "operationId": "createCustomerPortalSession", + "tags": [ + "setting" + ], + "parameters": [ + { + "name": "license_key", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "url to portal", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/saml/test_metadata": { "post": { "summary": "test metadata", @@ -1187,6 +1405,30 @@ } } }, + "/settings/list_global": { + "get": { + "summary": "list global settings", + "operationId": "listGlobalSettings", + "tags": [ + "setting" + ], + "responses": { + "200": { + "description": "list of settings", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GlobalSetting" + } + } + } + } + } + } + } + }, "/users/email": { "get": { "summary": "get current user email (if logged in)", @@ -2122,6 +2364,9 @@ "git_sync": { "$ref": "#/components/schemas/WorkspaceGitSyncSettings" }, + "deploy_ui": { + "$ref": "#/components/schemas/WorkspaceDeployUISettings" + }, "default_app": { "type": "string" }, @@ -2730,6 +2975,46 @@ } } }, + "/w/{workspace}/workspaces/edit_deploy_ui_config": { + "post": { + "summary": "edit workspace deploy ui settings", + "operationId": "editWorkspaceDeployUISettings", + "tags": [ + "workspace" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + } + ], + "requestBody": { + "description": "Workspace deploy UI settings", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "deploy_ui_settings": { + "$ref": "#/components/schemas/WorkspaceDeployUISettings" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "status", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, "/w/{workspace}/workspaces/edit_default_app": { "post": { "summary": "edit default app for workspace", @@ -2934,6 +3219,9 @@ "properties": { "new_key": { "type": "string" + }, + "skip_reencrypt": { + "type": "boolean" } }, "required": [ @@ -3127,6 +3415,40 @@ } } }, + "/w/{workspace}/users/username_to_email/{username}": { + "get": { + "summary": "get email from username", + "operationId": "usernameToEmail", + "tags": [ + "user" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "username", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "email", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/users/tokens/create": { "post": { "summary": "create token", @@ -3236,6 +3558,12 @@ "schema": { "type": "boolean" } + }, + { + "$ref": "#/components/parameters/Page" + }, + { + "$ref": "#/components/parameters/PerPage" } ], "responses": { @@ -3559,6 +3887,19 @@ "parameters": [ { "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "path_start", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/Page" + }, + { + "$ref": "#/components/parameters/PerPage" } ], "responses": { @@ -3710,6 +4051,50 @@ } } }, + "/oauth/connect_slack_callback": { + "post": { + "summary": "connect slack callback instance", + "operationId": "connectSlackCallbackInstance", + "tags": [ + "oauth" + ], + "requestBody": { + "description": "code endpoint", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "state": { + "type": "string" + } + }, + "required": [ + "code", + "state" + ] + } + } + } + }, + "responses": { + "200": { + "description": "success message", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/oauth/connect_callback/{client_name}": { "post": { "summary": "connect callback", @@ -3932,7 +4317,18 @@ "oauth": { "type": "array", "items": { - "type": "string" + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "display_name": { + "type": "string" + } + }, + "required": [ + "type" + ] } }, "saml": { @@ -3962,19 +4358,50 @@ "content": { "application/json": { "schema": { - "additionalProperties": { - "type": "object", - "properties": { - "extra_params": { - "additionalProperties": { - "type": "string" - } - }, - "scopes": { - "type": "array", - "items": { - "type": "string" - } + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "/oauth/get_connect/{client}": { + "get": { + "summary": "get oauth connect", + "operationId": "getOAuthConnect", + "tags": [ + "oauth" + ], + "parameters": [ + { + "name": "client", + "description": "client name", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "get", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "extra_params": { + "type": "object" + }, + "scopes": { + "type": "array", + "items": { + "type": "string" } } } @@ -4294,6 +4721,13 @@ "schema": { "type": "string" } + }, + { + "name": "path_start", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -4433,6 +4867,30 @@ } } }, + "/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", @@ -5281,7 +5739,23 @@ }, { "name": "show_archived", - "description": "(default false)\nshow also the archived files.\nwhen multiple archived hash share the same path, only the ones with the latest create_at\nare \ned.\n", + "description": "(default false)\nshow only the archived files.\nwhen multiple archived hash share the same path, only the ones with the latest create_at\nare \ned.\n", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "include_without_main", + "description": "(default false)\ninclude scripts without an exported main function\n", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "include_draft_only", + "description": "(default false)\ninclude scripts that have no deployed version\n", "in": "query", "schema": { "type": "boolean" @@ -5310,6 +5784,14 @@ "schema": { "type": "boolean" } + }, + { + "name": "with_deployment_msg", + "description": "(default false)\ninclude deployment message\n", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -5735,6 +6217,13 @@ }, { "$ref": "#/components/parameters/ScriptPath" + }, + { + "name": "with_starred_info", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -5751,6 +6240,67 @@ } } }, + "/w/{workspace}/scripts/get_triggers_count/{path}": { + "get": { + "summary": "get triggers count of script", + "operationId": "getTriggersCountOfScript", + "tags": [ + "script" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "responses": { + "200": { + "description": "triggers count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TriggersCount" + } + } + } + } + } + } + }, + "/w/{workspace}/scripts/list_tokens/{path}": { + "get": { + "summary": "get tokens with script scope", + "operationId": "listTokensOfScript", + "tags": [ + "script" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "responses": { + "200": { + "description": "tokens list", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TruncatedToken" + } + } + } + } + } + } + } + }, "/w/{workspace}/scripts/get/draft/{path}": { "get": { "summary": "get script by path with draft", @@ -5963,6 +6513,13 @@ }, { "$ref": "#/components/parameters/ScriptHash" + }, + { + "name": "with_starred_info", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -6076,6 +6633,14 @@ "type": "integer" } }, + { + "name": "skip_preprocessor", + "description": "skip the preprocessor", + "in": "query", + "schema": { + "type": "boolean" + } + }, { "$ref": "#/components/parameters/ParentJob" }, @@ -6518,7 +7083,7 @@ }, { "name": "show_archived", - "description": "(default false)\nshow also the archived files.\nwhen multiple archived hash share the same path, only the ones with the latest create_at\nare displayed.\n", + "description": "(default false)\nshow only the archived files.\nwhen multiple archived hash share the same path, only the ones with the latest create_at\nare displayed.\n", "in": "query", "schema": { "type": "boolean" @@ -6531,6 +7096,22 @@ "schema": { "type": "boolean" } + }, + { + "name": "include_draft_only", + "description": "(default false)\ninclude items that have no deployed version\n", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "with_deployment_msg", + "description": "(default false)\ninclude deployment message\n", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -6565,6 +7146,133 @@ } } }, + "/w/{workspace}/flows/history/p/{path}": { + "get": { + "summary": "get flow history by path", + "operationId": "getFlowHistory", + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "tags": [ + "flow" + ], + "responses": { + "200": { + "description": "Flow history", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FlowVersion" + } + } + } + } + } + } + } + }, + "/w/{workspace}/flows/get/v/{version}/p/{path}": { + "get": { + "summary": "get flow version", + "operationId": "getFlowVersion", + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "type": "string", + "name": "version", + "in": "path", + "required": true, + "schema": { + "type": "number" + } + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "tags": [ + "flow" + ], + "responses": { + "200": { + "description": "flow details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Flow" + } + } + } + } + } + } + }, + "/w/{workspace}/flows/history_update/v/{version}/p/{path}": { + "post": { + "summary": "update flow history", + "operationId": "updateFlowHistory", + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "type": "string", + "name": "version", + "in": "path", + "required": true, + "schema": { + "type": "number" + } + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "requestBody": { + "description": "Flow deployment message", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "deployment_msg": { + "type": "string" + } + }, + "required": [ + "deployment_msg" + ] + } + } + } + }, + "tags": [ + "flow" + ], + "responses": { + "200": { + "description": "success", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/w/{workspace}/flows/get/{path}": { "get": { "summary": "get flow by path", @@ -6578,6 +7286,13 @@ }, { "$ref": "#/components/parameters/ScriptPath" + }, + { + "name": "with_starred_info", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -6594,6 +7309,67 @@ } } }, + "/w/{workspace}/flows/get_triggers_count/{path}": { + "get": { + "summary": "get triggers count of flow", + "operationId": "getTriggersCountOfFlow", + "tags": [ + "flow" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "responses": { + "200": { + "description": "triggers count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TriggersCount" + } + } + } + } + } + } + }, + "/w/{workspace}/flows/list_tokens/{path}": { + "get": { + "summary": "get tokens with flow scope", + "operationId": "listTokensOfFlow", + "tags": [ + "flow" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/ScriptPath" + } + ], + "responses": { + "200": { + "description": "tokens list", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TruncatedToken" + } + } + } + } + } + } + } + }, "/w/{workspace}/flows/toggle_workspace_error_handler/{path}": { "post": { "summary": "Toggle ON and OFF the workspace error handler for a given flow", @@ -6887,44 +7663,6 @@ } } }, - "/w/{workspace}/flows/input_history/p/{path}": { - "get": { - "summary": "list inputs for previous completed flow jobs", - "operationId": "getFlowInputHistoryByPath", - "tags": [ - "flow" - ], - "parameters": [ - { - "$ref": "#/components/parameters/WorkspaceId" - }, - { - "$ref": "#/components/parameters/ScriptPath" - }, - { - "$ref": "#/components/parameters/Page" - }, - { - "$ref": "#/components/parameters/PerPage" - } - ], - "responses": { - "200": { - "description": "input history for completed jobs with this flow path", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Input" - } - } - } - } - } - } - } - }, "/w/{workspace}/raw_apps/list": { "get": { "summary": "list all raw apps", @@ -7136,6 +7874,22 @@ "schema": { "type": "boolean" } + }, + { + "name": "include_draft_only", + "description": "(default false)\ninclude items that have no deployed version\n", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "with_deployment_msg", + "description": "(default false)\ninclude deployment message\n", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -7258,6 +8012,13 @@ }, { "$ref": "#/components/parameters/ScriptPath" + }, + { + "name": "with_starred_info", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -7756,6 +8517,9 @@ "path": { "type": "string" }, + "lock": { + "type": "string" + }, "cache_ttl": { "type": "integer" } @@ -7767,6 +8531,15 @@ }, "force_viewer_static_fields": { "type": "object" + }, + "force_viewer_one_of_fields": { + "type": "object" + }, + "force_viewer_allow_user_resources": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -7822,6 +8595,14 @@ "type": "integer" } }, + { + "name": "skip_preprocessor", + "description": "skip the preprocessor", + "in": "query", + "schema": { + "type": "boolean" + } + }, { "$ref": "#/components/parameters/ParentJob" }, @@ -7996,6 +8777,14 @@ "type": "integer" } }, + { + "name": "skip_preprocessor", + "description": "skip the preprocessor", + "in": "query", + "schema": { + "type": "boolean" + } + }, { "$ref": "#/components/parameters/ParentJob" }, @@ -8339,6 +9128,14 @@ "schema": { "type": "boolean" } + }, + { + "name": "is_not_schedule", + "description": "is not a scheduled job", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -8388,6 +9185,9 @@ "properties": { "database_length": { "type": "integer" + }, + "suspended": { + "type": "integer" } }, "required": [ @@ -8434,10 +9234,120 @@ } } }, - "/w/{workspace}/jobs/queue/cancel_all": { + "/w/{workspace}/jobs/queue/list_filtered_uuids": { + "get": { + "summary": "get the ids of all jobs matching the given filters", + "operationId": "listFilteredUuids", + "tags": [ + "job" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/OrderDesc" + }, + { + "$ref": "#/components/parameters/CreatedBy" + }, + { + "$ref": "#/components/parameters/ParentJob" + }, + { + "$ref": "#/components/parameters/ScriptExactPath" + }, + { + "$ref": "#/components/parameters/ScriptStartPath" + }, + { + "$ref": "#/components/parameters/SchedulePath" + }, + { + "$ref": "#/components/parameters/ScriptExactHash" + }, + { + "$ref": "#/components/parameters/StartedBefore" + }, + { + "$ref": "#/components/parameters/StartedAfter" + }, + { + "$ref": "#/components/parameters/Success" + }, + { + "$ref": "#/components/parameters/ScheduledForBeforeNow" + }, + { + "$ref": "#/components/parameters/JobKinds" + }, + { + "$ref": "#/components/parameters/Suspended" + }, + { + "$ref": "#/components/parameters/Running" + }, + { + "$ref": "#/components/parameters/ArgsFilter" + }, + { + "$ref": "#/components/parameters/ResultFilter" + }, + { + "$ref": "#/components/parameters/Tag" + }, + { + "$ref": "#/components/parameters/Page" + }, + { + "$ref": "#/components/parameters/PerPage" + }, + { + "name": "concurrency_key", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "all_workspaces", + "description": "get jobs from all workspaces (only valid if request come from the `admins` workspace)", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "is_not_schedule", + "description": "is not a scheduled job", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "uuids of jobs", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "/w/{workspace}/jobs/queue/cancel_selection": { "post": { - "summary": "cancel all jobs", - "operationId": "cancelAll", + "summary": "cancel jobs based on the given uuids", + "operationId": "cancelSelection", "tags": [ "job" ], @@ -8446,6 +9356,20 @@ "$ref": "#/components/parameters/WorkspaceId" } ], + "requestBody": { + "description": "uuids of the jobs to cancel", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, "responses": { "200": { "description": "uuids of canceled jobs", @@ -8480,6 +9404,9 @@ { "$ref": "#/components/parameters/CreatedBy" }, + { + "$ref": "#/components/parameters/Label" + }, { "$ref": "#/components/parameters/ParentJob" }, @@ -8545,6 +9472,14 @@ "schema": { "type": "boolean" } + }, + { + "name": "is_not_schedule", + "description": "is not a scheduled job", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -8578,6 +9513,9 @@ { "$ref": "#/components/parameters/CreatedBy" }, + { + "$ref": "#/components/parameters/Label" + }, { "$ref": "#/components/parameters/ParentJob" }, @@ -8599,6 +9537,12 @@ { "$ref": "#/components/parameters/StartedAfter" }, + { + "$ref": "#/components/parameters/CreatedBefore" + }, + { + "$ref": "#/components/parameters/CreatedAfter" + }, { "$ref": "#/components/parameters/CreatedOrStartedBefore" }, @@ -8611,9 +9555,15 @@ { "$ref": "#/components/parameters/CreatedOrStartedAfter" }, + { + "$ref": "#/components/parameters/CreatedOrStartedAfterCompletedJob" + }, { "$ref": "#/components/parameters/JobKinds" }, + { + "$ref": "#/components/parameters/Suspended" + }, { "$ref": "#/components/parameters/ArgsFilter" }, @@ -8668,6 +9618,14 @@ "schema": { "type": "boolean" } + }, + { + "name": "is_not_schedule", + "description": "is not a scheduled job", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -8708,6 +9666,62 @@ } } }, + "/jobs/completed/count_by_tag": { + "get": { + "summary": "Count jobs by tag", + "operationId": "countJobsByTag", + "tags": [ + "job" + ], + "parameters": [ + { + "name": "horizon_secs", + "in": "query", + "description": "Past Time horizon in seconds (when to start the count = now - horizon) (default is 3600)", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "workspace_id", + "in": "query", + "description": "Specific workspace ID to filter results (optional)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Job counts by tag", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tag": { + "type": "string" + }, + "count": { + "type": "integer" + } + }, + "required": [ + "tag", + "count" + ] + } + } + } + } + } + } + } + }, "/w/{workspace}/jobs_u/get/{id}": { "get": { "summary": "get job", @@ -8802,6 +9816,33 @@ } } }, + "/w/{workspace}/jobs_u/get_args/{id}": { + "get": { + "summary": "get job args", + "operationId": "getJobArgs", + "tags": [ + "job" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/JobId" + } + ], + "responses": { + "200": { + "description": "job args", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, "/w/{workspace}/jobs_u/getupdate/{id}": { "get": { "summary": "get job updates", @@ -8829,6 +9870,13 @@ "schema": { "type": "integer" } + }, + { + "name": "get_progress", + "in": "query", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -8854,6 +9902,9 @@ "mem_peak": { "type": "integer" }, + "progress": { + "type": "integer" + }, "flow_status": { "$ref": "#/components/schemas/WorkflowStatusRecord" } @@ -8865,6 +9916,38 @@ } } }, + "/w/{workspace}/jobs_u/get_log_file/{path}": { + "get": { + "summary": "get log file from object store", + "operationId": "getLogFileFromStore", + "tags": [ + "job" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "path", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "job log", + "content": { + "text/plain": { + "type": "string" + } + } + } + } + } + }, "/w/{workspace}/jobs_u/get_flow_debug_info/{id}": { "get": { "summary": "get flow debug info", @@ -8934,6 +10017,34 @@ }, { "$ref": "#/components/parameters/JobId" + }, + { + "name": "suspended_job", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "resume_id", + "in": "query", + "schema": { + "type": "integer" + } + }, + { + "name": "secret", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "approver", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -9027,7 +10138,7 @@ }, "/w/{workspace}/jobs_u/queue/cancel/{id}": { "post": { - "summary": "cancel queued job", + "summary": "cancel queued or running job", "operationId": "cancelQueuedJob", "tags": [ "job" @@ -9982,6 +11093,13 @@ "schema": { "type": "boolean" } + }, + { + "name": "path_start", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -10060,7 +11178,8 @@ "type": "string", "enum": [ "error", - "recovery" + "recovery", + "success" ] }, "override_existing": { @@ -10097,6 +11216,311 @@ } } }, + "/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", @@ -10351,6 +11775,65 @@ } } }, + "/groups/export": { + "get": { + "summary": "export instance groups", + "operationId": "exportInstanceGroups", + "tags": [ + "group" + ], + "responses": { + "200": { + "description": "exported instance groups", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExportedInstanceGroup" + } + } + } + } + } + } + } + }, + "/groups/overwrite": { + "post": { + "summary": "overwrite instance groups", + "operationId": "overwriteInstanceGroups", + "tags": [ + "group" + ], + "requestBody": { + "description": "overwrite instance groups", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExportedInstanceGroup" + } + } + } + } + }, + "responses": { + "200": { + "description": "success message", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/w/{workspace}/groups/list": { "get": { "summary": "list groups", @@ -10759,6 +12242,9 @@ "name": { "type": "string" }, + "summary": { + "type": "string" + }, "owners": { "type": "array", "items": { @@ -10815,6 +12301,9 @@ "schema": { "type": "object", "properties": { + "summary": { + "type": "string" + }, "owners": { "type": "array", "items": { @@ -11131,6 +12620,57 @@ } } }, + "/workers/queue_metrics": { + "get": { + "summary": "get queue metrics", + "operationId": "getQueueMetrics", + "tags": [ + "worker" + ], + "responses": { + "200": { + "description": "metrics", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "values": { + "type": "array", + "items": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "created_at", + "value" + ] + } + } + }, + "required": [ + "id", + "values" + ] + } + } + } + } + } + } + } + }, "/configs/list_worker_groups": { "get": { "summary": "list worker groups", @@ -11248,6 +12788,30 @@ } } }, + "/configs/list": { + "get": { + "summary": "list configs", + "operationId": "listConfigs", + "tags": [ + "config" + ], + "responses": { + "200": { + "description": "list of configs", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Config" + } + } + } + } + } + } + } + }, "/w/{workspace}/acls/get/{kind}/{path}": { "get": { "summary": "get granular acls", @@ -11277,7 +12841,8 @@ "flow", "folder", "app", - "raw_app" + "raw_app", + "http_trigger" ] } } @@ -11328,7 +12893,8 @@ "flow", "folder", "app", - "raw_app" + "raw_app", + "http_trigger" ] } } @@ -11398,7 +12964,8 @@ "flow", "folder", "app", - "raw_app" + "raw_app", + "http_trigger" ] } } @@ -11633,6 +13200,52 @@ } } }, + "/w/{workspace}/inputs/{jobOrInputId}/args": { + "get": { + "summary": "Get args from history or saved input", + "operationId": "getArgsFromHistoryOrSavedInput", + "tags": [ + "input" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "jobOrInputId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "input", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "allow_large", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "args", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, "/w/{workspace}/inputs/list": { "get": { "summary": "List saved Inputs for a Runnable", @@ -12097,7 +13710,7 @@ }, "/w/{workspace}/job_helpers/test_connection": { "get": { - "summary": "Test connection to the workspace datasets storage", + "summary": "Test connection to the workspace object storage", "operationId": "datasetStorageTestConnection", "tags": [ "helpers" @@ -12105,6 +13718,13 @@ "parameters": [ { "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12121,7 +13741,7 @@ }, "/w/{workspace}/job_helpers/list_stored_files": { "get": { - "summary": "List the file keys available in the workspace files storage (S3)", + "summary": "List the file keys available in a workspace object storage", "operationId": "listStoredFiles", "tags": [ "helpers" @@ -12151,6 +13771,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12202,6 +13829,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12278,6 +13912,13 @@ "schema": { "type": "integer" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12349,6 +13990,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12363,6 +14011,144 @@ } } }, + "/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", + "operationId": "loadCsvPreview", + "tags": [ + "helpers" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/Path" + }, + { + "name": "offset", + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "sort_col", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "sort_desc", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "search_col", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "search_term", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "csv_separator", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Csv Preview", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, "/w/{workspace}/job_helpers/delete_s3_file": { "delete": { "summary": "Permanently delete file from S3", @@ -12381,6 +14167,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12421,6 +14214,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12477,6 +14277,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "requestBody": { @@ -12547,6 +14354,13 @@ "schema": { "type": "string" } + }, + { + "name": "storage", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -12564,6 +14378,56 @@ } } }, + "/w/{workspace}/job_helpers/download_s3_parquet_file_as_csv": { + "get": { + "summary": "Download file to S3 bucket", + "operationId": "fileDownloadParquetAsCsv", + "tags": [ + "helpers" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "file_key", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "s3_resource_path", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "resource_type", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The downloaded file", + "content": { + "text/csv": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/w/{workspace}/job_metrics/get/{id}": { "post": { "summary": "get job metrics", @@ -12637,6 +14501,182 @@ } } }, + "/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", + "operationId": "listLogFiles", + "tags": [ + "service_logs" + ], + "parameters": [ + { + "$ref": "#/components/parameters/Before" + }, + { + "$ref": "#/components/parameters/After" + }, + { + "name": "with_error", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "time", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "hostname": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "worker_group": { + "type": "string" + }, + "log_ts": { + "type": "string", + "format": "date-time" + }, + "file_path": { + "type": "string" + }, + "ok_lines": { + "type": "integer" + }, + "err_lines": { + "type": "integer" + }, + "json_fmt": { + "type": "boolean" + } + }, + "required": [ + "hostname", + "mode", + "log_ts", + "file_path", + "json_fmt" + ] + } + } + } + } + } + } + } + }, + "/service_logs/get_log_file/{path}": { + "get": { + "summary": "get log file by path", + "operationId": "getLogFile", + "tags": [ + "service_logs" + ], + "parameters": [ + { + "$ref": "#/components/parameters/Path" + } + ], + "responses": { + "200": { + "description": "log stream", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, "/concurrency_groups/list": { "get": { "summary": "List all concurrency groups", @@ -12661,7 +14701,7 @@ } } }, - "/concurrency_groups/{concurrency_id}": { + "/concurrency_groups/prune/{concurrency_id}": { "delete": { "summary": "Delete concurrency group", "operationId": "deleteConcurrencyGroup", @@ -12687,6 +14727,238 @@ } } } + }, + "/concurrency_groups/{id}/key": { + "get": { + "summary": "Get the concurrency key for a job that has concurrency limits enabled", + "operationId": "getConcurrencyKey", + "tags": [ + "concurrencyGroups" + ], + "parameters": [ + { + "$ref": "#/components/parameters/JobId" + } + ], + "responses": { + "200": { + "description": "concurrency key for given job", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/w/{workspace}/concurrency_groups/list_jobs": { + "get": { + "summary": "Get intervals of job runtime concurrency", + "operationId": "listExtendedJobs", + "tags": [ + "concurrencyGroups", + "job" + ], + "parameters": [ + { + "name": "concurrency_key", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "row_limit", + "in": "query", + "required": false, + "schema": { + "type": "number" + } + }, + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "$ref": "#/components/parameters/CreatedBy" + }, + { + "$ref": "#/components/parameters/Label" + }, + { + "$ref": "#/components/parameters/ParentJob" + }, + { + "$ref": "#/components/parameters/ScriptExactPath" + }, + { + "$ref": "#/components/parameters/ScriptStartPath" + }, + { + "$ref": "#/components/parameters/SchedulePath" + }, + { + "$ref": "#/components/parameters/ScriptExactHash" + }, + { + "$ref": "#/components/parameters/StartedBefore" + }, + { + "$ref": "#/components/parameters/StartedAfter" + }, + { + "$ref": "#/components/parameters/CreatedOrStartedBefore" + }, + { + "$ref": "#/components/parameters/Running" + }, + { + "$ref": "#/components/parameters/ScheduledForBeforeNow" + }, + { + "$ref": "#/components/parameters/CreatedOrStartedAfter" + }, + { + "$ref": "#/components/parameters/CreatedOrStartedAfterCompletedJob" + }, + { + "$ref": "#/components/parameters/JobKinds" + }, + { + "$ref": "#/components/parameters/ArgsFilter" + }, + { + "$ref": "#/components/parameters/Tag" + }, + { + "$ref": "#/components/parameters/ResultFilter" + }, + { + "$ref": "#/components/parameters/Page" + }, + { + "$ref": "#/components/parameters/PerPage" + }, + { + "name": "is_skipped", + "description": "is the job skipped", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "is_flow_step", + "description": "is the job a flow step", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "has_null_parent", + "description": "has null parent", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "success", + "description": "filter on successful jobs", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "all_workspaces", + "description": "get jobs from all workspaces (only valid if request come from the `admins` workspace)", + "in": "query", + "schema": { + "type": "boolean" + } + }, + { + "name": "is_not_schedule", + "description": "is not a scheduled job", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "time", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExtendedJobs" + } + } + } + } + } + } + }, + "/srch/w/{workspace}/index/search/job": { + "get": { + "summary": "Search through jobs with a string query", + "operationId": "searchJobsIndex", + "tags": [ + "indexSearch" + ], + "parameters": [ + { + "$ref": "#/components/parameters/WorkspaceId" + }, + { + "name": "search_query", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "search results", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "query_parse_errors": { + "description": "a list of the terms that couldn't be parsed (and thus ignored)", + "type": "array", + "items": { + "type": "object", + "properties": { + "dancer": { + "type": "string" + } + } + } + }, + "hits": { + "description": "the jobs that matched the query", + "type": "array", + "items": { + "$ref": "#/components/schemas/JobSearchHit" + } + } + } + } + } + } + } + } + } } }, "components": { @@ -12839,6 +15111,14 @@ "type": "string" } }, + "Label": { + "name": "label", + "description": "mask to filter exact matching job's label (job labels are completed jobs with as a result an object containing a string in the array at key 'wm_labels')", + "in": "query", + "schema": { + "type": "string" + } + }, "ParentJob": { "name": "parent_job", "description": "The parent job that is at the origin and responsible for the execution of this script if any", @@ -12929,6 +15209,24 @@ "type": "string" } }, + "CreatedBefore": { + "name": "created_before", + "description": "filter on created before (inclusive) timestamp", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + "CreatedAfter": { + "name": "created_after", + "description": "filter on created after (exclusive) timestamp", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, "StartedBefore": { "name": "started_before", "description": "filter on started before (inclusive) timestamp", @@ -12947,6 +15245,15 @@ "format": "date-time" } }, + "Before": { + "name": "before", + "description": "filter on started before (inclusive) timestamp", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, "CreatedOrStartedAfter": { "name": "created_or_started_after", "description": "filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp", @@ -12956,6 +15263,15 @@ "format": "date-time" } }, + "CreatedOrStartedAfterCompletedJob": { + "name": "created_or_started_after_completed_jobs", + "description": "filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp but only for the completed jobs", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, "CreatedOrStartedBefore": { "name": "created_or_started_before", "description": "filter on created_at for non non started job and started_at otherwise before (inclusive) timestamp", @@ -13030,15 +15346,6 @@ "format": "date-time" } }, - "Before": { - "name": "before", - "description": "filter on created before (exclusive) timestamp", - "in": "query", - "schema": { - "type": "string", - "format": "date-time" - } - }, "Username": { "name": "username", "description": "filter on exact username of user", @@ -13198,7 +15505,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] }, "kind": { @@ -13235,6 +15545,9 @@ "concurrency_time_window_s": { "type": "integer" }, + "concurrency_key": { + "type": "string" + }, "cache_ttl": { "type": "number" }, @@ -13258,6 +15571,15 @@ }, "visible_to_runner_only": { "type": "boolean" + }, + "no_main_func": { + "type": "boolean" + }, + "codebase": { + "type": "string" + }, + "has_preprocessor": { + "type": "boolean" } }, "required": [ @@ -13274,7 +15596,9 @@ "extra_perms", "language", "kind", - "starred" + "starred", + "no_main_func", + "has_preprocessor" ] }, "NewScript": { @@ -13319,7 +15643,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] }, "kind": { @@ -13379,6 +15706,15 @@ }, "visible_to_runner_only": { "type": "boolean" + }, + "no_main_func": { + "type": "boolean" + }, + "codebase": { + "type": "string" + }, + "has_preprocessor": { + "type": "boolean" } }, "required": [ @@ -13437,9 +15773,6 @@ "name": { "type": "string" }, - "args": { - "type": "object" - }, "created_by": { "type": "string" }, @@ -13613,7 +15946,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] }, "email": { @@ -13630,6 +15966,15 @@ }, "priority": { "type": "integer" + }, + "self_wait_time_ms": { + "type": "number" + }, + "aggregate_wait_time_ms": { + "type": "number" + }, + "suspend": { + "type": "number" } }, "required": [ @@ -13750,7 +16095,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] }, "is_skipped": { @@ -13770,6 +16118,18 @@ }, "priority": { "type": "integer" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, + "self_wait_time_ms": { + "type": "number" + }, + "aggregate_wait_time_ms": { + "type": "number" } }, "required": [ @@ -13789,29 +16149,58 @@ "tag" ] }, + "ObscuredJob": { + "type": "object", + "properties": { + "typ": { + "type": "string" + }, + "started_at": { + "type": "string", + "format": "date-time" + }, + "duration_ms": { + "type": "number" + } + } + }, "Job": { - "allOf": [ + "oneOf": [ { - "oneOf": [ + "allOf": [ { "$ref": "#/components/schemas/CompletedJob" }, { - "$ref": "#/components/schemas/QueuedJob" + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "CompletedJob" + ] + } + } } ] }, { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "CompletedJob", - "QueuedJob" - ] + "allOf": [ + { + "$ref": "#/components/schemas/QueuedJob" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "QueuedJob" + ] + } + } } - } + ] } ], "discriminator": { @@ -13940,6 +16329,9 @@ "items": { "type": "string" } + }, + "email": { + "type": "string" } }, "required": [ @@ -13963,6 +16355,9 @@ "items": { "type": "string" } + }, + "workspace_id": { + "type": "string" } } }, @@ -13978,6 +16373,9 @@ }, "impersonate_email": { "type": "string" + }, + "workspace_id": { + "type": "string" } }, "required": [ @@ -14025,6 +16423,10 @@ }, "is_refreshed": { "type": "boolean" + }, + "expires_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14077,6 +16479,10 @@ }, "is_oauth": { "type": "boolean" + }, + "expires_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14396,6 +16802,14 @@ "typ" ] } + }, + "no_main_func": { + "type": "boolean", + "nullable": true + }, + "has_preprocessor": { + "type": "boolean", + "nullable": true } }, "required": [ @@ -14403,7 +16817,9 @@ "start_kwargs", "args", "type", - "error" + "error", + "no_main_func", + "has_preprocessor" ] }, "Preview": { @@ -14433,7 +16849,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] }, "tag": { @@ -14550,6 +16969,13 @@ "additionalProperties": { "type": "boolean" } + }, + "created_by": { + "type": "string" + }, + "edited_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14597,6 +17023,13 @@ }, "account": { "type": "number" + }, + "created_by": { + "type": "string" + }, + "edited_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14619,6 +17052,16 @@ "schema": {}, "description": { "type": "string" + }, + "created_by": { + "type": "string" + }, + "edited_at": { + "type": "string", + "format": "date-time" + }, + "format_extension": { + "type": "string" } }, "required": [ @@ -14698,6 +17141,12 @@ "on_recovery_extra_args": { "$ref": "#/components/schemas/ScriptArgs" }, + "on_success": { + "type": "string" + }, + "on_success_extra_args": { + "$ref": "#/components/schemas/ScriptArgs" + }, "ws_error_handler_muted": { "type": "boolean" }, @@ -14712,6 +17161,10 @@ }, "tag": { "type": "string" + }, + "paused_until": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14806,6 +17259,12 @@ "on_recovery_extra_args": { "$ref": "#/components/schemas/ScriptArgs" }, + "on_success": { + "type": "string" + }, + "on_success_extra_args": { + "$ref": "#/components/schemas/ScriptArgs" + }, "ws_error_handler_muted": { "type": "boolean" }, @@ -14820,6 +17279,10 @@ }, "tag": { "type": "string" + }, + "paused_until": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14864,6 +17327,12 @@ "on_recovery_extra_args": { "$ref": "#/components/schemas/ScriptArgs" }, + "on_success": { + "type": "string" + }, + "on_success_extra_args": { + "$ref": "#/components/schemas/ScriptArgs" + }, "ws_error_handler_muted": { "type": "boolean" }, @@ -14878,6 +17347,10 @@ }, "tag": { "type": "string" + }, + "paused_until": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14888,6 +17361,181 @@ "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" + ] + }, + "TriggersCount": { + "type": "object", + "properties": { + "primary_schedule": { + "type": "object", + "properties": { + "schedule": { + "type": "string" + } + } + }, + "schedule_count": { + "type": "number" + }, + "http_routes_count": { + "type": "number" + }, + "webhook_count": { + "type": "number" + }, + "email_count": { + "type": "number" + } + } + }, "Group": { "type": "object", "properties": { @@ -14951,6 +17599,16 @@ "additionalProperties": { "type": "boolean" } + }, + "summary": { + "type": "string" + }, + "created_by": { + "type": "string" + }, + "edited_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -14992,6 +17650,36 @@ }, "wm_version": { "type": "string" + }, + "last_job_id": { + "type": "string" + }, + "last_job_workspace_id": { + "type": "string" + }, + "occupancy_rate": { + "type": "number" + }, + "occupancy_rate_15s": { + "type": "number" + }, + "occupancy_rate_5m": { + "type": "number" + }, + "occupancy_rate_30m": { + "type": "number" + }, + "memory": { + "type": "number" + }, + "vcpus": { + "type": "number" + }, + "memory_usage": { + "type": "number" + }, + "wm_memory_usage": { + "type": "number" } }, "required": [ @@ -15148,6 +17836,12 @@ } ] }, + "ExtraPerms": { + "type": "object", + "additionalProperties": { + "type": "boolean" + } + }, "FlowMetadata": { "type": "object", "properties": { @@ -15168,10 +17862,7 @@ "type": "boolean" }, "extra_perms": { - "type": "object" - }, - "additionalProperties": { - "type": "boolean" + "$ref": "#/components/schemas/ExtraPerms" }, "starred": { "type": "boolean" @@ -15291,6 +17982,12 @@ "type": "object" } }, + "triggerables_v2": { + "type": "object", + "additionalProperties": { + "type": "object" + } + }, "execution_mode": { "type": "string", "enum": [ @@ -15424,7 +18121,9 @@ "type": "string", "format": "date-time" }, - "value": {}, + "value": { + "type": "object" + }, "policy": { "$ref": "#/components/schemas/Policy" }, @@ -15487,6 +18186,25 @@ "version" ] }, + "FlowVersion": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "deployment_msg": { + "type": "string" + } + }, + "required": [ + "id", + "created_at" + ] + }, "SlackToken": { "type": "object", "properties": { @@ -15581,6 +18299,32 @@ }, "public_resource": { "type": "boolean" + }, + "secondary_storage": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "S3Storage", + "AzureBlobStorage", + "AzureWorkloadIdentity", + "S3AwsOidc" + ] + }, + "s3_resource_path": { + "type": "string" + }, + "azure_blob_resource_path": { + "type": "string" + }, + "public_resource": { + "type": "boolean" + } + } + } } } }, @@ -15709,6 +18453,31 @@ } } }, + "WorkspaceDeployUISettings": { + "type": "object", + "properties": { + "include_path": { + "type": "array", + "items": { + "type": "string" + } + }, + "include_type": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "script", + "flow", + "app", + "resource", + "variable", + "secret" + ] + } + } + } + }, "WorkspaceDefaultScripts": { "type": "object", "properties": { @@ -15873,7 +18642,10 @@ "mssql", "graphql", "nativets", - "bun" + "bun", + "php", + "rust", + "ansible" ] } }, @@ -15886,21 +18658,144 @@ "ConcurrencyGroup": { "type": "object", "properties": { - "concurrency_id": { + "concurrency_key": { "type": "string" }, - "job_uuids": { + "total_running": { + "type": "number" + } + }, + "required": [ + "concurrency_key", + "total_running" + ] + }, + "ExtendedJobs": { + "type": "object", + "properties": { + "jobs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Job" + } + }, + "obscured_jobs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ObscuredJob" + } + }, + "omitted_obscured_jobs": { + "description": "Obscured jobs omitted for security because of too specific filtering", + "type": "boolean" + } + }, + "required": [ + "jobs", + "obscured_jobs" + ] + }, + "ExportedUser": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password_hash": { + "type": "string" + }, + "super_admin": { + "type": "boolean" + }, + "verified": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "company": { + "type": "string" + }, + "first_time_user": { + "type": "boolean" + }, + "username": { + "type": "string" + } + }, + "required": [ + "email", + "super_admin", + "verified", + "first_time_user" + ] + }, + "GlobalSetting": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "object" + } + }, + "required": [ + "name", + "value" + ] + }, + "Config": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "config": { + "type": "object" + } + }, + "required": [ + "name" + ] + }, + "ExportedInstanceGroup": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "emails": { "type": "array", "items": { "type": "string" } + }, + "id": { + "type": "string" + }, + "scim_display_name": { + "type": "string" + }, + "external_id": { + "type": "string" } }, "required": [ - "concurrency_id", - "job_uuids" + "name" ] }, + "JobSearchHit": { + "type": "object", + "properties": { + "dancer": { + "type": "string" + } + } + }, "StaticTransform": { "type": "object", "properties": { @@ -15979,7 +18874,8 @@ "snowflake", "mssql", "graphql", - "nativets" + "nativets", + "php" ] }, "path": { @@ -16002,6 +18898,9 @@ }, "concurrency_time_window_s": { "type": "number" + }, + "custom_concurrency_key": { + "type": "string" } }, "required": [ @@ -16031,6 +18930,9 @@ "enum": [ "script" ] + }, + "tag_override": { + "type": "string" } }, "required": [ @@ -16087,6 +18989,31 @@ "expr" ] }, + "stop_after_all_iters_if": { + "type": "object", + "properties": { + "skip_if_stopped": { + "type": "boolean" + }, + "expr": { + "type": "string" + } + }, + "required": [ + "expr" + ] + }, + "skip_if": { + "type": "object", + "properties": { + "expr": { + "type": "string" + } + }, + "required": [ + "expr" + ] + }, "sleep": { "$ref": "#/components/schemas/InputTransform" }, @@ -16139,6 +19066,9 @@ }, "hide_cancel": { "type": "boolean" + }, + "continue_on_disapprove_timeout": { + "type": "boolean" } } }, @@ -16419,12 +19349,18 @@ "failure_module": { "$ref": "#/components/schemas/FlowModule" }, + "preprocessor_module": { + "$ref": "#/components/schemas/FlowModule" + }, "same_worker": { "type": "boolean" }, "concurrent_limit": { "type": "number" }, + "concurrency_key": { + "type": "string" + }, "concurrency_time_window_s": { "type": "number" }, @@ -16490,6 +19426,9 @@ "count": { "type": "integer" }, + "progress": { + "type": "integer" + }, "iterator": { "type": "object", "properties": { @@ -16509,6 +19448,12 @@ "type": "string" } }, + "flow_jobs_success": { + "type": "array", + "items": { + "type": "boolean" + } + }, "branch_chosen": { "type": "object", "properties": { @@ -16559,6 +19504,16 @@ "approver" ] } + }, + "failed_retries": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + }, + "skipped": { + "type": "boolean" } }, "required": [ @@ -16580,6 +19535,13 @@ "user_states": { "additionalProperties": true }, + "preprocessor_module": { + "allOf": [ + { + "$ref": "#/components/schemas/FlowStatusModule" + } + ] + }, "failure_module": { "allOf": [ { diff --git a/backend/windmill-api/openapi-deref.yaml b/backend/windmill-api/openapi-deref.yaml index 9654b10550..e2a0b00a85 100644 --- a/backend/windmill-api/openapi-deref.yaml +++ b/backend/windmill-api/openapi-deref.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: 1.269.0 + version: 1.409.0 title: Windmill API contact: name: Windmill Team @@ -87,7 +87,7 @@ paths: - name: id in: path required: true - schema: &ref_24 + schema: &ref_28 type: integer responses: '200': @@ -221,44 +221,54 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: &ref_3 + schema: &ref_5 type: integer - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: &ref_4 + schema: &ref_6 type: integer - name: before - description: filter on created before (exclusive) timestamp + description: filter on started before (inclusive) timestamp in: query - schema: &ref_102 + schema: &ref_109 type: string format: date-time - name: after description: filter on created after (exclusive) timestamp in: query - schema: &ref_101 + schema: &ref_110 type: string format: date-time - name: username description: filter on exact username of user in: query - schema: &ref_103 + schema: &ref_119 type: string - name: operation description: filter on exact or prefix name of operation in: query - schema: &ref_104 + schema: &ref_120 + type: string + - name: operations + in: query + description: comma separated list of exact operations to include + schema: + type: string + - name: exclude_operations + in: query + description: comma separated list of operations to exclude + schema: type: string - name: resource description: filter on exact or prefix name of resource in: query - schema: &ref_105 + schema: &ref_121 type: string - name: action_kind description: filter on type of operation in: query - schema: &ref_106 + schema: &ref_122 type: string enum: - Create @@ -290,12 +300,12 @@ paths: application/json: schema: type: object - properties: &ref_119 + properties: &ref_136 email: type: string password: type: string - required: &ref_120 + required: &ref_137 - email - password responses: @@ -332,10 +342,10 @@ paths: text/plain: schema: type: string - /w/{workspace}/users/add: - post: - summary: create user (require admin privilege) - operationId: createUser + /w/{workspace}/users/{username}: + get: + summary: get user (require admin privilege) + operationId: getUser tags: - user - admin @@ -344,31 +354,56 @@ paths: in: path required: true schema: *ref_0 - requestBody: - description: new user - required: true - content: - application/json: - schema: - type: object - properties: &ref_121 - email: - type: string - username: - type: string - is_admin: - type: boolean - required: &ref_122 - - email - - username - - is_admin + - name: username + in: path + required: true + schema: + type: string responses: - '201': + '200': description: user created content: - text/plain: + application/json: schema: - type: string + type: object + properties: &ref_10 + email: + type: string + username: + type: string + is_admin: + type: boolean + is_super_admin: + type: boolean + created_at: + type: string + format: date-time + operator: + type: boolean + disabled: + type: boolean + groups: + type: array + items: + type: string + folders: + type: array + items: + type: string + folders_owners: + type: array + items: + type: string + required: &ref_11 + - email + - username + - is_admin + - is_super_admin + - created_at + - operator + - disabled + - folders + - folders_owners /w/{workspace}/users/update/{username}: post: summary: update user (require admin privilege) @@ -393,7 +428,7 @@ paths: application/json: schema: type: object - properties: &ref_123 + properties: &ref_138 is_admin: type: boolean operator: @@ -421,7 +456,7 @@ paths: - name: path in: path required: true - schema: &ref_17 + schema: &ref_21 type: string responses: '200': @@ -512,6 +547,8 @@ paths: properties: is_super_admin: type: boolean + name: + type: string responses: '200': description: user updated @@ -519,6 +556,74 @@ paths: text/plain: schema: type: string + /users/username_info/{email}: + get: + summary: global username info (require super admin) + operationId: globalUsernameInfo + tags: + - user + parameters: + - name: email + in: path + required: true + schema: + type: string + responses: + '200': + description: user renamed + content: + application/json: + schema: + type: object + properties: + username: + type: string + workspace_usernames: + type: array + items: + type: object + properties: + workspace_id: + type: string + username: + type: string + required: + - workspace_id + - username + required: + - username + - workspace_usernames + /users/rename/{email}: + post: + summary: global rename user (require super admin) + operationId: globalUserRename + tags: + - user + parameters: + - name: email + in: path + required: true + schema: + type: string + requestBody: + description: new username + required: true + content: + application/json: + schema: + type: object + properties: + new_username: + type: string + required: + - new_username + responses: + '200': + description: user renamed + content: + text/plain: + schema: + type: string /users/delete/{email}: delete: summary: global delete user (require super admin) @@ -538,6 +643,67 @@ paths: text/plain: schema: type: string + /users/overwrite: + post: + summary: global overwrite users (require super admin and EE) + operationId: globalUsersOverwrite + tags: + - user + requestBody: + description: List of users + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_3 + email: + type: string + password_hash: + type: string + super_admin: + type: boolean + verified: + type: boolean + name: + type: string + company: + type: string + first_time_user: + type: boolean + username: + type: string + required: &ref_4 + - email + - super_admin + - verified + - first_time_user + responses: + '200': + description: Success message + content: + text/plain: + schema: + type: string + /users/export: + get: + summary: global export users (require super admin and EE) + operationId: globalUsersExport + tags: + - user + responses: + '200': + description: exported users + content: + application/json: + schema: + type: array + items: + type: object + properties: *ref_3 + required: *ref_4 /w/{workspace}/users/delete/{username}: delete: summary: delete user (require admin privilege) @@ -577,7 +743,7 @@ paths: type: array items: type: object - properties: &ref_5 + properties: &ref_7 id: type: string name: @@ -586,7 +752,7 @@ paths: type: string domain: type: string - required: &ref_6 + required: &ref_8 - id - name - owner @@ -616,7 +782,7 @@ paths: application/json: schema: type: object - properties: &ref_151 + properties: &ref_172 email: type: string workspaces: @@ -634,7 +800,7 @@ paths: - id - name - username - required: &ref_152 + required: &ref_173 - email - workspaces /workspaces/list_as_superadmin: @@ -647,11 +813,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: workspaces @@ -661,8 +827,8 @@ paths: type: array items: type: object - properties: *ref_5 - required: *ref_6 + properties: *ref_7 + required: *ref_8 /workspaces/create: post: summary: create workspace @@ -676,17 +842,16 @@ paths: application/json: schema: type: object - properties: &ref_153 + properties: &ref_174 id: type: string name: type: string username: type: string - required: &ref_154 + required: &ref_175 - id - name - - username responses: '201': description: token created @@ -756,7 +921,7 @@ paths: - name: key in: path required: true - schema: &ref_7 + schema: &ref_9 type: string responses: '200': @@ -773,7 +938,7 @@ paths: - name: key in: path required: true - schema: *ref_7 + schema: *ref_9 requestBody: description: value set required: true @@ -850,6 +1015,33 @@ paths: text/plain: 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 @@ -875,6 +1067,27 @@ paths: text/plain: schema: type: string + /settings/test_object_storage_config: + post: + summary: test object storage config + operationId: testObjectStorageConfig + tags: + - setting + requestBody: + description: test object storage config + required: true + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + '200': + description: status + content: + text/plain: + schema: + type: string /settings/send_stats: post: summary: send stats @@ -888,6 +1101,110 @@ paths: text/plain: schema: type: string + /settings/latest_key_renewal_attempt: + get: + summary: get latest key renewal attempt + operationId: getLatestKeyRenewalAttempt + tags: + - setting + responses: + '200': + description: status + content: + application/json: + schema: + type: object + properties: + result: + type: string + attempted_at: + type: string + format: date-time + required: + - result + - attempted_at + nullable: true + /settings/renew_license_key: + post: + summary: renew license key + operationId: renewLicenseKey + tags: + - setting + parameters: + - name: license_key + in: query + required: false + schema: + type: string + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + /settings/customer_portal: + post: + summary: create customer portal session + operationId: createCustomerPortalSession + tags: + - setting + parameters: + - name: license_key + in: query + required: false + schema: + type: string + responses: + '200': + description: url to portal + content: + text/plain: + schema: + type: string + /saml/test_metadata: + post: + summary: test metadata + operationId: testMetadata + tags: + - setting + requestBody: + description: test metadata + required: true + content: + application/json: + schema: + type: string + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + /settings/list_global: + get: + summary: list global settings + operationId: listGlobalSettings + tags: + - setting + responses: + '200': + description: list of settings + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_214 + name: + type: string + value: + type: object + required: &ref_215 + - name + - value /users/email: get: summary: get current user email (if logged in) @@ -1026,7 +1343,7 @@ paths: application/json: schema: type: object - properties: &ref_10 + properties: &ref_12 email: type: string login_type: @@ -1042,7 +1359,9 @@ paths: type: string company: type: string - required: &ref_11 + username: + type: string + required: &ref_13 - email - login_type - super_admin @@ -1062,7 +1381,7 @@ paths: type: array items: type: object - properties: &ref_12 + properties: &ref_14 workspace_id: type: string email: @@ -1071,7 +1390,7 @@ paths: type: boolean operator: type: boolean - required: &ref_13 + required: &ref_15 - workspace_id - email - is_admin @@ -1094,49 +1413,8 @@ paths: application/json: schema: type: object - properties: &ref_8 - email: - type: string - username: - type: string - is_admin: - type: boolean - is_super_admin: - type: boolean - created_at: - type: string - format: date-time - operator: - type: boolean - disabled: - type: boolean - groups: - type: array - items: - type: string - folders: - type: array - items: - type: string - folders_owners: - type: array - items: - type: string - usage: - type: object - properties: &ref_118 - executions: - type: number - required: &ref_9 - - email - - username - - is_admin - - is_super_admin - - created_at - - operator - - disabled - - folders - - folders_owners + properties: *ref_10 + required: *ref_11 /users/accept_invite: post: summary: accept invite to workspace @@ -1157,7 +1435,6 @@ paths: type: string required: - workspace_id - - username responses: '200': description: status @@ -1257,7 +1534,6 @@ paths: - email - is_admin - operator - - username responses: '200': description: status @@ -1373,6 +1649,82 @@ paths: text/plain: schema: type: string + /w/{workspace}/workspaces/get_workspace_name: + get: + summary: get workspace name + operationId: getWorkspaceName + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + /w/{workspace}/workspaces/change_workspace_name: + post: + summary: change workspace name + operationId: changeWorkspaceName + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + content: + application/json: + schema: + type: object + properties: + new_name: + type: string + required: + - username + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + /w/{workspace}/workspaces/change_workspace_id: + post: + summary: change workspace id + operationId: changeWorkspaceId + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + content: + application/json: + schema: + type: object + properties: + new_id: + type: string + new_name: + type: string + required: + - username + responses: + '200': + description: status + content: + text/plain: + schema: + type: string /w/{workspace}/users/whois/{username}: get: summary: whois @@ -1396,8 +1748,8 @@ paths: application/json: schema: type: object - properties: *ref_8 - required: *ref_9 + properties: *ref_10 + required: *ref_11 /users/exists/{email}: get: summary: exists email @@ -1427,11 +1779,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: user @@ -1441,8 +1793,8 @@ paths: type: array items: type: object - properties: *ref_10 - required: *ref_11 + properties: *ref_12 + required: *ref_13 /w/{workspace}/workspaces/list_pending_invites: get: summary: list pending invites for a workspace @@ -1463,8 +1815,8 @@ paths: type: array items: type: object - properties: *ref_12 - required: *ref_13 + properties: *ref_14 + required: *ref_15 /w/{workspace}/workspaces/get_settings: get: summary: get settings @@ -1500,6 +1852,8 @@ paths: type: boolean plan: type: string + automatic_billing: + type: boolean customer_id: type: string webhook: @@ -1514,26 +1868,46 @@ paths: type: string error_handler_extra_args: type: object - additionalProperties: &ref_14 {} + additionalProperties: &ref_16 {} error_handler_muted_on_cancel: type: boolean large_file_storage: type: object - properties: &ref_15 + properties: &ref_17 type: type: string enum: - S3Storage - AzureBlobStorage + - AzureWorkloadIdentity + - S3AwsOidc s3_resource_path: type: string azure_blob_resource_path: type: string public_resource: type: boolean + secondary_storage: + type: object + additionalProperties: + type: object + properties: + type: + type: string + enum: + - S3Storage + - AzureBlobStorage + - AzureWorkloadIdentity + - S3AwsOidc + s3_resource_path: + type: string + azure_blob_resource_path: + type: string + public_resource: + type: boolean git_sync: type: object - properties: &ref_16 + properties: &ref_18 include_path: type: array items: @@ -1552,24 +1926,78 @@ paths: - secret - resourcetype - schedule + - user + - group repositories: type: array items: type: object - properties: &ref_174 + properties: &ref_198 script_path: type: string git_repo_resource_path: type: string use_individual_branch: type: boolean - required: &ref_175 + group_by_folder: + type: boolean + exclude_types_override: + type: array + items: + type: string + enum: + - script + - flow + - app + - folder + - resource + - variable + - secret + - resourcetype + - schedule + - user + - group + required: &ref_199 - script_path - git_repo_resource_path + deploy_ui: + type: object + properties: &ref_19 + include_path: + type: array + items: + type: string + include_type: + type: array + items: + type: string + enum: + - script + - flow + - app + - resource + - variable + - secret default_app: type: string + default_scripts: + type: object + properties: &ref_20 + order: + type: array + items: + type: string + hidden: + type: array + items: + type: string + default_script_content: + additionalProperties: + type: string required: - code_completion_enabled + - automatic_billing + - error_handler_muted_on_cancel /w/{workspace}/workspaces/get_deploy_to: get: summary: get deploy to @@ -1634,8 +2062,43 @@ paths: type: number seats: type: number + automatic_billing: + type: boolean required: - premium + - automatic_billing + /w/{workspace}/workspaces/set_automatic_billing: + post: + summary: set automatic billing + operationId: setAutomaticBilling + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: automatic billing + required: true + content: + application/json: + schema: + type: object + properties: + automatic_billing: + type: boolean + seats: + type: number + required: + - automatic_billing + responses: + '200': + description: status + content: + text/plain: + schema: + type: string /w/{workspace}/workspaces/edit_slack_command: post: summary: edit slack command @@ -1867,7 +2330,7 @@ paths: type: string error_handler_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 error_handler_muted_on_cancel: type: boolean responses: @@ -1898,7 +2361,7 @@ paths: properties: large_file_storage: type: object - properties: *ref_15 + properties: *ref_17 responses: '200': description: status @@ -1926,7 +2389,35 @@ paths: properties: git_sync_settings: type: object - properties: *ref_16 + properties: *ref_18 + responses: + '200': + description: status + content: + application/json: + schema: {} + /w/{workspace}/workspaces/edit_deploy_ui_config: + post: + summary: edit workspace deploy ui settings + operationId: editWorkspaceDeployUISettings + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: Workspace deploy UI settings + required: true + content: + application/json: + schema: + type: object + properties: + deploy_ui_settings: + type: object + properties: *ref_19 responses: '200': description: status @@ -1961,6 +2452,81 @@ paths: text/plain: schema: type: string + /w/{workspace}/workspaces/default_scripts: + post: + summary: edit default scripts for workspace + operationId: editDefaultScripts + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: Workspace default app + content: + application/json: + schema: + type: object + properties: *ref_20 + responses: + '200': + description: status + content: + text/plain: + schema: + type: string + get: + summary: get default scripts for workspace + operationId: get default scripts + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: status + content: + application/json: + schema: + type: object + properties: *ref_20 + /w/{workspace}/workspaces/set_environment_variable: + post: + summary: set environment variable + operationId: setEnvironmentVariable + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: Workspace default app + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + value: + type: string + required: + - name + responses: + '200': + description: status + content: + text/plain: + schema: + type: string /w/{workspace}/workspaces/encryption_key: get: summary: retrieves the encryption key for this workspace @@ -2004,6 +2570,8 @@ paths: properties: new_key: type: string + skip_reencrypt: + type: boolean required: - new_key responses: @@ -2052,7 +2620,25 @@ paths: application/json: schema: type: object - properties: *ref_15 + properties: *ref_17 + /w/{workspace}/workspaces/usage: + get: + summary: get usage + operationId: getWorkspaceUsage + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: usage + content: + text/plain: + schema: + type: number /w/{workspace}/users/list: get: summary: list users @@ -2073,8 +2659,33 @@ paths: type: array items: type: object - properties: *ref_8 - required: *ref_9 + properties: *ref_10 + required: *ref_11 + /w/{workspace}/users/list_usage: + get: + summary: list users usage + operationId: listUsersUsage + tags: + - user + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: user + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_135 + email: + type: string + executions: + type: number /w/{workspace}/users/list_usernames: get: summary: list usernames @@ -2095,6 +2706,29 @@ paths: type: array items: type: string + /w/{workspace}/users/username_to_email/{username}: + get: + summary: get email from username + operationId: usernameToEmail + tags: + - user + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: email + content: + text/plain: + schema: + type: string /users/tokens/create: post: summary: create token @@ -2108,7 +2742,7 @@ paths: application/json: schema: type: object - properties: &ref_126 + properties: &ref_139 label: type: string expiration: @@ -2118,6 +2752,8 @@ paths: type: array items: type: string + workspace_id: + type: string responses: '201': description: token created @@ -2138,7 +2774,7 @@ paths: application/json: schema: type: object - properties: &ref_127 + properties: &ref_140 label: type: string expiration: @@ -2146,7 +2782,9 @@ paths: format: date-time impersonate_email: type: string - required: &ref_128 + workspace_id: + type: string + required: &ref_141 - impersonate_email responses: '201': @@ -2185,6 +2823,14 @@ paths: in: query schema: type: boolean + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 responses: '200': description: truncated token @@ -2194,7 +2840,7 @@ paths: type: array items: type: object - properties: &ref_124 + properties: &ref_38 label: type: string expiration: @@ -2212,7 +2858,9 @@ paths: type: array items: type: string - required: &ref_125 + email: + type: string + required: &ref_39 - token_prefix - created_at - last_used_at @@ -2261,7 +2909,7 @@ paths: application/json: schema: type: object - properties: &ref_131 + properties: &ref_144 path: type: string value: @@ -2274,7 +2922,10 @@ paths: type: integer is_oauth: type: boolean - required: &ref_132 + expires_at: + type: string + format: date-time + required: &ref_145 - path - value - is_secret @@ -2325,7 +2976,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: variable deleted @@ -2347,7 +2998,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: already_encrypted in: query schema: @@ -2359,7 +3010,7 @@ paths: application/json: schema: type: object - properties: &ref_133 + properties: &ref_146 path: type: string value: @@ -2389,7 +3040,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: decrypt_secret description: | ask to decrypt secret if this variable is secret @@ -2411,7 +3062,7 @@ paths: application/json: schema: type: object - properties: &ref_18 + properties: &ref_22 workspace_id: type: string path: @@ -2438,7 +3089,10 @@ paths: type: boolean is_refreshed: type: boolean - required: &ref_19 + expires_at: + type: string + format: date-time + required: &ref_23 - workspace_id - path - is_secret @@ -2457,7 +3111,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: variable @@ -2479,7 +3133,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: variable @@ -2498,6 +3152,18 @@ paths: in: path required: true schema: *ref_0 + - name: path_start + in: query + schema: + type: string + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 responses: '200': description: variable list @@ -2507,8 +3173,8 @@ paths: type: array items: type: object - properties: *ref_18 - required: *ref_19 + properties: *ref_22 + required: *ref_23 /w/{workspace}/variables/list_contextual: get: summary: list contextual variables @@ -2529,17 +3195,20 @@ paths: type: array items: type: object - properties: &ref_129 + properties: &ref_142 name: type: string value: type: string description: type: string - required: &ref_130 + is_custom: + type: boolean + required: &ref_143 - name - value - description + - is_custom /oauth/login_callback/{client_name}: post: security: [] @@ -2551,7 +3220,7 @@ paths: - name: client_name in: path required: true - schema: &ref_20 + schema: &ref_24 type: string requestBody: description: Partially filled script @@ -2614,6 +3283,34 @@ paths: text/plain: schema: type: string + /oauth/connect_slack_callback: + post: + summary: connect slack callback instance + operationId: connectSlackCallbackInstance + tags: + - oauth + requestBody: + description: code endpoint + required: true + content: + application/json: + schema: + type: object + properties: + code: + type: string + state: + type: string + required: + - code + - state + responses: + '200': + description: success message + content: + text/plain: + schema: + type: string /oauth/connect_callback/{client_name}: post: summary: connect callback @@ -2624,7 +3321,7 @@ paths: - name: client_name in: path required: true - schema: *ref_20 + schema: *ref_24 requestBody: description: code endpoint required: true @@ -2647,7 +3344,7 @@ paths: application/json: schema: type: object - properties: &ref_167 + properties: &ref_191 access_token: type: string expires_in: @@ -2658,7 +3355,7 @@ paths: type: array items: type: string - required: &ref_168 + required: &ref_192 - access_token /w/{workspace}/oauth/create_account: post: @@ -2709,7 +3406,7 @@ paths: - name: id in: path required: true - schema: &ref_21 + schema: &ref_25 type: integer requestBody: description: variable path @@ -2744,7 +3441,7 @@ paths: - name: id in: path required: true - schema: *ref_21 + schema: *ref_25 responses: '200': description: disconnected client @@ -2787,7 +3484,14 @@ paths: oauth: type: array items: - type: string + type: object + properties: + type: + type: string + display_name: + type: string + required: + - type saml: type: string required: @@ -2804,16 +3508,36 @@ paths: content: application/json: schema: - additionalProperties: - type: object - properties: - extra_params: - additionalProperties: - type: string - scopes: - type: array - items: - type: string + type: array + items: + type: string + /oauth/get_connect/{client}: + get: + summary: get oauth connect + operationId: getOAuthConnect + tags: + - oauth + parameters: + - name: client + description: client name + in: path + required: true + schema: + type: string + responses: + '200': + description: get + content: + application/json: + schema: + type: object + properties: + extra_params: + type: object + scopes: + type: array + items: + type: string /w/{workspace}/resources/create: post: summary: create resource @@ -2836,7 +3560,7 @@ paths: application/json: schema: type: object - properties: &ref_136 + properties: &ref_153 path: type: string value: {} @@ -2844,7 +3568,7 @@ paths: type: string resource_type: type: string - required: &ref_137 + required: &ref_154 - path - value - resource_type @@ -2869,7 +3593,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource deleted @@ -2891,7 +3615,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: updated resource required: true @@ -2899,7 +3623,7 @@ paths: application/json: schema: type: object - properties: &ref_138 + properties: &ref_155 path: type: string description: @@ -2926,7 +3650,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: updated resource required: true @@ -2957,7 +3681,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource @@ -2965,7 +3689,7 @@ paths: application/json: schema: type: object - properties: &ref_139 + properties: &ref_156 workspace_id: type: string path: @@ -2981,7 +3705,12 @@ paths: type: object additionalProperties: type: boolean - required: &ref_140 + created_by: + type: string + edited_at: + type: string + format: date-time + required: &ref_157 - path - resource_type - is_oauth @@ -2999,7 +3728,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: job_id description: job id in: query @@ -3026,7 +3755,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource value @@ -3047,7 +3776,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: does resource exists @@ -3069,11 +3798,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: resource_type description: resource_types to list from, separated by ',', in: query @@ -3084,6 +3813,10 @@ paths: in: query schema: type: string + - name: path_start + in: query + schema: + type: string responses: '200': description: resource list @@ -3093,7 +3826,7 @@ paths: type: array items: type: object - properties: &ref_141 + properties: &ref_158 workspace_id: type: string path: @@ -3119,7 +3852,12 @@ paths: type: boolean account: type: number - required: &ref_142 + created_by: + type: string + edited_at: + type: string + format: date-time + required: &ref_159 - path - resource_type - is_oauth @@ -3166,7 +3904,7 @@ paths: - name: name in: path required: true - schema: &ref_80 + schema: &ref_92 type: string responses: '200': @@ -3203,7 +3941,7 @@ paths: application/json: schema: type: object - properties: &ref_22 + properties: &ref_26 workspace_id: type: string name: @@ -3211,7 +3949,14 @@ paths: schema: {} description: type: string - required: &ref_23 + created_by: + type: string + edited_at: + type: string + format: date-time + format_extension: + type: string + required: &ref_27 - name responses: '201': @@ -3220,6 +3965,23 @@ paths: text/plain: 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: + - name: workspace + in: path + required: true + schema: *ref_0 + 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 @@ -3234,7 +3996,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource_type deleted @@ -3256,7 +4018,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: updated resource_type required: true @@ -3264,7 +4026,7 @@ paths: application/json: schema: type: object - properties: &ref_143 + properties: &ref_160 schema: {} description: type: string @@ -3289,7 +4051,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource_type deleted @@ -3297,8 +4059,8 @@ paths: application/json: schema: type: object - properties: *ref_22 - required: *ref_23 + properties: *ref_26 + required: *ref_27 /w/{workspace}/resources/type/exists/{path}: get: summary: does resource_type exists @@ -3313,7 +4075,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: does resource_type exist @@ -3341,8 +4103,8 @@ paths: type: array items: type: object - properties: *ref_22 - required: *ref_23 + properties: *ref_26 + required: *ref_27 /w/{workspace}/resources/type/listnames: get: summary: list resource_types names @@ -3481,7 +4243,7 @@ paths: - name: id in: path required: true - schema: *ref_24 + schema: *ref_28 responses: '200': description: flow @@ -3492,51 +4254,51 @@ paths: properties: flow: type: object - properties: &ref_43 + properties: &ref_50 summary: type: string description: type: string value: type: object - properties: &ref_50 + properties: &ref_58 modules: type: array items: type: object - properties: &ref_27 + properties: &ref_31 id: type: string value: - oneOf: &ref_206 + oneOf: &ref_239 - type: object - properties: &ref_192 + properties: &ref_223 input_transforms: type: object additionalProperties: - oneOf: &ref_25 + oneOf: &ref_29 - type: object - properties: &ref_188 + properties: &ref_219 value: {} type: type: string enum: - javascript - required: &ref_189 + required: &ref_220 - expr - type - type: object - properties: &ref_190 + properties: &ref_221 expr: type: string type: type: string enum: - javascript - required: &ref_191 + required: &ref_222 - expr - type - discriminator: &ref_26 + discriminator: &ref_30 propertyName: type mapping: static: '#/components/schemas/StaticTransform' @@ -3559,6 +4321,7 @@ paths: - mssql - graphql - nativets + - php path: type: string lock: @@ -3573,18 +4336,20 @@ paths: type: number concurrency_time_window_s: type: number - required: &ref_193 + custom_concurrency_key: + type: string + required: &ref_224 - type - content - language - input_transforms - type: object - properties: &ref_194 + properties: &ref_225 input_transforms: type: object additionalProperties: - oneOf: *ref_25 - discriminator: *ref_26 + oneOf: *ref_29 + discriminator: *ref_30 path: type: string hash: @@ -3593,40 +4358,42 @@ paths: type: string enum: - script - required: &ref_195 + tag_override: + type: string + required: &ref_226 - type - path - input_transforms - type: object - properties: &ref_196 + properties: &ref_227 input_transforms: type: object additionalProperties: - oneOf: *ref_25 - discriminator: *ref_26 + oneOf: *ref_29 + discriminator: *ref_30 path: type: string type: type: string enum: - flow - required: &ref_197 + required: &ref_228 - type - path - input_transforms - type: object - properties: &ref_198 + properties: &ref_229 modules: type: array items: type: object - properties: *ref_27 - required: &ref_28 + properties: *ref_31 + required: &ref_32 - value - id iterator: - oneOf: *ref_25 - discriminator: *ref_26 + oneOf: *ref_29 + discriminator: *ref_30 skip_failures: type: boolean type: @@ -3637,13 +4404,35 @@ paths: type: boolean parallelism: type: integer - required: &ref_199 + required: &ref_230 - modules - iterator - skip_failures - type - type: object - properties: &ref_200 + properties: &ref_231 + modules: + type: array + items: + type: object + properties: *ref_31 + required: *ref_32 + skip_failures: + type: boolean + type: + type: string + enum: + - forloopflow + parallel: + type: boolean + parallelism: + type: integer + required: &ref_232 + - modules + - skip_failures + - type + - type: object + properties: &ref_233 branches: type: array items: @@ -3657,8 +4446,8 @@ paths: type: array items: type: object - properties: *ref_27 - required: *ref_28 + properties: *ref_31 + required: *ref_32 required: - modules - expr @@ -3666,20 +4455,20 @@ paths: type: array items: type: object - properties: *ref_27 - required: *ref_28 + properties: *ref_31 + required: *ref_32 required: - modules type: type: string enum: - branchone - required: &ref_201 + required: &ref_234 - branches - default - type - type: object - properties: &ref_202 + properties: &ref_235 branches: type: array items: @@ -3693,8 +4482,8 @@ paths: type: array items: type: object - properties: *ref_27 - required: *ref_28 + properties: *ref_31 + required: *ref_32 required: - modules - expr @@ -3704,26 +4493,27 @@ paths: - branchall parallel: type: boolean - required: &ref_203 + required: &ref_236 - branches - type - type: object - properties: &ref_204 + properties: &ref_237 type: type: string enum: - identity flow: type: boolean - required: &ref_205 + required: &ref_238 - type - discriminator: &ref_207 + discriminator: &ref_240 propertyName: type mapping: rawscript: '#/components/schemas/RawScript' script: '#/components/schemas/PathScript' flow: '#/components/schemas/PathFlow' forloopflow: '#/components/schemas/ForloopFlow' + whileloopflow: '#/components/schemas/WhileloopFlow' branchone: '#/components/schemas/BranchOne' branchall: '#/components/schemas/BranchAll' identity: '#/components/schemas/Identity' @@ -3736,9 +4526,25 @@ paths: type: string required: - expr + stop_after_all_iters_if: + type: object + properties: + skip_if_stopped: + type: boolean + expr: + type: string + required: + - expr + skip_if: + type: object + properties: + expr: + type: string + required: + - expr sleep: - oneOf: *ref_25 - discriminator: *ref_26 + oneOf: *ref_29 + discriminator: *ref_30 cache_ttl: type: number timeout: @@ -3768,15 +4574,21 @@ paths: user_auth_required: type: boolean user_groups_required: - oneOf: *ref_25 - discriminator: *ref_26 + oneOf: *ref_29 + discriminator: *ref_30 self_approval_disabled: type: boolean + hide_cancel: + type: boolean + continue_on_disapprove_timeout: + type: boolean priority: type: number + continue_on_error: + type: boolean retry: type: object - properties: &ref_77 + properties: &ref_87 constant: type: object properties: @@ -3797,15 +4609,21 @@ paths: type: integer minimum: 0 maximum: 100 - required: *ref_28 + required: *ref_32 failure_module: type: object - properties: *ref_27 - required: *ref_28 + properties: *ref_31 + required: *ref_32 + preprocessor_module: + type: object + properties: *ref_31 + required: *ref_32 same_worker: type: boolean concurrent_limit: type: number + concurrency_key: + type: string concurrency_time_window_s: type: number skip_expr: @@ -3816,11 +4634,11 @@ paths: type: number early_return: type: string - required: &ref_51 + required: &ref_59 - modules schema: type: object - required: &ref_44 + required: &ref_51 - summary - value /apps/hub/list: @@ -3873,7 +4691,7 @@ paths: - name: id in: path required: true - schema: *ref_24 + schema: *ref_28 responses: '200': description: app @@ -3903,7 +4721,7 @@ paths: - name: path in: path required: true - schema: &ref_29 + schema: &ref_33 type: string responses: '200': @@ -3922,7 +4740,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script details @@ -3993,7 +4811,7 @@ paths: type: number kind: name: kind - schema: &ref_30 + schema: &ref_34 type: string enum: - script @@ -4066,7 +4884,7 @@ paths: type: string kind: name: kind - schema: *ref_30 + schema: *ref_34 score: type: number required: @@ -4119,20 +4937,20 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: order_desc description: order by desc order (default true) in: query - schema: &ref_41 + schema: &ref_48 type: boolean - name: created_by description: mask to filter exact matching user creator in: query - schema: &ref_42 + schema: &ref_49 type: string - name: path_start description: mask to filter matching starting path @@ -4182,7 +5000,7 @@ paths: description: > (default false) - show also the archived files. + show only the archived files. when multiple archived hash share the same path, only the ones with the latest create_at @@ -4193,6 +5011,20 @@ paths: in: query schema: type: boolean + - name: include_without_main + description: | + (default false) + include scripts without an exported main function + in: query + schema: + type: boolean + - name: include_draft_only + description: | + (default false) + include scripts that have no deployed version + in: query + schema: + type: boolean - name: is_template description: | (default regardless) @@ -4216,6 +5048,13 @@ paths: in: query schema: type: boolean + - name: with_deployment_msg + description: | + (default false) + include deployment message + in: query + schema: + type: boolean responses: '200': description: All scripts @@ -4225,7 +5064,7 @@ paths: type: array items: type: object - properties: &ref_31 + properties: &ref_35 workspace_id: type: string hash: @@ -4282,6 +5121,9 @@ paths: - graphql - nativets - bun + - php + - rust + - ansible kind: type: string enum: @@ -4306,6 +5148,8 @@ paths: type: integer concurrency_time_window_s: type: integer + concurrency_key: + type: string cache_ttl: type: number dedicated_worker: @@ -4320,7 +5164,15 @@ paths: type: integer delete_after_use: type: boolean - required: &ref_32 + visible_to_runner_only: + type: boolean + no_main_func: + type: boolean + codebase: + type: string + has_preprocessor: + type: boolean + required: &ref_36 - hash - path - summary @@ -4335,6 +5187,8 @@ paths: - language - kind - starred + - no_main_func + - has_preprocessor /w/{workspace}/scripts/list_paths: get: summary: list all scripts paths @@ -4416,7 +5270,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: draft deleted @@ -4442,7 +5296,7 @@ paths: application/json: schema: type: object - properties: &ref_34 + properties: &ref_40 path: type: string parent_hash: @@ -4475,6 +5329,9 @@ paths: - graphql - nativets - bun + - php + - rust + - ansible kind: type: string enum: @@ -4513,7 +5370,15 @@ paths: type: string concurrency_key: type: string - required: &ref_35 + visible_to_runner_only: + type: boolean + no_main_func: + type: boolean + codebase: + type: string + has_preprocessor: + type: boolean + required: &ref_41 - path - summary - description @@ -4540,7 +5405,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: Workspace error handler enabled required: true @@ -4617,7 +5482,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script archived @@ -4639,7 +5504,7 @@ paths: - name: hash in: path required: true - schema: &ref_33 + schema: &ref_37 type: string responses: '200': @@ -4648,8 +5513,8 @@ paths: application/json: schema: type: object - properties: *ref_31 - required: *ref_32 + properties: *ref_35 + required: *ref_36 /w/{workspace}/scripts/delete/h/{hash}: post: summary: delete script by hash (erase content but keep hash, require admin) @@ -4664,7 +5529,7 @@ paths: - name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 responses: '200': description: script details @@ -4672,8 +5537,8 @@ paths: application/json: schema: type: object - properties: *ref_31 - required: *ref_32 + properties: *ref_35 + required: *ref_36 /w/{workspace}/scripts/delete/p/{path}: post: summary: delete all scripts at a given path (require admin) @@ -4688,7 +5553,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script path @@ -4710,7 +5575,11 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 + - name: with_starred_info + in: query + schema: + type: boolean responses: '200': description: script details @@ -4718,8 +5587,70 @@ paths: application/json: schema: type: object - properties: *ref_31 - required: *ref_32 + properties: *ref_35 + required: *ref_36 + /w/{workspace}/scripts/get_triggers_count/{path}: + get: + summary: get triggers count of script + operationId: getTriggersCountOfScript + tags: + - script + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_33 + responses: + '200': + description: triggers count + content: + application/json: + schema: + type: object + properties: &ref_53 + primary_schedule: + type: object + properties: + schedule: + type: string + schedule_count: + type: number + http_routes_count: + type: number + webhook_count: + type: number + email_count: + type: number + /w/{workspace}/scripts/list_tokens/{path}: + get: + summary: get tokens with script scope + operationId: listTokensOfScript + tags: + - script + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_33 + responses: + '200': + description: tokens list + content: + application/json: + schema: + type: array + items: + type: object + properties: *ref_38 + required: *ref_39 /w/{workspace}/scripts/get/draft/{path}: get: summary: get script by path with draft @@ -4734,23 +5665,23 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script details content: application/json: schema: - allOf: &ref_110 + allOf: &ref_126 - type: object - properties: *ref_34 - required: *ref_35 + properties: *ref_40 + required: *ref_41 - type: object properties: draft: type: object - properties: *ref_34 - required: *ref_35 + properties: *ref_40 + required: *ref_41 hash: type: string required: @@ -4769,7 +5700,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script history @@ -4779,12 +5710,12 @@ paths: type: array items: type: object - properties: &ref_111 + properties: &ref_127 script_hash: type: string deployment_msg: type: string - required: &ref_112 + required: &ref_128 - script_hash /w/{workspace}/scripts/history_update/h/{hash}/p/{path}: post: @@ -4800,11 +5731,11 @@ paths: - name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: Script deployment message required: true @@ -4836,7 +5767,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script content @@ -4860,12 +5791,12 @@ paths: - name: token in: path required: true - schema: &ref_96 + schema: &ref_115 type: string - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script content @@ -4887,7 +5818,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: does it exists @@ -4909,7 +5840,11 @@ paths: - name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 + - name: with_starred_info + in: query + schema: + type: boolean responses: '200': description: script details @@ -4917,8 +5852,8 @@ paths: application/json: schema: type: object - properties: *ref_31 - required: *ref_32 + properties: *ref_35 + required: *ref_36 /w/{workspace}/scripts/raw/h/{path}: get: summary: raw script by hash @@ -4933,7 +5868,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: script content @@ -4955,7 +5890,7 @@ paths: - name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 responses: '200': description: script details @@ -4982,7 +5917,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: scheduled_for description: when to schedule this job (leave empty for immediate run) in: query @@ -4994,18 +5929,30 @@ paths: in: query schema: type: integer + - name: skip_preprocessor + description: skip the preprocessor + in: query + schema: + type: boolean - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: &ref_36 + schema: &ref_42 type: string format: uuid - name: tag description: Override the tag to use in: query - schema: &ref_38 + schema: &ref_44 + type: string + - name: cache_ttl + description: >- + Override the cache time to live (in seconds). Can not be used to + disable caching, only override with a new cache ttl + in: query + schema: &ref_45 type: string - name: job_id description: >- @@ -5014,7 +5961,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: &ref_37 + schema: &ref_43 type: string format: uuid - name: invisible_to_owner @@ -5029,7 +5976,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '201': description: job created @@ -5052,13 +5999,13 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -5066,7 +6013,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -5075,14 +6022,14 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: &ref_39 + schema: &ref_46 type: string - name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: &ref_40 + schema: &ref_47 type: string requestBody: description: script args @@ -5091,7 +6038,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '200': description: job result @@ -5112,17 +6059,23 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 + - name: cache_ttl + description: >- + Override the cache time to live (in seconds). Can not be used to + disable caching, only override with a new cache ttl + in: query + schema: *ref_45 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -5130,7 +6083,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -5139,13 +6092,13 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: *ref_40 + schema: *ref_47 requestBody: description: script args required: true @@ -5153,7 +6106,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '200': description: job result @@ -5173,17 +6126,23 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 + - name: cache_ttl + description: >- + Override the cache time to live (in seconds). Can not be used to + disable caching, only override with a new cache ttl + in: query + schema: *ref_45 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -5191,7 +6150,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -5200,13 +6159,13 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: *ref_40 + schema: *ref_47 - name: payload description: > The base64 encoded payload that has been encoded as a JSON. e.g how @@ -5214,7 +6173,7 @@ paths: `encodeURIComponent(btoa(JSON.stringify({a: 2})))` in: query - schema: &ref_76 + schema: &ref_86 type: string responses: '200': @@ -5236,7 +6195,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -5245,13 +6204,13 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: *ref_40 + schema: *ref_47 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -5259,7 +6218,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 requestBody: description: script args required: true @@ -5267,7 +6226,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '200': description: job result @@ -5288,7 +6247,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -5297,13 +6256,13 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: *ref_40 + schema: *ref_47 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -5311,7 +6270,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 requestBody: description: script args required: true @@ -5319,7 +6278,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '200': description: job result @@ -5414,19 +6373,19 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 - name: path_start description: mask to filter matching starting path in: query @@ -5441,7 +6400,7 @@ paths: description: > (default false) - show also the archived files. + show only the archived files. when multiple archived hash share the same path, only the ones with the latest create_at @@ -5457,6 +6416,20 @@ paths: in: query schema: type: boolean + - name: include_draft_only + description: | + (default false) + include items that have no deployed version + in: query + schema: + type: boolean + - name: with_deployment_msg + description: | + (default false) + include deployment message + in: query + schema: + type: boolean responses: '200': description: All flow @@ -5466,12 +6439,12 @@ paths: type: array items: allOf: - - allOf: &ref_45 + - allOf: &ref_52 - type: object - properties: *ref_43 - required: *ref_44 + properties: *ref_50 + required: *ref_51 - type: object - properties: &ref_155 + properties: &ref_177 workspace_id: type: string path: @@ -5485,8 +6458,8 @@ paths: type: boolean extra_perms: type: object - additionalProperties: - type: boolean + additionalProperties: &ref_176 + type: boolean starred: type: boolean draft_only: @@ -5501,7 +6474,9 @@ paths: type: boolean timeout: type: number - required: &ref_156 + visible_to_runner_only: + type: boolean + required: &ref_178 - path - edited_by - edited_at @@ -5513,6 +6488,109 @@ paths: type: boolean draft_only: type: boolean + /w/{workspace}/flows/history/p/{path}: + get: + summary: get flow history by path + operationId: getFlowHistory + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_33 + tags: + - flow + responses: + '200': + description: Flow history + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_189 + id: + type: integer + created_at: + type: string + format: date-time + deployment_msg: + type: string + required: &ref_190 + - id + - created_at + /w/{workspace}/flows/get/v/{version}/p/{path}: + get: + summary: get flow version + operationId: getFlowVersion + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - type: string + name: version + in: path + required: true + schema: + type: number + - name: path + in: path + required: true + schema: *ref_33 + tags: + - flow + responses: + '200': + description: flow details + content: + application/json: + schema: + allOf: *ref_52 + /w/{workspace}/flows/history_update/v/{version}/p/{path}: + post: + summary: update flow history + operationId: updateFlowHistory + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - type: string + name: version + in: path + required: true + schema: + type: number + - name: path + in: path + required: true + schema: *ref_33 + requestBody: + description: Flow deployment message + required: true + content: + application/json: + schema: + type: object + properties: + deployment_msg: + type: string + required: + - deployment_msg + tags: + - flow + responses: + '200': + description: success + content: + text/plain: + schema: + type: string /w/{workspace}/flows/get/{path}: get: summary: get flow by path @@ -5527,14 +6605,67 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 + - name: with_starred_info + in: query + schema: + type: boolean responses: '200': description: flow details content: application/json: schema: - allOf: *ref_45 + allOf: *ref_52 + /w/{workspace}/flows/get_triggers_count/{path}: + get: + summary: get triggers count of flow + operationId: getTriggersCountOfFlow + tags: + - flow + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_33 + responses: + '200': + description: triggers count + content: + application/json: + schema: + type: object + properties: *ref_53 + /w/{workspace}/flows/list_tokens/{path}: + get: + summary: get tokens with flow scope + operationId: listTokensOfFlow + tags: + - flow + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_33 + responses: + '200': + description: tokens list + content: + application/json: + schema: + type: array + items: + type: object + properties: *ref_38 + required: *ref_39 /w/{workspace}/flows/toggle_workspace_error_handler/{path}: post: summary: Toggle ON and OFF the workspace error handler for a given flow @@ -5549,7 +6680,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: Workspace error handler enabled required: true @@ -5581,7 +6712,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: flow details with draft @@ -5589,11 +6720,11 @@ paths: application/json: schema: allOf: - - allOf: *ref_45 + - allOf: *ref_52 - type: object properties: draft: - allOf: *ref_45 + allOf: *ref_52 /w/{workspace}/flows/exists/{path}: get: summary: exists flow by path @@ -5608,7 +6739,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: flow details @@ -5634,10 +6765,10 @@ paths: application/json: schema: allOf: - - allOf: &ref_46 + - allOf: &ref_54 - type: object - properties: *ref_43 - required: *ref_44 + properties: *ref_50 + required: *ref_51 - type: object properties: path: @@ -5652,6 +6783,8 @@ paths: type: boolean timeout: type: number + visible_to_runner_only: + type: boolean required: - path - type: object @@ -5681,7 +6814,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: Partially filled flow required: true @@ -5689,7 +6822,7 @@ paths: application/json: schema: allOf: - - allOf: *ref_46 + - allOf: *ref_54 - type: object properties: deployment_message: @@ -5715,7 +6848,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: archiveFlow required: true @@ -5747,7 +6880,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: flow delete @@ -5755,61 +6888,6 @@ paths: text/plain: schema: type: string - /w/{workspace}/flows/input_history/p/{path}: - get: - summary: list inputs for previous completed flow jobs - operationId: getFlowInputHistoryByPath - tags: - - flow - parameters: - - name: workspace - in: path - required: true - schema: *ref_0 - - name: path - in: path - required: true - schema: *ref_29 - - name: page - description: which page to return (start at 1, default 1) - in: query - schema: *ref_3 - - name: per_page - description: number of items to return for a given page (default 30, max 100) - in: query - schema: *ref_4 - responses: - '200': - description: input history for completed jobs with this flow path - content: - application/json: - schema: - type: array - items: - type: object - properties: &ref_87 - id: - type: string - name: - type: string - args: - type: object - created_by: - type: string - created_at: - type: string - format: date-time - is_public: - type: boolean - success: - type: boolean - required: &ref_88 - - id - - name - - args - - created_by - - created_at - - is_public /w/{workspace}/raw_apps/list: get: summary: list all raw apps @@ -5824,19 +6902,19 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 - name: path_start description: mask to filter matching starting path in: query @@ -5863,7 +6941,7 @@ paths: type: array items: type: object - properties: &ref_162 + properties: &ref_184 workspace_id: type: string path: @@ -5881,7 +6959,7 @@ paths: edited_at: type: string format: date-time - required: &ref_163 + required: &ref_185 - workspace_id - path - summary @@ -5902,7 +6980,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app exists @@ -5924,12 +7002,12 @@ paths: - name: version in: path required: true - schema: &ref_95 + schema: &ref_114 type: number - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: app details @@ -5978,19 +7056,19 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 - name: path_start description: mask to filter matching starting path in: query @@ -6008,6 +7086,20 @@ paths: in: query schema: type: boolean + - name: include_draft_only + description: | + (default false) + include items that have no deployed version + in: query + schema: + type: boolean + - name: with_deployment_msg + description: | + (default false) + include deployment message + in: query + schema: + type: boolean responses: '200': description: All apps @@ -6017,7 +7109,7 @@ paths: type: array items: type: object - properties: &ref_160 + properties: &ref_182 id: type: integer workspace_id: @@ -6043,7 +7135,7 @@ paths: - viewer - publisher - anonymous - required: &ref_161 + required: &ref_183 - id - workspace_id - path @@ -6078,11 +7170,15 @@ paths: type: string policy: type: object - properties: &ref_47 + properties: &ref_55 triggerables: type: object additionalProperties: type: object + triggerables_v2: + type: object + additionalProperties: + type: object execution_mode: type: string enum: @@ -6123,7 +7219,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app exists @@ -6145,7 +7241,11 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 + - name: with_starred_info + in: query + schema: + type: boolean responses: '200': description: app details @@ -6153,7 +7253,7 @@ paths: application/json: schema: type: object - properties: &ref_48 + properties: &ref_56 id: type: integer workspace_id: @@ -6171,10 +7271,11 @@ paths: created_at: type: string format: date-time - value: {} + value: + type: object policy: type: object - properties: *ref_47 + properties: *ref_55 execution_mode: type: string enum: @@ -6185,7 +7286,7 @@ paths: type: object additionalProperties: type: boolean - required: &ref_49 + required: &ref_57 - id - workspace_id - path @@ -6211,17 +7312,17 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: app details with draft content: application/json: schema: - allOf: &ref_164 + allOf: &ref_186 - type: object - properties: *ref_48 - required: *ref_49 + properties: *ref_56 + required: *ref_57 - type: object properties: draft_only: @@ -6241,7 +7342,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 responses: '200': description: app history @@ -6251,12 +7352,12 @@ paths: type: array items: type: object - properties: &ref_165 + properties: &ref_187 version: type: integer deployment_msg: type: string - required: &ref_166 + required: &ref_188 - version /w/{workspace}/apps/history_update/a/{id}/v/{version}: post: @@ -6272,11 +7373,11 @@ paths: - name: id in: path required: true - schema: *ref_24 + schema: *ref_28 - name: version in: path required: true - schema: &ref_97 + schema: &ref_116 type: integer requestBody: description: App deployment message @@ -6309,7 +7410,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app details @@ -6317,8 +7418,8 @@ paths: application/json: schema: type: object - properties: *ref_48 - required: *ref_49 + properties: *ref_56 + required: *ref_57 /w/{workspace}/apps_u/public_resource/{path}: get: summary: get public resource @@ -6333,7 +7434,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: resource value @@ -6354,7 +7455,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app secret @@ -6376,7 +7477,7 @@ paths: - name: id in: path required: true - schema: *ref_24 + schema: *ref_28 responses: '200': description: app details @@ -6384,8 +7485,8 @@ paths: application/json: schema: type: object - properties: *ref_48 - required: *ref_49 + properties: *ref_56 + required: *ref_57 /w/{workspace}/raw_apps/create: post: summary: create raw app @@ -6436,7 +7537,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: updateraw app required: true @@ -6472,7 +7573,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app deleted @@ -6494,7 +7595,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: app deleted @@ -6516,7 +7617,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: update app required: true @@ -6532,7 +7633,7 @@ paths: value: {} policy: type: object - properties: *ref_47 + properties: *ref_55 deployment_message: type: string responses: @@ -6556,7 +7657,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 requestBody: description: update app required: true @@ -6579,6 +7680,8 @@ paths: type: string path: type: string + lock: + type: string cache_ttl: type: integer required: @@ -6586,6 +7689,12 @@ paths: - language force_viewer_static_fields: type: object + force_viewer_one_of_fields: + type: object + force_viewer_allow_user_resources: + type: array + items: + type: string required: - args - component @@ -6610,7 +7719,7 @@ paths: - name: path in: path required: true - schema: *ref_29 + schema: *ref_33 - name: scheduled_for description: when to schedule this job (leave empty for immediate run) in: query @@ -6622,16 +7731,21 @@ paths: in: query schema: type: integer + - name: skip_preprocessor + description: skip the preprocessor + in: query + schema: + type: boolean - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -6639,7 +7753,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -6648,7 +7762,7 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: invisible_to_owner description: make the run invisible to the the flow owner (default false) in: query @@ -6661,7 +7775,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '201': description: job created @@ -6684,7 +7798,7 @@ paths: - name: id in: path required: true - schema: &ref_73 + schema: &ref_83 type: string format: uuid - name: step_id @@ -6717,11 +7831,11 @@ paths: The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -6729,7 +7843,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -6738,7 +7852,7 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: invisible_to_owner description: make the run invisible to the the flow owner (default false) in: query @@ -6751,7 +7865,7 @@ paths: application/json: schema: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 responses: '201': description: job created @@ -6774,7 +7888,7 @@ paths: - name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 - name: scheduled_for description: when to schedule this job (leave empty for immediate run) in: query @@ -6786,16 +7900,27 @@ paths: in: query schema: type: integer + - name: skip_preprocessor + description: skip the preprocessor + in: query + schema: + type: boolean - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 + - name: cache_ttl + description: >- + Override the cache time to live (in seconds). Can not be used to + disable caching, only override with a new cache ttl + in: query + schema: *ref_45 - name: job_id description: >- The job id to assign to the created job. if missing, job is chosen @@ -6803,7 +7928,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 - name: include_header description: > List of headers's keys (separated with ',') whove value are added to @@ -6812,7 +7937,7 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: invisible_to_owner description: make the run invisible to the the script owner (default false) in: query @@ -6852,7 +7977,7 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: invisible_to_owner description: make the run invisible to the the script owner (default false) in: query @@ -6865,7 +7990,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 requestBody: description: preview required: true @@ -6873,14 +7998,14 @@ paths: application/json: schema: type: object - properties: &ref_134 + properties: &ref_147 content: type: string path: type: string args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 language: type: string enum: @@ -6897,6 +8022,9 @@ paths: - graphql - nativets - bun + - php + - rust + - ansible tag: type: string kind: @@ -6909,7 +8037,49 @@ paths: type: boolean lock: type: string - required: &ref_135 + required: &ref_148 + - args + responses: + '201': + description: job created + content: + text/plain: + schema: + type: string + format: uuid + /w/{workspace}/jobs/workflow_as_code/{job_id}/{entrypoint}: + post: + summary: run code-workflow task + operationId: runCodeWorkflowTask + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: job_id + in: path + required: true + schema: + type: string + - name: entrypoint + in: path + required: true + schema: + type: string + requestBody: + description: preview + required: true + content: + application/json: + schema: + type: object + properties: &ref_149 + args: + type: object + additionalProperties: *ref_16 + required: &ref_150 - args responses: '201': @@ -6942,7 +8112,7 @@ paths: type: array items: type: object - properties: &ref_184 + properties: &ref_208 raw_code: type: string path: @@ -6963,7 +8133,10 @@ paths: - graphql - nativets - bun - required: &ref_185 + - php + - rust + - ansible + required: &ref_209 - raw_code - path - language @@ -7003,7 +8176,7 @@ paths: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 - name: invisible_to_owner description: make the run invisible to the the script owner (default false) in: query @@ -7016,7 +8189,7 @@ paths: queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 requestBody: description: preview required: true @@ -7024,21 +8197,21 @@ paths: application/json: schema: type: object - properties: &ref_157 + properties: &ref_179 value: type: object - properties: *ref_50 - required: *ref_51 + properties: *ref_58 + required: *ref_59 path: type: string args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 tag: type: string restarted_from: type: object - properties: &ref_159 + properties: &ref_181 flow_job_id: type: string format: uuid @@ -7046,7 +8219,7 @@ paths: type: string branch_or_iteration_n: type: integer - required: &ref_158 + required: &ref_180 - value - content - args @@ -7072,95 +8245,103 @@ paths: - name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: script_path_exact description: mask to filter exact matching path in: query - schema: &ref_54 + schema: &ref_62 type: string - name: script_path_start description: mask to filter matching starting path in: query - schema: &ref_55 + schema: &ref_63 type: string - name: schedule_path description: mask to filter by schedule path in: query - schema: &ref_56 + schema: &ref_64 type: string - name: script_hash description: mask to filter exact matching path in: query - schema: &ref_57 + schema: &ref_65 type: string - name: started_before description: filter on started before (inclusive) timestamp in: query - schema: &ref_58 + schema: &ref_66 type: string format: date-time - name: started_after description: filter on started after (exclusive) timestamp in: query - schema: &ref_59 + schema: &ref_67 type: string format: date-time - name: success description: filter on successful jobs in: query - schema: &ref_60 + schema: &ref_68 type: boolean - name: scheduled_for_before_now description: filter on jobs scheduled_for before now (hence waitinf for a worker) in: query - schema: &ref_68 + schema: &ref_69 type: boolean - name: job_kinds description: >- filter on job kind (values 'preview', 'script', 'dependencies', 'flow') separated by, in: query - schema: &ref_61 + schema: &ref_70 type: string - name: suspended description: filter on suspended jobs in: query - schema: &ref_100 + schema: &ref_71 type: boolean - name: running description: filter on running jobs in: query - schema: &ref_67 + schema: &ref_72 type: boolean - name: args description: >- filter on jobs containing those args as a json subset (@> in postgres) in: query - schema: &ref_62 + schema: &ref_73 type: string - name: result description: >- filter on jobs containing those result as a json subset (@> in postgres) in: query - schema: &ref_63 + schema: &ref_74 type: string - name: tag description: filter on jobs with a given tag/worker group in: query - schema: &ref_64 + schema: &ref_75 type: string + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 - name: all_workspaces description: >- get jobs from all workspaces (only valid if request come from the @@ -7168,6 +8349,11 @@ paths: in: query schema: type: boolean + - name: is_not_schedule + description: is not a scheduled job + in: query + schema: + type: boolean responses: '200': description: All queued jobs @@ -7177,7 +8363,7 @@ paths: type: array items: type: object - properties: &ref_71 + properties: &ref_81 workspace_id: type: string id: @@ -7205,7 +8391,7 @@ paths: type: string args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 logs: type: string raw_code: @@ -7244,14 +8430,14 @@ paths: by extension its DT_TOKEN. flow_status: type: object - properties: &ref_65 + properties: &ref_76 step: type: integer modules: type: array items: type: object - properties: &ref_52 + properties: &ref_60 type: type: string enum: @@ -7268,6 +8454,8 @@ paths: format: uuid count: type: integer + progress: + type: integer iterator: type: object properties: @@ -7281,6 +8469,10 @@ paths: type: array items: type: string + flow_jobs_success: + type: array + items: + type: boolean branch_chosen: type: object properties: @@ -7315,13 +8507,27 @@ paths: required: - resume_id - approver - required: &ref_53 + failed_retries: + type: array + items: + type: string + format: uuid + skipped: + type: boolean + required: &ref_61 - type + user_states: + additionalProperties: true + preprocessor_module: + allOf: + - type: object + properties: *ref_60 + required: *ref_61 failure_module: allOf: - type: object - properties: *ref_52 - required: *ref_53 + properties: *ref_60 + required: *ref_61 - type: object properties: parent_module: @@ -7336,14 +8542,14 @@ paths: items: type: string format: uuid - required: &ref_66 + required: &ref_77 - step - modules - failure_module raw_flow: type: object - properties: *ref_50 - required: *ref_51 + properties: *ref_58 + required: *ref_59 is_flow_step: type: boolean language: @@ -7362,6 +8568,9 @@ paths: - graphql - nativets - bun + - php + - rust + - ansible email: type: string visible_to_owner: @@ -7372,7 +8581,13 @@ paths: type: string priority: type: integer - required: &ref_72 + self_wait_time_ms: + type: number + aggregate_wait_time_ms: + type: number + suspend: + type: number + required: &ref_82 - id - running - canceled @@ -7410,6 +8625,8 @@ paths: properties: database_length: type: integer + suspended: + type: integer required: - database_length /w/{workspace}/jobs/completed/count: @@ -7435,10 +8652,10 @@ paths: type: integer required: - database_length - /w/{workspace}/jobs/queue/cancel_all: - post: - summary: cancel all jobs - operationId: cancelAll + /w/{workspace}/jobs/queue/list_filtered_uuids: + get: + summary: get the ids of all jobs matching the given filters + operationId: listFilteredUuids tags: - job parameters: @@ -7446,6 +8663,136 @@ paths: in: path required: true schema: *ref_0 + - name: order_desc + description: order by desc order (default true) + in: query + schema: *ref_48 + - name: created_by + description: mask to filter exact matching user creator + in: query + schema: *ref_49 + - name: parent_job + description: >- + The parent job that is at the origin and responsible for the + execution of this script if any + in: query + schema: *ref_42 + - name: script_path_exact + description: mask to filter exact matching path + in: query + schema: *ref_62 + - name: script_path_start + description: mask to filter matching starting path + in: query + schema: *ref_63 + - name: schedule_path + description: mask to filter by schedule path + in: query + schema: *ref_64 + - name: script_hash + description: mask to filter exact matching path + in: query + schema: *ref_65 + - name: started_before + description: filter on started before (inclusive) timestamp + in: query + schema: *ref_66 + - name: started_after + description: filter on started after (exclusive) timestamp + in: query + schema: *ref_67 + - name: success + description: filter on successful jobs + in: query + schema: *ref_68 + - name: scheduled_for_before_now + description: filter on jobs scheduled_for before now (hence waitinf for a worker) + in: query + schema: *ref_69 + - name: job_kinds + description: >- + filter on job kind (values 'preview', 'script', 'dependencies', + 'flow') separated by, + in: query + schema: *ref_70 + - name: suspended + description: filter on suspended jobs + in: query + schema: *ref_71 + - name: running + description: filter on running jobs + in: query + schema: *ref_72 + - name: args + description: >- + filter on jobs containing those args as a json subset (@> in + postgres) + in: query + schema: *ref_73 + - name: result + description: >- + filter on jobs containing those result as a json subset (@> in + postgres) + in: query + schema: *ref_74 + - name: tag + description: filter on jobs with a given tag/worker group + in: query + schema: *ref_75 + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 + - name: concurrency_key + in: query + required: false + schema: + type: string + - name: all_workspaces + description: >- + get jobs from all workspaces (only valid if request come from the + `admins` workspace) + in: query + schema: + type: boolean + - name: is_not_schedule + description: is not a scheduled job + in: query + schema: + type: boolean + responses: + '200': + description: uuids of jobs + content: + application/json: + schema: + type: array + items: + type: string + /w/{workspace}/jobs/queue/cancel_selection: + post: + summary: cancel jobs based on the given uuids + operationId: cancelSelection + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: uuids of the jobs to cancel + required: true + content: + application/json: + schema: + type: array + items: + type: string responses: '200': description: uuids of canceled jobs @@ -7469,67 +8816,83 @@ paths: - name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 + - name: label + description: >- + mask to filter exact matching job's label (job labels are completed + jobs with as a result an object containing a string in the array at + key 'wm_labels') + in: query + schema: &ref_78 + type: string - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: script_path_exact description: mask to filter exact matching path in: query - schema: *ref_54 + schema: *ref_62 - name: script_path_start description: mask to filter matching starting path in: query - schema: *ref_55 + schema: *ref_63 - name: schedule_path description: mask to filter by schedule path in: query - schema: *ref_56 + schema: *ref_64 - name: script_hash description: mask to filter exact matching path in: query - schema: *ref_57 + schema: *ref_65 - name: started_before description: filter on started before (inclusive) timestamp in: query - schema: *ref_58 + schema: *ref_66 - name: started_after description: filter on started after (exclusive) timestamp in: query - schema: *ref_59 + schema: *ref_67 - name: success description: filter on successful jobs in: query - schema: *ref_60 + schema: *ref_68 - name: job_kinds description: >- filter on job kind (values 'preview', 'script', 'dependencies', 'flow') separated by, in: query - schema: *ref_61 + schema: *ref_70 - name: args description: >- filter on jobs containing those args as a json subset (@> in postgres) in: query - schema: *ref_62 + schema: *ref_73 - name: result description: >- filter on jobs containing those result as a json subset (@> in postgres) in: query - schema: *ref_63 + schema: *ref_74 - name: tag description: filter on jobs with a given tag/worker group in: query - schema: *ref_64 + schema: *ref_75 + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 - name: is_skipped description: is the job skipped in: query @@ -7540,6 +8903,16 @@ paths: in: query schema: type: boolean + - name: has_null_parent + description: has null parent + in: query + schema: + type: boolean + - name: is_not_schedule + description: is not a scheduled job + in: query + schema: + type: boolean responses: '200': description: All completed jobs @@ -7549,7 +8922,7 @@ paths: type: array items: type: object - properties: &ref_69 + properties: &ref_79 workspace_id: type: string id: @@ -7576,7 +8949,7 @@ paths: type: string args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 result: {} logs: type: string @@ -7615,12 +8988,12 @@ paths: by extension its DT_TOKEN. flow_status: type: object - properties: *ref_65 - required: *ref_66 + properties: *ref_76 + required: *ref_77 raw_flow: type: object - properties: *ref_50 - required: *ref_51 + properties: *ref_58 + required: *ref_59 is_flow_step: type: boolean language: @@ -7639,6 +9012,9 @@ paths: - graphql - nativets - bun + - php + - rust + - ansible is_skipped: type: boolean email: @@ -7651,7 +9027,15 @@ paths: type: string priority: type: integer - required: &ref_70 + labels: + type: array + items: + type: string + self_wait_time_ms: + type: number + aggregate_wait_time_ms: + type: number + required: &ref_80 - id - created_by - duration_ms @@ -7680,59 +9064,87 @@ paths: - name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 + - name: label + description: >- + mask to filter exact matching job's label (job labels are completed + jobs with as a result an object containing a string in the array at + key 'wm_labels') + in: query + schema: *ref_78 - name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 - name: script_path_exact description: mask to filter exact matching path in: query - schema: *ref_54 + schema: *ref_62 - name: script_path_start description: mask to filter matching starting path in: query - schema: *ref_55 + schema: *ref_63 - name: schedule_path description: mask to filter by schedule path in: query - schema: *ref_56 + schema: *ref_64 - name: script_hash description: mask to filter exact matching path in: query - schema: *ref_57 + schema: *ref_65 - name: started_before description: filter on started before (inclusive) timestamp in: query - schema: *ref_58 + schema: *ref_66 - name: started_after description: filter on started after (exclusive) timestamp in: query - schema: *ref_59 + schema: *ref_67 + - name: created_before + description: filter on created before (inclusive) timestamp + in: query + schema: &ref_117 + type: string + format: date-time + - name: created_after + description: filter on created after (exclusive) timestamp + in: query + schema: &ref_118 + type: string + format: date-time - name: created_or_started_before description: >- filter on created_at for non non started job and started_at otherwise before (inclusive) timestamp in: query - schema: &ref_99 + schema: &ref_111 type: string format: date-time - name: running description: filter on running jobs in: query - schema: *ref_67 + schema: *ref_72 - name: scheduled_for_before_now description: filter on jobs scheduled_for before now (hence waitinf for a worker) in: query - schema: *ref_68 + schema: *ref_69 - name: created_or_started_after description: >- filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp in: query - schema: &ref_98 + schema: &ref_112 + type: string + format: date-time + - name: created_or_started_after_completed_jobs + description: >- + filter on created_at for non non started job and started_at + otherwise after (exclusive) timestamp but only for the completed + jobs + in: query + schema: &ref_113 type: string format: date-time - name: job_kinds @@ -7740,23 +9152,35 @@ paths: filter on job kind (values 'preview', 'script', 'dependencies', 'flow') separated by, in: query - schema: *ref_61 + schema: *ref_70 + - name: suspended + description: filter on suspended jobs + in: query + schema: *ref_71 - name: args description: >- filter on jobs containing those args as a json subset (@> in postgres) in: query - schema: *ref_62 + schema: *ref_73 - name: tag description: filter on jobs with a given tag/worker group in: query - schema: *ref_64 + schema: *ref_75 - name: result description: >- filter on jobs containing those result as a json subset (@> in postgres) in: query - schema: *ref_63 + schema: *ref_74 + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 - name: is_skipped description: is the job skipped in: query @@ -7767,6 +9191,11 @@ paths: in: query schema: type: boolean + - name: has_null_parent + description: has null parent + in: query + schema: + type: boolean - name: success description: filter on successful jobs in: query @@ -7779,6 +9208,11 @@ paths: in: query schema: type: boolean + - name: is_not_schedule + description: is not a scheduled job + in: query + schema: + type: boolean responses: '200': description: All jobs @@ -7787,22 +9221,28 @@ paths: schema: type: array items: - allOf: &ref_74 - - oneOf: + oneOf: &ref_84 + - allOf: - type: object - properties: *ref_69 - required: *ref_70 + properties: *ref_79 + required: *ref_80 - type: object - properties: *ref_71 - required: *ref_72 - - type: object - properties: - type: - type: string - enum: - - CompletedJob - - QueuedJob - discriminator: &ref_75 + properties: + type: + type: string + enum: + - CompletedJob + - allOf: + - type: object + properties: *ref_81 + required: *ref_82 + - type: object + properties: + type: + type: string + enum: + - QueuedJob + discriminator: &ref_85 propertyName: type /jobs/db_clock: get: @@ -7817,6 +9257,44 @@ paths: application/json: schema: type: integer + /jobs/completed/count_by_tag: + get: + summary: Count jobs by tag + operationId: countJobsByTag + tags: + - job + parameters: + - name: horizon_secs + in: query + description: >- + Past Time horizon in seconds (when to start the count = now - + horizon) (default is 3600) + required: false + schema: + type: integer + - name: workspace_id + in: query + description: Specific workspace ID to filter results (optional) + required: false + schema: + type: string + responses: + '200': + description: Job counts by tag + content: + application/json: + schema: + type: array + items: + type: object + properties: + tag: + type: string + count: + type: integer + required: + - tag + - count /w/{workspace}/jobs_u/get/{id}: get: summary: get job @@ -7831,15 +9309,19 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 + - name: no_logs + in: query + schema: + type: boolean responses: '200': description: job details content: application/json: schema: - allOf: *ref_74 - discriminator: *ref_75 + oneOf: *ref_84 + discriminator: *ref_85 /w/{workspace}/jobs_u/get_root_job_id/{id}: get: summary: get root job id @@ -7854,7 +9336,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 responses: '200': description: get root job id @@ -7876,7 +9358,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 responses: '200': description: job details @@ -7884,6 +9366,27 @@ paths: text/plain: schema: type: string + /w/{workspace}/jobs_u/get_args/{id}: + get: + summary: get job args + operationId: getJobArgs + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_83 + responses: + '200': + description: job args + content: + application/json: + schema: {} /w/{workspace}/jobs_u/getupdate/{id}: get: summary: get job updates @@ -7898,7 +9401,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: running in: query schema: @@ -7907,6 +9410,10 @@ paths: in: query schema: type: integer + - name: get_progress + in: query + schema: + type: boolean responses: '200': description: job details @@ -7921,8 +9428,49 @@ paths: type: boolean new_logs: type: string + log_offset: + type: integer mem_peak: type: integer + progress: + type: integer + flow_status: + type: object + additionalProperties: &ref_151 + type: object + properties: &ref_152 + scheduled_for: + type: string + format: date-time + started_at: + type: string + format: date-time + duration_ms: + type: number + name: + type: string + /w/{workspace}/jobs_u/get_log_file/{path}: + get: + summary: get log file from object store + operationId: getLogFileFromStore + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: + type: string + responses: + '200': + description: job log + content: + text/plain: + type: string /w/{workspace}/jobs_u/get_flow_debug_info/{id}: get: summary: get flow debug info @@ -7937,7 +9485,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 responses: '200': description: flow debug info details @@ -7958,7 +9506,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 responses: '200': description: job details @@ -7966,8 +9514,8 @@ paths: application/json: schema: type: object - properties: *ref_69 - required: *ref_70 + properties: *ref_79 + required: *ref_80 /w/{workspace}/jobs_u/completed/get_result/{id}: get: summary: get completed job result @@ -7982,7 +9530,23 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 + - name: suspended_job + in: query + schema: + type: string + - name: resume_id + in: query + schema: + type: integer + - name: secret + in: query + schema: + type: string + - name: approver + in: query + schema: + type: string responses: '200': description: result @@ -8003,10 +9567,10 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: get_started in: query - schema: &ref_108 + schema: &ref_124 type: boolean responses: '200': @@ -8040,7 +9604,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 responses: '200': description: job details @@ -8048,11 +9612,11 @@ paths: application/json: schema: type: object - properties: *ref_69 - required: *ref_70 + properties: *ref_79 + required: *ref_80 /w/{workspace}/jobs_u/queue/cancel/{id}: post: - summary: cancel queued job + summary: cancel queued or running job operationId: cancelQueuedJob tags: - job @@ -8064,7 +9628,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 requestBody: description: reason required: true @@ -8096,7 +9660,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: reason required: true @@ -8128,7 +9692,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 requestBody: description: reason required: true @@ -8160,7 +9724,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8191,7 +9755,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8233,7 +9797,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: payload description: > The base64 encoded payload that has been encoded as a JSON. e.g how @@ -8241,7 +9805,7 @@ paths: `encodeURIComponent(btoa(JSON.stringify({a: 2})))` in: query - schema: *ref_76 + schema: *ref_86 - name: resume_id in: path required: true @@ -8276,7 +9840,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8304,6 +9868,64 @@ paths: text/plain: schema: type: string + /w/{workspace}/jobs/flow/user_states/{id}/{key}: + post: + summary: set flow user state at a given key + operationId: setFlowUserState + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_83 + - name: key + in: path + required: true + schema: + type: string + requestBody: + description: new value + required: true + content: + application/json: + schema: {} + responses: + '200': + description: flow user state updated + content: + text/plain: + schema: + type: string + get: + summary: get flow user state at a given key + operationId: getFlowUserState + tags: + - job + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_83 + - name: key + in: path + required: true + schema: + type: string + responses: + '200': + description: flow user state updated + content: + application/json: + schema: {} /w/{workspace}/jobs/flow/resume/{id}: post: summary: resume a job for a suspended flow as an owner @@ -8318,7 +9940,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 requestBody: required: true content: @@ -8346,7 +9968,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8381,7 +10003,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8423,7 +10045,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 - name: resume_id in: path required: true @@ -8447,8 +10069,8 @@ paths: type: object properties: job: - allOf: *ref_74 - discriminator: *ref_75 + oneOf: *ref_84 + discriminator: *ref_85 approvers: type: array items: @@ -8513,7 +10135,7 @@ paths: application/json: schema: type: object - properties: &ref_145 + properties: &ref_162 path: type: string schedule: @@ -8526,7 +10148,7 @@ paths: type: boolean args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 enabled: type: boolean on_failure: @@ -8537,26 +10159,34 @@ paths: type: boolean on_failure_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 on_recovery: type: string on_recovery_times: type: number on_recovery_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 + on_success: + type: string + on_success_extra_args: + type: object + additionalProperties: *ref_16 ws_error_handler_muted: type: boolean retry: type: object - properties: *ref_77 + properties: *ref_87 no_flow_overlap: type: boolean summary: type: string tag: type: string - required: &ref_146 + paused_until: + type: string + format: date-time + required: &ref_163 - path - schedule - timezone @@ -8584,7 +10214,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: updated schedule required: true @@ -8592,14 +10222,14 @@ paths: application/json: schema: type: object - properties: &ref_147 + properties: &ref_164 schedule: type: string timezone: type: string args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 on_failure: type: string on_failure_times: @@ -8608,26 +10238,34 @@ paths: type: boolean on_failure_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 on_recovery: type: string on_recovery_times: type: number on_recovery_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 + on_success: + type: string + on_success_extra_args: + type: object + additionalProperties: *ref_16 ws_error_handler_muted: type: boolean retry: type: object - properties: *ref_77 + properties: *ref_87 no_flow_overlap: type: boolean summary: type: string tag: type: string - required: &ref_148 + paused_until: + type: string + format: date-time + required: &ref_165 - schedule - timezone - script_path @@ -8654,7 +10292,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 requestBody: description: updated schedule enable required: true @@ -8688,7 +10326,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: schedule deleted @@ -8710,7 +10348,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: schedule deleted @@ -8718,7 +10356,7 @@ paths: application/json: schema: type: object - properties: &ref_78 + properties: &ref_88 path: type: string edited_by: @@ -8738,7 +10376,7 @@ paths: type: boolean args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 extra_perms: type: object additionalProperties: @@ -8755,26 +10393,34 @@ paths: type: boolean on_failure_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 on_recovery: type: string on_recovery_times: type: number on_recovery_extra_args: type: object - additionalProperties: *ref_14 + additionalProperties: *ref_16 + on_success: + type: string + on_success_extra_args: + type: object + additionalProperties: *ref_16 ws_error_handler_muted: type: boolean retry: type: object - properties: *ref_77 + properties: *ref_87 summary: type: string no_flow_overlap: type: boolean tag: type: string - required: &ref_79 + paused_until: + type: string + format: date-time + required: &ref_89 - path - edited_by - edited_at @@ -8799,7 +10445,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: schedule exists @@ -8821,11 +10467,17 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 + - name: args + description: >- + filter on jobs containing those args as a json subset (@> in + postgres) + in: query + schema: *ref_73 - name: path description: filter by path in: query @@ -8835,6 +10487,10 @@ paths: in: query schema: type: boolean + - name: path_start + in: query + schema: + type: string responses: '200': description: schedule list @@ -8844,8 +10500,8 @@ paths: type: array items: type: object - properties: *ref_78 - required: *ref_79 + properties: *ref_88 + required: *ref_89 /w/{workspace}/schedules/list_with_jobs: get: summary: list schedules with last 20 jobs @@ -8860,11 +10516,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: schedule list @@ -8873,10 +10529,10 @@ paths: schema: type: array items: - allOf: &ref_144 + allOf: &ref_161 - type: object - properties: *ref_78 - required: *ref_79 + properties: *ref_88 + required: *ref_89 - type: object properties: jobs: @@ -8918,6 +10574,7 @@ paths: enum: - error - recovery + - success override_existing: type: boolean path: @@ -8936,6 +10593,332 @@ paths: responses: '201': description: default error handler set + /w/{workspace}/http_triggers/create: + post: + summary: create http trigger + operationId: createHttpTrigger + tags: + - http_trigger + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: new http trigger + required: true + content: + application/json: + schema: + type: object + properties: &ref_166 + 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: &ref_167 + - path + - script_path + - route_path + - is_flow + - is_async + - requires_auth + - http_method + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + requestBody: + description: updated trigger + required: true + content: + application/json: + schema: + type: object + properties: &ref_168 + 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: &ref_169 + - path + - script_path + - is_flow + - kind + - is_async + - requires_auth + - http_method + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + responses: + '200': + description: http trigger deleted + content: + application/json: + schema: + type: object + properties: &ref_90 + 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: &ref_91 + - path + - edited_by + - edited_at + - script_path + - route_path + - extra_perms + - is_flow + - email + - workspace_id + - is_async + - requires_auth + - http_method + /w/{workspace}/http_triggers/list: + get: + summary: list http triggers + operationId: listHttpTriggers + tags: + - http_trigger + parameters: + - required: true + name: workspace + in: path + schema: *ref_0 + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 + - 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: + type: object + properties: *ref_90 + required: *ref_91 + /w/{workspace}/http_triggers/exists/{path}: + get: + summary: does http trigger exists + operationId: existsHttpTrigger + tags: + - http_trigger + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: whether http triggers are used + content: + application/json: + schema: + type: boolean /groups/list: get: summary: list instance groups @@ -8951,7 +10934,7 @@ paths: type: array items: type: object - properties: &ref_81 + properties: &ref_93 name: type: string summary: @@ -8960,7 +10943,7 @@ paths: type: array items: type: string - required: &ref_82 + required: &ref_94 - name /groups/get/{name}: get: @@ -8972,7 +10955,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: instance group @@ -8980,8 +10963,8 @@ paths: application/json: schema: type: object - properties: *ref_81 - required: *ref_82 + properties: *ref_93 + required: *ref_94 /groups/create: post: summary: create instance group @@ -9019,7 +11002,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: update instance group required: true @@ -9049,7 +11032,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: instance group deleted @@ -9067,7 +11050,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: user to add to instance group required: true @@ -9097,7 +11080,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: user to remove from instance group required: true @@ -9117,6 +11100,62 @@ paths: text/plain: schema: type: string + /groups/export: + get: + summary: export instance groups + operationId: exportInstanceGroups + tags: + - group + responses: + '200': + description: exported instance groups + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_95 + name: + type: string + summary: + type: string + emails: + type: array + items: + type: string + id: + type: string + scim_display_name: + type: string + external_id: + type: string + required: &ref_96 + - name + /groups/overwrite: + post: + summary: overwrite instance groups + operationId: overwriteInstanceGroups + tags: + - group + requestBody: + description: overwrite instance groups + required: true + content: + application/json: + schema: + type: array + items: + type: object + properties: *ref_95 + required: *ref_96 + responses: + '200': + description: success message + content: + text/plain: + schema: + type: string /w/{workspace}/groups/list: get: summary: list groups @@ -9131,11 +11170,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: group list @@ -9145,7 +11184,7 @@ paths: type: array items: type: object - properties: &ref_83 + properties: &ref_97 name: type: string summary: @@ -9158,7 +11197,7 @@ paths: type: object additionalProperties: type: boolean - required: &ref_84 + required: &ref_98 - name /w/{workspace}/groups/listnames: get: @@ -9231,7 +11270,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: updated group required: true @@ -9263,7 +11302,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: group deleted @@ -9285,7 +11324,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: group @@ -9293,8 +11332,8 @@ paths: application/json: schema: type: object - properties: *ref_83 - required: *ref_84 + properties: *ref_97 + required: *ref_98 /w/{workspace}/groups/adduser/{name}: post: summary: add user to group @@ -9309,7 +11348,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: added user to group required: true @@ -9341,7 +11380,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: added user to group required: true @@ -9373,11 +11412,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: folder list @@ -9387,7 +11426,7 @@ paths: type: array items: type: object - properties: &ref_85 + properties: &ref_99 name: type: string owners: @@ -9398,7 +11437,14 @@ paths: type: object additionalProperties: type: boolean - required: &ref_86 + summary: + type: string + created_by: + type: string + edited_at: + type: string + format: date-time + required: &ref_100 - name - owners - extra_perms @@ -9448,6 +11494,8 @@ paths: properties: name: type: string + summary: + type: string owners: type: array items: @@ -9478,7 +11526,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: update folder required: true @@ -9487,6 +11535,8 @@ paths: schema: type: object properties: + summary: + type: string owners: type: array items: @@ -9515,7 +11565,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: folder deleted @@ -9537,7 +11587,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: folder @@ -9545,8 +11595,8 @@ paths: application/json: schema: type: object - properties: *ref_85 - required: *ref_86 + properties: *ref_99 + required: *ref_100 /w/{workspace}/folders/getusage/{name}: get: summary: get folder usage @@ -9561,7 +11611,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: folder @@ -9603,7 +11653,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: owner user to folder required: true @@ -9614,6 +11664,8 @@ paths: properties: owner: type: string + required: + - owner responses: '200': description: owner added to folder @@ -9635,7 +11687,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: added owner to folder required: true @@ -9646,6 +11698,10 @@ paths: properties: owner: type: string + write: + type: boolean + required: + - owner responses: '200': description: owner removed from folder @@ -9663,11 +11719,11 @@ paths: - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 - name: ping_since in: query required: false @@ -9685,7 +11741,7 @@ paths: type: array items: type: object - properties: &ref_149 + properties: &ref_170 worker: type: string worker_instance: @@ -9707,7 +11763,27 @@ paths: type: string wm_version: type: string - required: &ref_150 + last_job_id: + type: string + last_job_workspace_id: + type: string + occupancy_rate: + type: number + occupancy_rate_15s: + type: number + occupancy_rate_5m: + type: number + occupancy_rate_30m: + type: number + memory: + type: number + vcpus: + type: number + memory_usage: + type: number + wm_memory_usage: + type: number + required: &ref_171 - worker - worker_instance - ping_at @@ -9735,6 +11811,39 @@ paths: application/json: schema: type: boolean + /workers/queue_metrics: + get: + summary: get queue metrics + operationId: getQueueMetrics + tags: + - worker + responses: + '200': + description: metrics + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + values: + type: array + items: + type: object + properties: + created_at: + type: string + value: + type: number + required: + - created_at + - value + required: + - id + - values /configs/list_worker_groups: get: summary: list worker groups @@ -9767,7 +11876,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: a config @@ -9784,7 +11893,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 requestBody: description: worker group required: true @@ -9807,7 +11916,7 @@ paths: - name: name in: path required: true - schema: *ref_80 + schema: *ref_92 responses: '200': description: Delete config @@ -9815,6 +11924,28 @@ paths: text/plain: schema: type: string + /configs/list: + get: + summary: list configs + operationId: listConfigs + tags: + - config + responses: + '200': + description: list of configs + content: + application/json: + schema: + type: array + items: + type: object + properties: &ref_216 + name: + type: string + config: + type: object + required: &ref_217 + - name /w/{workspace}/acls/get/{kind}/{path}: get: summary: get granular acls @@ -9829,7 +11960,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: kind in: path required: true @@ -9845,6 +11976,7 @@ paths: - folder - app - raw_app + - http_trigger responses: '200': description: acls @@ -9868,7 +12000,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: kind in: path required: true @@ -9884,6 +12016,7 @@ paths: - folder - app - raw_app + - http_trigger requestBody: description: acl to add required: true @@ -9919,7 +12052,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: kind in: path required: true @@ -9935,6 +12068,7 @@ paths: - folder - app - raw_app + - http_trigger requestBody: description: acl to add required: true @@ -9968,7 +12102,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '204': description: flow preview captured @@ -9986,7 +12120,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '201': description: flow preview capture created @@ -10003,7 +12137,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 responses: '200': description: captured flow preview @@ -10083,24 +12217,24 @@ paths: schema: *ref_0 - name: runnable_id in: query - schema: &ref_89 + schema: &ref_101 type: string - name: runnable_type in: query - schema: &ref_90 + schema: &ref_102 type: string - enum: &ref_117 + enum: &ref_133 - ScriptHash - ScriptPath - FlowPath - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: Input history for completed jobs @@ -10110,8 +12244,57 @@ paths: type: array items: type: object - properties: *ref_87 - required: *ref_88 + properties: &ref_103 + id: + type: string + name: + type: string + created_by: + type: string + created_at: + type: string + format: date-time + is_public: + type: boolean + success: + type: boolean + required: &ref_104 + - id + - name + - args + - created_by + - created_at + - is_public + /w/{workspace}/inputs/{jobOrInputId}/args: + get: + summary: Get args from history or saved input + operationId: getArgsFromHistoryOrSavedInput + tags: + - input + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: jobOrInputId + in: path + required: true + schema: + type: string + - name: input + in: query + schema: + type: boolean + - name: allow_large + in: query + schema: + type: boolean + responses: + '200': + description: args + content: + application/json: + schema: {} /w/{workspace}/inputs/list: get: summary: List saved Inputs for a Runnable @@ -10125,18 +12308,18 @@ paths: schema: *ref_0 - name: runnable_id in: query - schema: *ref_89 + schema: *ref_101 - name: runnable_type in: query - schema: *ref_90 + schema: *ref_102 - name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 - name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 responses: '200': description: Saved Inputs for a Runnable @@ -10146,8 +12329,8 @@ paths: type: array items: type: object - properties: *ref_87 - required: *ref_88 + properties: *ref_103 + required: *ref_104 /w/{workspace}/inputs/create: post: summary: Create an Input for future use in a script or flow @@ -10161,10 +12344,10 @@ paths: schema: *ref_0 - name: runnable_id in: query - schema: *ref_89 + schema: *ref_101 - name: runnable_type in: query - schema: *ref_90 + schema: *ref_102 requestBody: description: Input required: true @@ -10172,12 +12355,12 @@ paths: application/json: schema: type: object - properties: &ref_113 + properties: &ref_129 name: type: string args: type: object - required: &ref_114 + required: &ref_130 - name - args - created_by @@ -10207,14 +12390,14 @@ paths: application/json: schema: type: object - properties: &ref_115 + properties: &ref_131 id: type: string name: type: string is_public: type: boolean - required: &ref_116 + required: &ref_132 - id - name - is_public @@ -10240,7 +12423,7 @@ paths: - name: input in: path required: true - schema: &ref_107 + schema: &ref_123 type: string responses: '200': @@ -10273,7 +12456,7 @@ paths: properties: s3_resource: type: object - properties: &ref_91 + properties: &ref_105 bucket: type: string region: @@ -10288,7 +12471,7 @@ paths: type: string pathStyle: type: boolean - required: &ref_92 + required: &ref_106 - bucket - region - endPoint @@ -10364,8 +12547,8 @@ paths: properties: s3_resource: type: object - properties: *ref_91 - required: *ref_92 + properties: *ref_105 + required: *ref_106 responses: '200': description: Connection settings @@ -10386,10 +12569,10 @@ paths: type: boolean client_kwargs: type: object - properties: &ref_93 + properties: &ref_107 region_name: type: string - required: &ref_94 + required: &ref_108 - region_name required: - endpoint_url @@ -10444,8 +12627,8 @@ paths: type: boolean client_kwargs: type: object - properties: *ref_93 - required: *ref_94 + properties: *ref_107 + required: *ref_108 required: - endpoint_url - use_ssl @@ -10503,11 +12686,11 @@ paths: application/json: schema: type: object - properties: *ref_91 - required: *ref_92 + properties: *ref_105 + required: *ref_106 /w/{workspace}/job_helpers/test_connection: get: - summary: Test connection to the workspace datasets storage + summary: Test connection to the workspace object storage operationId: datasetStorageTestConnection tags: - helpers @@ -10516,6 +12699,10 @@ paths: in: path required: true schema: *ref_0 + - name: storage + in: query + schema: + type: string responses: '200': description: Connection settings @@ -10524,7 +12711,7 @@ paths: schema: {} /w/{workspace}/job_helpers/list_stored_files: get: - summary: List the file keys available in the workspace files storage (S3) + summary: List the file keys available in a workspace object storage operationId: listStoredFiles tags: - helpers @@ -10546,6 +12733,10 @@ paths: in: query schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: List of file keys @@ -10560,10 +12751,10 @@ paths: type: array items: type: object - properties: &ref_169 + properties: &ref_193 s3: type: string - required: &ref_170 + required: &ref_194 - s3 restricted_access: type: boolean @@ -10585,6 +12776,10 @@ paths: required: true schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: FileMetadata @@ -10592,7 +12787,7 @@ paths: application/json: schema: type: object - properties: &ref_171 + properties: &ref_195 mime_type: type: string size_in_bytes: @@ -10645,6 +12840,10 @@ paths: in: query schema: type: integer + - name: storage + in: query + schema: + type: string responses: '200': description: FilePreview @@ -10652,7 +12851,7 @@ paths: application/json: schema: type: object - properties: &ref_172 + properties: &ref_196 msg: type: string content: @@ -10664,7 +12863,7 @@ paths: - Csv - Parquet - Unknown - required: &ref_173 + required: &ref_197 - content_type /w/{workspace}/job_helpers/load_parquet_preview/{path}: get: @@ -10680,7 +12879,7 @@ paths: - name: path in: path required: true - schema: *ref_17 + schema: *ref_21 - name: offset in: query schema: @@ -10705,12 +12904,106 @@ paths: in: query schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: Parquet Preview content: application/json: schema: {} + /w/{workspace}/job_helpers/load_table_count/{path}: + get: + summary: Load the table row count + operationId: loadTableRowCount + tags: + - helpers + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + - 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 + operationId: loadCsvPreview + tags: + - helpers + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: path + in: path + required: true + schema: *ref_21 + - name: offset + in: query + schema: + type: number + - name: limit + in: query + schema: + type: number + - name: sort_col + in: query + schema: + type: string + - name: sort_desc + in: query + schema: + type: boolean + - name: search_col + in: query + schema: + type: string + - name: search_term + in: query + schema: + type: string + - name: storage + in: query + schema: + type: string + - name: csv_separator + in: query + schema: + type: string + responses: + '200': + description: Csv Preview + content: + application/json: + schema: {} /w/{workspace}/job_helpers/delete_s3_file: delete: summary: Permanently delete file from S3 @@ -10727,6 +13020,10 @@ paths: required: true schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: Confirmation @@ -10754,6 +13051,10 @@ paths: required: true schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: Confirmation @@ -10791,6 +13092,10 @@ paths: required: false schema: type: string + - name: storage + in: query + schema: + type: string requestBody: description: File content required: true @@ -10837,6 +13142,10 @@ paths: required: false schema: type: string + - name: storage + in: query + schema: + type: string responses: '200': description: Chunk of the downloaded file @@ -10845,6 +13154,39 @@ paths: schema: type: string format: binary + /w/{workspace}/job_helpers/download_s3_parquet_file_as_csv: + get: + summary: Download file to S3 bucket + operationId: fileDownloadParquetAsCsv + tags: + - helpers + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: file_key + in: query + required: true + schema: + type: string + - name: s3_resource_path + in: query + required: false + schema: + type: string + - name: resource_type + in: query + required: false + schema: + type: string + responses: + '200': + description: The downloaded file + content: + text/csv: + schema: + type: string /w/{workspace}/job_metrics/get/{id}: post: summary: get job metrics @@ -10859,7 +13201,7 @@ paths: - name: id in: path required: true - schema: *ref_73 + schema: *ref_83 requestBody: description: parameters for statistics retrieval required: true @@ -10888,48 +13230,175 @@ paths: type: array items: type: object - properties: &ref_176 + properties: &ref_200 id: type: string name: type: string - required: &ref_177 + required: &ref_201 - id scalar_metrics: type: array items: type: object - properties: &ref_178 + properties: &ref_202 metric_id: type: string value: type: number - required: &ref_179 + required: &ref_203 - id - value timeseries_metrics: type: array items: type: object - properties: &ref_180 + properties: &ref_204 metric_id: type: string values: type: array items: type: object - properties: &ref_182 + properties: &ref_206 timestamp: type: string format: date-time value: type: number - required: &ref_183 + required: &ref_207 - timestamp - value - required: &ref_181 + required: &ref_205 - id - values + /w/{workspace}/job_metrics/set_progress/{id}: + post: + summary: set job metrics + operationId: setJobProgress + tags: + - metrics + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_83 + 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: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: id + in: path + required: true + schema: *ref_83 + 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 + operationId: listLogFiles + tags: + - service_logs + parameters: + - name: before + description: filter on started before (inclusive) timestamp + in: query + schema: *ref_109 + - name: after + description: filter on created after (exclusive) timestamp + in: query + schema: *ref_110 + - name: with_error + in: query + required: false + schema: + type: boolean + responses: + '200': + description: time + content: + application/json: + schema: + type: array + items: + type: object + properties: + hostname: + type: string + mode: + type: string + worker_group: + type: string + log_ts: + type: string + format: date-time + file_path: + type: string + ok_lines: + type: integer + err_lines: + type: integer + json_fmt: + type: boolean + required: + - hostname + - mode + - log_ts + - file_path + - json_fmt + /service_logs/get_log_file/{path}: + get: + summary: get log file by path + operationId: getLogFile + tags: + - service_logs + parameters: + - name: path + in: path + required: true + schema: *ref_21 + responses: + '200': + description: log stream + content: + text/plain: + schema: + type: string /concurrency_groups/list: get: summary: List all concurrency groups @@ -10945,17 +13414,15 @@ paths: type: array items: type: object - properties: &ref_186 - concurrency_id: + properties: &ref_210 + concurrency_key: type: string - job_uuids: - type: array - items: - type: string - required: &ref_187 - - concurrency_id - - job_uuids - /concurrency_groups/{concurrency_id}: + total_running: + type: number + required: &ref_211 + - concurrency_key + - total_running + /concurrency_groups/prune/{concurrency_id}: delete: summary: Delete concurrency group operationId: deleteConcurrencyGroup @@ -10965,7 +13432,7 @@ paths: - name: concurrency_id in: path required: true - schema: &ref_109 + schema: &ref_125 type: string responses: '200': @@ -10975,6 +13442,251 @@ paths: schema: type: object properties: {} + /concurrency_groups/{id}/key: + get: + summary: Get the concurrency key for a job that has concurrency limits enabled + operationId: getConcurrencyKey + tags: + - concurrencyGroups + parameters: + - name: id + in: path + required: true + schema: *ref_83 + responses: + '200': + description: concurrency key for given job + content: + application/json: + schema: + type: string + /w/{workspace}/concurrency_groups/list_jobs: + get: + summary: Get intervals of job runtime concurrency + operationId: listExtendedJobs + tags: + - concurrencyGroups + - job + parameters: + - name: concurrency_key + in: query + required: false + schema: + type: string + - name: row_limit + in: query + required: false + schema: + type: number + - name: workspace + in: path + required: true + schema: *ref_0 + - name: created_by + description: mask to filter exact matching user creator + in: query + schema: *ref_49 + - name: label + description: >- + mask to filter exact matching job's label (job labels are completed + jobs with as a result an object containing a string in the array at + key 'wm_labels') + in: query + schema: *ref_78 + - name: parent_job + description: >- + The parent job that is at the origin and responsible for the + execution of this script if any + in: query + schema: *ref_42 + - name: script_path_exact + description: mask to filter exact matching path + in: query + schema: *ref_62 + - name: script_path_start + description: mask to filter matching starting path + in: query + schema: *ref_63 + - name: schedule_path + description: mask to filter by schedule path + in: query + schema: *ref_64 + - name: script_hash + description: mask to filter exact matching path + in: query + schema: *ref_65 + - name: started_before + description: filter on started before (inclusive) timestamp + in: query + schema: *ref_66 + - name: started_after + description: filter on started after (exclusive) timestamp + in: query + schema: *ref_67 + - name: created_or_started_before + description: >- + filter on created_at for non non started job and started_at + otherwise before (inclusive) timestamp + in: query + schema: *ref_111 + - name: running + description: filter on running jobs + in: query + schema: *ref_72 + - name: scheduled_for_before_now + description: filter on jobs scheduled_for before now (hence waitinf for a worker) + in: query + schema: *ref_69 + - name: created_or_started_after + description: >- + filter on created_at for non non started job and started_at + otherwise after (exclusive) timestamp + in: query + schema: *ref_112 + - name: created_or_started_after_completed_jobs + description: >- + filter on created_at for non non started job and started_at + otherwise after (exclusive) timestamp but only for the completed + jobs + in: query + schema: *ref_113 + - name: job_kinds + description: >- + filter on job kind (values 'preview', 'script', 'dependencies', + 'flow') separated by, + in: query + schema: *ref_70 + - name: args + description: >- + filter on jobs containing those args as a json subset (@> in + postgres) + in: query + schema: *ref_73 + - name: tag + description: filter on jobs with a given tag/worker group + in: query + schema: *ref_75 + - name: result + description: >- + filter on jobs containing those result as a json subset (@> in + postgres) + in: query + schema: *ref_74 + - name: page + description: which page to return (start at 1, default 1) + in: query + schema: *ref_5 + - name: per_page + description: number of items to return for a given page (default 30, max 100) + in: query + schema: *ref_6 + - name: is_skipped + description: is the job skipped + in: query + schema: + type: boolean + - name: is_flow_step + description: is the job a flow step + in: query + schema: + type: boolean + - name: has_null_parent + description: has null parent + in: query + schema: + type: boolean + - name: success + description: filter on successful jobs + in: query + schema: + type: boolean + - name: all_workspaces + description: >- + get jobs from all workspaces (only valid if request come from the + `admins` workspace) + in: query + schema: + type: boolean + - name: is_not_schedule + description: is not a scheduled job + in: query + schema: + type: boolean + responses: + '200': + description: time + content: + application/json: + schema: + type: object + properties: &ref_212 + jobs: + type: array + items: + oneOf: *ref_84 + discriminator: *ref_85 + obscured_jobs: + type: array + items: + type: object + properties: &ref_134 + typ: + type: string + started_at: + type: string + format: date-time + duration_ms: + type: number + omitted_obscured_jobs: + description: >- + Obscured jobs omitted for security because of too specific + filtering + type: boolean + required: &ref_213 + - jobs + - obscured_jobs + /srch/w/{workspace}/index/search/job: + get: + summary: Search through jobs with a string query + operationId: searchJobsIndex + tags: + - indexSearch + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + - name: search_query + in: query + required: true + schema: + type: string + responses: + '200': + description: search results + content: + application/json: + schema: + type: object + properties: + query_parse_errors: + description: >- + a list of the terms that couldn't be parsed (and thus + ignored) + type: array + items: + type: object + properties: + dancer: + type: string + hits: + description: the jobs that matched the query + type: array + items: + type: object + properties: &ref_218 + dancer: + type: string components: securitySchemes: bearerAuth: @@ -10989,7 +13701,7 @@ components: name: key in: path required: true - schema: *ref_7 + schema: *ref_9 WorkspaceId: name: workspace in: path @@ -10999,89 +13711,104 @@ components: name: version in: path required: true - schema: *ref_95 + schema: *ref_114 Token: name: token in: path required: true - schema: *ref_96 + schema: *ref_115 AccountId: name: id in: path required: true - schema: *ref_21 + schema: *ref_25 ClientName: name: client_name in: path required: true - schema: *ref_20 + schema: *ref_24 ScriptPath: name: path in: path required: true - schema: *ref_29 + schema: *ref_33 ScriptHash: name: hash in: path required: true - schema: *ref_33 + schema: *ref_37 JobId: name: id in: path required: true - schema: *ref_73 + schema: *ref_83 Path: name: path in: path required: true - schema: *ref_17 + schema: *ref_21 PathId: name: id in: path required: true - schema: *ref_24 + schema: *ref_28 PathVersion: name: version in: path required: true - schema: *ref_97 + schema: *ref_116 Name: name: name in: path required: true - schema: *ref_80 + schema: *ref_92 Page: name: page description: which page to return (start at 1, default 1) in: query - schema: *ref_3 + schema: *ref_5 PerPage: name: per_page description: number of items to return for a given page (default 30, max 100) in: query - schema: *ref_4 + schema: *ref_6 OrderDesc: name: order_desc description: order by desc order (default true) in: query - schema: *ref_41 + schema: *ref_48 CreatedBy: name: created_by description: mask to filter exact matching user creator in: query - schema: *ref_42 + schema: *ref_49 + Label: + name: label + description: >- + mask to filter exact matching job's label (job labels are completed jobs + with as a result an object containing a string in the array at key + 'wm_labels') + in: query + schema: *ref_78 ParentJob: name: parent_job description: >- The parent job that is at the origin and responsible for the execution of this script if any in: query - schema: *ref_36 + schema: *ref_42 WorkerTag: name: tag description: Override the tag to use in: query - schema: *ref_38 + schema: *ref_44 + CacheTtl: + name: cache_ttl + description: >- + Override the cache time to live (in seconds). Can not be used to disable + caching, only override with a new cache ttl + in: query + schema: *ref_45 NewJobId: name: job_id description: >- @@ -11089,7 +13816,7 @@ components: randomly using the ULID scheme. If a job id already exists in the queue or as a completed job, the request to create one will fail (Bad Request) in: query - schema: *ref_37 + schema: *ref_43 IncludeHeader: name: include_header description: > @@ -11099,14 +13826,14 @@ components: Header's key lowercased and '-'' replaced to '_' such that 'Content-Type' becomes the 'content_type' arg key in: query - schema: *ref_39 + schema: *ref_46 QueueLimit: name: queue_limit description: > The maximum size of the queue for which the request would get rejected if that job would push it above that limit in: query - schema: *ref_40 + schema: *ref_47 Payload: name: payload description: > @@ -11115,233 +13842,249 @@ components: `encodeURIComponent(btoa(JSON.stringify({a: 2})))` in: query - schema: *ref_76 + schema: *ref_86 ScriptStartPath: name: script_path_start description: mask to filter matching starting path in: query - schema: *ref_55 + schema: *ref_63 SchedulePath: name: schedule_path description: mask to filter by schedule path in: query - schema: *ref_56 + schema: *ref_64 ScriptExactPath: name: script_path_exact description: mask to filter exact matching path in: query - schema: *ref_54 + schema: *ref_62 ScriptExactHash: name: script_hash description: mask to filter exact matching path in: query - schema: *ref_57 + schema: *ref_65 + CreatedBefore: + name: created_before + description: filter on created before (inclusive) timestamp + in: query + schema: *ref_117 + CreatedAfter: + name: created_after + description: filter on created after (exclusive) timestamp + in: query + schema: *ref_118 StartedBefore: name: started_before description: filter on started before (inclusive) timestamp in: query - schema: *ref_58 + schema: *ref_66 StartedAfter: name: started_after description: filter on started after (exclusive) timestamp in: query - schema: *ref_59 + schema: *ref_67 + Before: + name: before + description: filter on started before (inclusive) timestamp + in: query + schema: *ref_109 CreatedOrStartedAfter: name: created_or_started_after description: >- filter on created_at for non non started job and started_at otherwise after (exclusive) timestamp in: query - schema: *ref_98 + schema: *ref_112 + CreatedOrStartedAfterCompletedJob: + name: created_or_started_after_completed_jobs + description: >- + filter on created_at for non non started job and started_at otherwise + after (exclusive) timestamp but only for the completed jobs + in: query + schema: *ref_113 CreatedOrStartedBefore: name: created_or_started_before description: >- filter on created_at for non non started job and started_at otherwise before (inclusive) timestamp in: query - schema: *ref_99 + schema: *ref_111 Success: name: success description: filter on successful jobs in: query - schema: *ref_60 + schema: *ref_68 ScheduledForBeforeNow: name: scheduled_for_before_now description: filter on jobs scheduled_for before now (hence waitinf for a worker) in: query - schema: *ref_68 + schema: *ref_69 Suspended: name: suspended description: filter on suspended jobs in: query - schema: *ref_100 + schema: *ref_71 Running: name: running description: filter on running jobs in: query - schema: *ref_67 + schema: *ref_72 ArgsFilter: name: args description: filter on jobs containing those args as a json subset (@> in postgres) in: query - schema: *ref_62 + schema: *ref_73 Tag: name: tag description: filter on jobs with a given tag/worker group in: query - schema: *ref_64 + schema: *ref_75 ResultFilter: name: result description: filter on jobs containing those result as a json subset (@> in postgres) in: query - schema: *ref_63 + schema: *ref_74 After: name: after description: filter on created after (exclusive) timestamp in: query - schema: *ref_101 - Before: - name: before - description: filter on created before (exclusive) timestamp - in: query - schema: *ref_102 + schema: *ref_110 Username: name: username description: filter on exact username of user in: query - schema: *ref_103 + schema: *ref_119 Operation: name: operation description: filter on exact or prefix name of operation in: query - schema: *ref_104 + schema: *ref_120 ResourceName: name: resource description: filter on exact or prefix name of resource in: query - schema: *ref_105 + schema: *ref_121 ActionKind: name: action_kind description: filter on type of operation in: query - schema: *ref_106 + schema: *ref_122 JobKinds: name: job_kinds description: >- filter on job kind (values 'preview', 'script', 'dependencies', 'flow') separated by, in: query - schema: *ref_61 + schema: *ref_70 RunnableId: name: runnable_id in: query - schema: *ref_89 + schema: *ref_101 RunnableTypeQuery: name: runnable_type in: query - schema: *ref_90 + schema: *ref_102 InputId: name: input in: path required: true - schema: *ref_107 + schema: *ref_123 GetStarted: name: get_started in: query - schema: *ref_108 + schema: *ref_124 ConcurrencyId: name: concurrency_id in: path required: true - schema: *ref_109 + schema: *ref_125 schemas: Script: type: object - properties: *ref_31 - required: *ref_32 + properties: *ref_35 + required: *ref_36 NewScript: type: object - properties: *ref_34 - required: *ref_35 + properties: *ref_40 + required: *ref_41 NewScriptWithDraft: - allOf: *ref_110 + allOf: *ref_126 ScriptHistory: - type: object - properties: *ref_111 - required: *ref_112 - ScriptArgs: - type: object - additionalProperties: *ref_14 - Input: - type: object - properties: *ref_87 - required: *ref_88 - CreateInput: - type: object - properties: *ref_113 - required: *ref_114 - UpdateInput: - type: object - properties: *ref_115 - required: *ref_116 - RunnableType: - type: string - enum: *ref_117 - QueuedJob: - type: object - properties: *ref_71 - required: *ref_72 - CompletedJob: - type: object - properties: *ref_69 - required: *ref_70 - Job: - allOf: *ref_74 - discriminator: *ref_75 - User: - type: object - properties: *ref_8 - required: *ref_9 - Usage: - type: object - properties: *ref_118 - Login: - type: object - properties: *ref_119 - required: *ref_120 - NewUser: - type: object - properties: *ref_121 - required: *ref_122 - EditWorkspaceUser: - type: object - properties: *ref_123 - TruncatedToken: - type: object - properties: *ref_124 - required: *ref_125 - NewToken: - type: object - properties: *ref_126 - NewTokenImpersonate: type: object properties: *ref_127 required: *ref_128 - ListableVariable: + ScriptArgs: type: object - properties: *ref_18 - required: *ref_19 - ContextualVariable: + additionalProperties: *ref_16 + Input: + type: object + properties: *ref_103 + required: *ref_104 + CreateInput: type: object properties: *ref_129 required: *ref_130 - CreateVariable: + UpdateInput: type: object properties: *ref_131 required: *ref_132 + RunnableType: + type: string + enum: *ref_133 + QueuedJob: + type: object + properties: *ref_81 + required: *ref_82 + CompletedJob: + type: object + properties: *ref_79 + required: *ref_80 + ObscuredJob: + type: object + properties: *ref_134 + Job: + oneOf: *ref_84 + discriminator: *ref_85 + User: + type: object + properties: *ref_10 + required: *ref_11 + UserUsage: + type: object + properties: *ref_135 + Login: + type: object + properties: *ref_136 + required: *ref_137 + EditWorkspaceUser: + type: object + properties: *ref_138 + TruncatedToken: + type: object + properties: *ref_38 + required: *ref_39 + NewToken: + type: object + properties: *ref_139 + NewTokenImpersonate: + type: object + properties: *ref_140 + required: *ref_141 + ListableVariable: + type: object + properties: *ref_22 + required: *ref_23 + ContextualVariable: + type: object + properties: *ref_142 + required: *ref_143 + CreateVariable: + type: object + properties: *ref_144 + required: *ref_145 EditVariable: type: object - properties: *ref_133 + properties: *ref_146 AuditLog: type: object properties: *ref_1 @@ -11457,124 +14200,164 @@ components: required: - name - typ + no_main_func: + type: boolean + nullable: true + has_preprocessor: + type: boolean + nullable: true required: - star_args - start_kwargs - args - type - error + - no_main_func + - has_preprocessor Preview: - type: object - properties: *ref_134 - required: *ref_135 - CreateResource: - type: object - properties: *ref_136 - required: *ref_137 - EditResource: - type: object - properties: *ref_138 - Resource: - type: object - properties: *ref_139 - required: *ref_140 - ListableResource: - type: object - properties: *ref_141 - required: *ref_142 - ResourceType: - type: object - properties: *ref_22 - required: *ref_23 - EditResourceType: - type: object - properties: *ref_143 - Schedule: - type: object - properties: *ref_78 - required: *ref_79 - ScheduleWJobs: - allOf: *ref_144 - NewSchedule: - type: object - properties: *ref_145 - required: *ref_146 - EditSchedule: type: object properties: *ref_147 required: *ref_148 - Group: - type: object - properties: *ref_83 - required: *ref_84 - InstanceGroup: - type: object - properties: *ref_81 - required: *ref_82 - Folder: - type: object - properties: *ref_85 - required: *ref_86 - WorkerPing: + WorkflowTask: type: object properties: *ref_149 required: *ref_150 - UserWorkspaceList: + WorkflowStatusRecord: type: object - properties: *ref_151 - required: *ref_152 - CreateWorkspace: + additionalProperties: *ref_151 + WorkflowStatus: + type: object + properties: *ref_152 + CreateResource: type: object properties: *ref_153 required: *ref_154 - Workspace: - type: object - properties: *ref_5 - required: *ref_6 - WorkspaceInvite: - type: object - properties: *ref_12 - required: *ref_13 - GlobalUserInfo: - type: object - properties: *ref_10 - required: *ref_11 - Flow: - allOf: *ref_45 - FlowMetadata: + EditResource: type: object properties: *ref_155 - required: *ref_156 - OpenFlowWPath: - allOf: *ref_46 - FlowPreview: + Resource: type: object - properties: *ref_157 - required: *ref_158 - RestartedFrom: + properties: *ref_156 + required: *ref_157 + ListableResource: type: object - properties: *ref_159 - Policy: + properties: *ref_158 + required: *ref_159 + ResourceType: type: object - properties: *ref_47 - ListableApp: + properties: *ref_26 + required: *ref_27 + EditResourceType: type: object properties: *ref_160 - required: *ref_161 - ListableRawApp: + Schedule: + type: object + properties: *ref_88 + required: *ref_89 + ScheduleWJobs: + allOf: *ref_161 + NewSchedule: type: object properties: *ref_162 required: *ref_163 + EditSchedule: + type: object + properties: *ref_164 + required: *ref_165 + HttpTrigger: + type: object + properties: *ref_90 + required: *ref_91 + NewHttpTrigger: + type: object + properties: *ref_166 + required: *ref_167 + EditHttpTrigger: + type: object + properties: *ref_168 + required: *ref_169 + TriggersCount: + type: object + properties: *ref_53 + Group: + type: object + properties: *ref_97 + required: *ref_98 + InstanceGroup: + type: object + properties: *ref_93 + required: *ref_94 + Folder: + type: object + properties: *ref_99 + required: *ref_100 + WorkerPing: + type: object + properties: *ref_170 + required: *ref_171 + UserWorkspaceList: + type: object + properties: *ref_172 + required: *ref_173 + CreateWorkspace: + type: object + properties: *ref_174 + required: *ref_175 + Workspace: + type: object + properties: *ref_7 + required: *ref_8 + WorkspaceInvite: + type: object + properties: *ref_14 + required: *ref_15 + GlobalUserInfo: + type: object + properties: *ref_12 + required: *ref_13 + Flow: + allOf: *ref_52 + ExtraPerms: + type: object + additionalProperties: *ref_176 + FlowMetadata: + type: object + properties: *ref_177 + required: *ref_178 + OpenFlowWPath: + allOf: *ref_54 + FlowPreview: + type: object + properties: *ref_179 + required: *ref_180 + RestartedFrom: + type: object + properties: *ref_181 + Policy: + type: object + properties: *ref_55 + ListableApp: + type: object + properties: *ref_182 + required: *ref_183 + ListableRawApp: + type: object + properties: *ref_184 + required: *ref_185 AppWithLastVersion: type: object - properties: *ref_48 - required: *ref_49 + properties: *ref_56 + required: *ref_57 AppWithLastVersionWDraft: - allOf: *ref_164 + allOf: *ref_186 AppHistory: type: object - properties: *ref_165 - required: *ref_166 + properties: *ref_187 + required: *ref_188 + FlowVersion: + type: object + properties: *ref_189 + required: *ref_190 SlackToken: type: object properties: @@ -11596,40 +14379,46 @@ components: - bot TokenResponse: type: object - properties: *ref_167 - required: *ref_168 + properties: *ref_191 + required: *ref_192 HubScriptKind: name: kind - schema: *ref_30 + schema: *ref_34 PolarsClientKwargs: type: object - properties: *ref_93 - required: *ref_94 + properties: *ref_107 + required: *ref_108 LargeFileStorage: type: object - properties: *ref_15 + properties: *ref_17 WindmillLargeFile: type: object - properties: *ref_169 - required: *ref_170 + properties: *ref_193 + required: *ref_194 WindmillFileMetadata: type: object - properties: *ref_171 + properties: *ref_195 WindmillFilePreview: type: object - properties: *ref_172 - required: *ref_173 + properties: *ref_196 + required: *ref_197 S3Resource: type: object - properties: *ref_91 - required: *ref_92 + properties: *ref_105 + required: *ref_106 WorkspaceGitSyncSettings: type: object - properties: *ref_16 + properties: *ref_18 + WorkspaceDeployUISettings: + type: object + properties: *ref_19 + WorkspaceDefaultScripts: + type: object + properties: *ref_20 GitRepositorySettings: type: object - properties: *ref_174 - required: *ref_175 + properties: *ref_198 + required: *ref_199 UploadFilePart: type: object properties: @@ -11641,91 +14430,118 @@ components: - part_number - tag MetricMetadata: - type: object - properties: *ref_176 - required: *ref_177 - ScalarMetric: - type: object - properties: *ref_178 - required: *ref_179 - TimeseriesMetric: - type: object - properties: *ref_180 - required: *ref_181 - MetricDataPoint: - type: object - properties: *ref_182 - required: *ref_183 - RawScriptForDependencies: - type: object - properties: *ref_184 - required: *ref_185 - ConcurrencyGroup: - type: object - properties: *ref_186 - required: *ref_187 - StaticTransform: - type: object - properties: *ref_188 - required: *ref_189 - JavascriptTransform: - type: object - properties: *ref_190 - required: *ref_191 - InputTransform: - oneOf: *ref_25 - discriminator: *ref_26 - RawScript: - type: object - properties: *ref_192 - required: *ref_193 - PathScript: - type: object - properties: *ref_194 - required: *ref_195 - PathFlow: - type: object - properties: *ref_196 - required: *ref_197 - FlowModule: - type: object - properties: *ref_27 - required: *ref_28 - ForloopFlow: - type: object - properties: *ref_198 - required: *ref_199 - BranchOne: type: object properties: *ref_200 required: *ref_201 - BranchAll: + ScalarMetric: type: object properties: *ref_202 required: *ref_203 - Identity: + TimeseriesMetric: type: object properties: *ref_204 required: *ref_205 + MetricDataPoint: + type: object + properties: *ref_206 + required: *ref_207 + RawScriptForDependencies: + type: object + properties: *ref_208 + required: *ref_209 + ConcurrencyGroup: + type: object + properties: *ref_210 + required: *ref_211 + ExtendedJobs: + type: object + properties: *ref_212 + required: *ref_213 + ExportedUser: + type: object + properties: *ref_3 + required: *ref_4 + GlobalSetting: + type: object + properties: *ref_214 + required: *ref_215 + Config: + type: object + properties: *ref_216 + required: *ref_217 + ExportedInstanceGroup: + type: object + properties: *ref_95 + required: *ref_96 + JobSearchHit: + type: object + properties: *ref_218 + StaticTransform: + type: object + properties: *ref_219 + required: *ref_220 + JavascriptTransform: + type: object + properties: *ref_221 + required: *ref_222 + InputTransform: + oneOf: *ref_29 + discriminator: *ref_30 + RawScript: + type: object + properties: *ref_223 + required: *ref_224 + PathScript: + type: object + properties: *ref_225 + required: *ref_226 + PathFlow: + type: object + properties: *ref_227 + required: *ref_228 + FlowModule: + type: object + properties: *ref_31 + required: *ref_32 + ForloopFlow: + type: object + properties: *ref_229 + required: *ref_230 + WhileloopFlow: + type: object + properties: *ref_231 + required: *ref_232 + BranchOne: + type: object + properties: *ref_233 + required: *ref_234 + BranchAll: + type: object + properties: *ref_235 + required: *ref_236 + Identity: + type: object + properties: *ref_237 + required: *ref_238 FlowModuleValue: - oneOf: *ref_206 - discriminator: *ref_207 + oneOf: *ref_239 + discriminator: *ref_240 Retry: type: object - properties: *ref_77 + properties: *ref_87 FlowValue: + type: object + properties: *ref_58 + required: *ref_59 + OpenFlow: type: object properties: *ref_50 required: *ref_51 - OpenFlow: - type: object - properties: *ref_43 - required: *ref_44 FlowStatusModule: type: object - properties: *ref_52 - required: *ref_53 + properties: *ref_60 + required: *ref_61 FlowStatus: type: object - properties: *ref_65 - required: *ref_66 + properties: *ref_76 + required: *ref_77 diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 081a69dafc..1744b48526 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.407.1 + version: 1.409.2 title: Windmill API contact: @@ -2789,7 +2789,14 @@ paths: oauth: type: array items: - type: string + type: object + properties: + type: + type: string + display_name: + type: string + required: + - type saml: type: string required: @@ -4013,6 +4020,42 @@ paths: schema: $ref: "#/components/schemas/Script" + /w/{workspace}/scripts/get_triggers_count/{path}: + get: + summary: get triggers count of script + operationId: getTriggersCountOfScript + tags: + - script + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: triggers count + content: + application/json: + schema: + $ref: "#/components/schemas/TriggersCount" + + /w/{workspace}/scripts/list_tokens/{path}: + get: + summary: get tokens with script scope + operationId: listTokensOfScript + tags: + - script + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: tokens list + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/TruncatedToken" + /w/{workspace}/scripts/get/draft/{path}: get: summary: get script by path with draft @@ -4617,6 +4660,43 @@ paths: schema: $ref: "#/components/schemas/Flow" + /w/{workspace}/flows/get_triggers_count/{path}: + get: + summary: get triggers count of flow + operationId: getTriggersCountOfFlow + tags: + - flow + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: triggers count + content: + application/json: + schema: + $ref: "#/components/schemas/TriggersCount" + + /w/{workspace}/flows/list_tokens/{path}: + get: + summary: get tokens with flow scope + operationId: listTokensOfFlow + tags: + - flow + parameters: + - $ref: "#/components/parameters/WorkspaceId" + - $ref: "#/components/parameters/ScriptPath" + responses: + "200": + description: tokens list + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/TruncatedToken" + + /w/{workspace}/flows/toggle_workspace_error_handler/{path}: post: summary: Toggle ON and OFF the workspace error handler for a given flow @@ -10247,6 +10327,8 @@ components: type: array items: type: string + email: + type: string required: - token_prefix - created_at @@ -10264,6 +10346,8 @@ components: type: array items: type: string + workspace_id: + type: string NewTokenImpersonate: type: object @@ -10275,6 +10359,8 @@ components: format: date-time impersonate_email: type: string + workspace_id: + type: string required: - impersonate_email @@ -11111,6 +11197,23 @@ components: - requires_auth - http_method + TriggersCount: + type: object + properties: + primary_schedule: + type: object + properties: + schedule: + type: string + schedule_count: + type: number + http_routes_count: + type: number + webhook_count: + type: number + email_count: + type: number + Group: type: object properties: diff --git a/backend/windmill-api/src/flows.rs b/backend/windmill-api/src/flows.rs index ca9f9944db..de183ae6eb 100644 --- a/backend/windmill-api/src/flows.rs +++ b/backend/windmill-api/src/flows.rs @@ -9,6 +9,9 @@ use std::collections::HashMap; use crate::db::ApiAuthed; +use crate::triggers::{ + get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail, +}; use crate::utils::WithStarredInfoQuery; use crate::{ db::DB, @@ -53,6 +56,8 @@ pub fn workspaced_service() -> Router { .route("/update/*path", post(update_flow)) .route("/archive/*path", post(archive_flow_by_path)) .route("/delete/*path", delete(delete_flow_by_path)) + .route("/get_triggers_count/*path", get(get_triggers_count)) + .route("/list_tokens/*path", get(list_tokens)) .route("/get/*path", get(get_flow_by_path)) .route("/get/draft/*path", get(get_flow_by_path_w_draft)) .route("/exists/*path", get(exists_flow_by_path)) @@ -874,6 +879,22 @@ async fn update_flow( Ok(nf.path.to_string()) } +async fn get_triggers_count( + Extension(db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult { + let path = path.to_path(); + get_triggers_count_internal(&db, &w_id, &path, true).await +} + +async fn list_tokens( + Extension(db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult> { + let path = path.to_path(); + list_tokens_internal(&db, &w_id, &path, true).await +} + async fn get_flow_by_path( authed: ApiAuthed, Extension(user_db): Extension, diff --git a/backend/windmill-api/src/folders.rs b/backend/windmill-api/src/folders.rs index fef5b7fe07..c9b69836c6 100644 --- a/backend/windmill-api/src/folders.rs +++ b/backend/windmill-api/src/folders.rs @@ -275,8 +275,10 @@ pub fn require_is_owner(authed: &ApiAuthed, name: &str) -> Result<()> { async fn update_folder( authed: ApiAuthed, + Extension(db): Extension, Extension(user_db): Extension, Extension(webhook): Extension, + Extension(rsmq): Extension>, Path((w_id, name)): Path<(String, String)>, Json(mut ng): Json, ) -> Result { @@ -367,6 +369,18 @@ async fn update_folder( } } + handle_deployment_metadata( + &authed.email, + &authed.username, + &db, + &w_id, + DeployedObject::Folder { path: format!("f/{}", name) }, + Some(format!("Folder '{}' updated", name)), + rsmq, + true, + ) + .await?; + audit_log( &mut *tx, &authed, diff --git a/backend/windmill-api/src/jobs.rs b/backend/windmill-api/src/jobs.rs index 69ca4f7e21..817a6f0d02 100644 --- a/backend/windmill-api/src/jobs.rs +++ b/backend/windmill-api/src/jobs.rs @@ -24,7 +24,7 @@ use windmill_common::jobs::{ format_completed_job_result, format_result, CompletedJobWithFormattedResult, FormattedResult, ENTRYPOINT_OVERRIDE, }; -use windmill_common::worker::TMP_DIR; +use windmill_common::worker::{CLOUD_HOSTED, TMP_DIR}; #[cfg(all(feature = "enterprise", feature = "parquet"))] use windmill_common::scripts::PREVIEW_IS_CODEBASE_HASH; @@ -81,7 +81,7 @@ use windmill_common::{METRICS_DEBUG_ENABLED, METRICS_ENABLED}; use windmill_common::{get_latest_deployed_hash_for_path, BASE_URL}; use windmill_queue::{ cancel_job, get_queued_job, get_result_by_id_from_running_flow, job_is_complete, push, - DecodeQueries, PushArgs, PushArgsOwned, PushIsolationLevel, QueueTransaction, + DecodeQueries, PushArgs, PushArgsOwned, PushIsolationLevel, }; #[cfg(feature = "prometheus")] @@ -544,8 +544,8 @@ pub async fn get_path_for_hash<'c>( Ok(path) } -pub async fn get_path_tag_limits_cache_for_hash<'c, R: rsmq_async::RsmqConnection + Send>( - tx: &mut QueueTransaction<'c, R>, +pub async fn get_path_tag_limits_cache_for_hash( + tx: &DB, w_id: &str, hash: i64, ) -> error::Result<( @@ -1469,6 +1469,8 @@ async fn cancel_jobs( } } + uuids.extend(trivial_jobs); + Ok(Json(uuids)) } @@ -2810,7 +2812,6 @@ pub async fn run_flow_by_path_inner( let flow_path = flow_path.to_path(); check_scopes(&authed, || format!("run:flow/{flow_path}"))?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); let (tag, dedicated_worker, has_preprocessor) = sqlx::query!( "SELECT tag, dedicated_worker, flow_version.value->>'preprocessor_module' IS NOT NULL as has_preprocessor @@ -2821,7 +2822,7 @@ pub async fn run_flow_by_path_inner( flow_path, w_id ) - .fetch_optional(&mut tx) + .fetch_optional(&db) .await? .map(|x| (x.tag, x.dedicated_worker, x.has_preprocessor)) .ok_or_else(|| { @@ -2834,7 +2835,7 @@ pub async fn run_flow_by_path_inner( check_tag_available_for_workspace(&w_id, &tag).await?; let scheduled_for = run_query.get_scheduled_for(&db).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, tx, @@ -2906,14 +2907,13 @@ pub async fn restart_flow( ) -> error::Result<(StatusCode, String)> { check_license_key_valid().await?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); let completed_job = sqlx::query_as::<_, CompletedJob>( "SELECT *, result->'wm_labels' as labels from completed_job WHERE id = $1 and workspace_id = $2", ) .bind(job_id) .bind(&w_id) - .fetch_optional(&mut tx) + .fetch_optional(&db) .await? .with_context(|| "Unable to find completed job with the given job UUID")?; @@ -2931,7 +2931,7 @@ pub async fn restart_flow( let scheduled_for = run_query.get_scheduled_for(&db).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -3007,16 +3007,16 @@ pub async fn run_script_by_path_inner( check_scopes(&authed, || format!("run:script/{script_path}"))?; - 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, run_query.skip_preprocessor).await?; + script_path_to_payload(script_path, &db, &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); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -3049,6 +3049,11 @@ pub async fn run_script_by_path_inner( Ok((StatusCode::CREATED, uuid.to_string())) } +#[derive(Deserialize)] +pub struct WorkflowAsCodeQuery { + pub skip_update: Option, +} + pub async fn run_workflow_as_code( authed: ApiAuthed, Extension(db): Extension, @@ -3056,15 +3061,38 @@ pub async fn run_workflow_as_code( Extension(rsmq): Extension>, Path((w_id, job_id, entrypoint)): Path<(String, Uuid, String)>, Query(run_query): Query, + Query(wkflow_query): Query, Json(task): Json, ) -> error::Result<(StatusCode, String)> { + + let mut i = 1; + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + #[cfg(feature = "enterprise")] check_license_key_valid().await?; check_tag_available_for_workspace(&w_id, &run_query.tag).await?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + let job = get_queued_job(&job_id, &w_id, &db).await?; + + + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + + let job = not_found_if_none(job, "Queued Job", &job_id.to_string())?; let (job_payload, tag, _delete_after_use, timeout) = match job.job_kind { JobKind::Preview => ( @@ -3089,7 +3117,7 @@ pub async fn run_workflow_as_code( JobKind::Script => { script_path_to_payload( job.script_path(), - &mut tx, + &db, &w_id, run_query.skip_preprocessor, ) @@ -3098,6 +3126,12 @@ pub async fn run_workflow_as_code( _ => return Err(anyhow::anyhow!("Not supported").into()), }; + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + let mut extra = HashMap::new(); extra.insert(ENTRYPOINT_OVERRIDE.to_string(), to_raw_value(&entrypoint)); @@ -3106,7 +3140,21 @@ pub async fn run_workflow_as_code( let tag = run_query.tag.clone().or(tag).or(Some(job.tag)); - let tx = PushIsolationLevel::Transaction(tx); + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + + + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); + + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + let (uuid, mut tx) = push( &db, @@ -3133,14 +3181,39 @@ pub async fn run_workflow_as_code( Some(&authed.clone().into()), ) .await?; - sqlx::query!( - "UPDATE queue SET flow_status = jsonb_set(COALESCE(flow_status, '{}'::jsonb), array[$1], jsonb_set(jsonb_set('{}'::jsonb, '{scheduled_for}', to_jsonb(now()::text)), '{name}', to_jsonb($4::text))) WHERE id = $2 AND workspace_id = $3", - uuid.to_string(), - job_id, - w_id, - entrypoint - ).execute(&mut tx).await?; + + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + + if !wkflow_query.skip_update.unwrap_or(false) { + sqlx::query!( + "UPDATE queue SET flow_status = jsonb_set(COALESCE(flow_status, '{}'::jsonb), array[$1], jsonb_set(jsonb_set('{}'::jsonb, '{scheduled_for}', to_jsonb(now()::text)), '{name}', to_jsonb($4::text))) WHERE id = $2 AND workspace_id = $3", + uuid.to_string(), + job_id, + w_id, + entrypoint + ).execute(&mut tx).await?; + } else { + tracing::info!("Skipping update of flow status for job {job_id} in workspace {w_id}"); + } + + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + i += 1; + } + + tx.commit().await?; + + + if *CLOUD_HOSTED { + tracing::info!("workflow_as_code_tracing id {i} "); + } + Ok((StatusCode::CREATED, uuid.to_string())) } @@ -3504,15 +3577,13 @@ pub async fn run_wait_result_job_by_path_get( let script_path = script_path.to_path(); check_scopes(&authed, || format!("run:script/{script_path}"))?; - 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, run_query.skip_preprocessor).await?; + script_path_to_payload(script_path, &db, &w_id, run_query.skip_preprocessor).await?; let tag = run_query.tag.clone().or(tag); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -3629,15 +3700,13 @@ pub async fn run_wait_result_script_by_path_internal( let script_path = script_path.to_path(); check_scopes(&authed, || format!("run:script/{script_path}"))?; - 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, run_query.skip_preprocessor).await?; + script_path_to_payload(script_path, &db, &w_id, run_query.skip_preprocessor).await?; let tag = run_query.tag.clone().or(tag); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -3689,8 +3758,6 @@ pub async fn run_wait_result_script_by_hash( check_queue_too_long(&db, run_query.queue_limit).await?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); - let hash = script_hash.0; let ( path, @@ -3705,7 +3772,7 @@ pub async fn run_wait_result_script_by_hash( delete_after_use, timeout, has_preprocessor, - ) = get_path_tag_limits_cache_for_hash(&mut tx, &w_id, hash).await?; + ) = get_path_tag_limits_cache_for_hash(&db, &w_id, hash).await?; if let Some(run_query_cache_ttl) = run_query.cache_ttl { cache_ttl = Some(run_query_cache_ttl); } @@ -3714,7 +3781,7 @@ pub async fn run_wait_result_script_by_hash( let tag = run_query.tag.clone().or(tag); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -3796,7 +3863,6 @@ pub async fn run_wait_result_flow_by_path_internal( let flow_path = flow_path.to_path(); check_scopes(&authed, || format!("run:flow/{flow_path}"))?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); let scheduled_for = run_query.get_scheduled_for(&db).await?; @@ -3809,7 +3875,7 @@ pub async fn run_wait_result_flow_by_path_internal( flow_path, w_id ) - .fetch_optional(&mut tx) + .fetch_optional(&db) .await? .map(|x| (x.tag, x.dedicated_worker, x.early_return, x.has_preprocessor)) .ok_or_else(|| { @@ -3821,7 +3887,7 @@ pub async fn run_wait_result_flow_by_path_internal( let tag = run_query.tag.clone().or(tag); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, @@ -4127,10 +4193,10 @@ async fn run_dependencies_job( JsonRawValue::from_string("true".to_string()).unwrap(), ); if language == ScriptLang::Bun { - let annotation = windmill_common::worker::get_annotation_ts(&raw_code); + let annotation = windmill_common::worker::TypeScriptAnnotations::parse(&raw_code); hm.insert( "npm_mode".to_string(), - JsonRawValue::from_string(annotation.npm_mode.to_string()).unwrap(), + JsonRawValue::from_string(annotation.npm.to_string()).unwrap(), ); } (PushArgs { extra: Some(hm), args: &ehm }, deps) @@ -4293,7 +4359,6 @@ async fn add_batch_jobs( } } "flow" => { - let mut tx = PushIsolationLevel::IsolatedRoot(db.clone(), rsmq); let mut uuids: Vec = Vec::new(); let payload = if let Some(ref fv) = batch_info.flow_value { @@ -4311,6 +4376,7 @@ async fn add_batch_jobs( ))? } }; + let mut tx = PushIsolationLevel::IsolatedRoot(db.clone(), rsmq); for _ in 0..n { let ehm = HashMap::new(); let (uuid, ntx) = push( @@ -4511,7 +4577,6 @@ pub async fn run_job_by_hash_inner( #[cfg(feature = "enterprise")] check_license_key_valid().await?; - let mut tx: QueueTransaction<'_, _> = (rsmq, user_db.begin(&authed).await?).into(); let hash = script_hash.0; let ( @@ -4527,7 +4592,7 @@ pub async fn run_job_by_hash_inner( _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?; + ) = get_path_tag_limits_cache_for_hash(&db, &w_id, hash).await?; check_scopes(&authed, || format!("run:script/{path}"))?; if let Some(run_query_cache_ttl) = run_query.cache_ttl { cache_ttl = Some(run_query_cache_ttl); @@ -4536,7 +4601,7 @@ pub async fn run_job_by_hash_inner( let tag = run_query.tag.clone().or(tag); check_tag_available_for_workspace(&w_id, &tag).await?; - let tx = PushIsolationLevel::Transaction(tx); + let tx = PushIsolationLevel::Isolated(user_db, authed.clone().into(), rsmq); let (uuid, tx) = push( &db, diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index c73972529a..78108a61a4 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -82,6 +82,7 @@ pub mod smtp_server_ee; mod static_assets; mod stripe_ee; mod tracing_init; +mod triggers; mod users; mod utils; mod variables; diff --git a/backend/windmill-api/src/scripts.rs b/backend/windmill-api/src/scripts.rs index 112a601901..9b91c6b5fb 100644 --- a/backend/windmill-api/src/scripts.rs +++ b/backend/windmill-api/src/scripts.rs @@ -9,6 +9,9 @@ use crate::{ db::{ApiAuthed, DB}, schedule::clear_schedule, + triggers::{ + get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail, + }, users::{maybe_refresh_folders, require_owner_of_path, AuthCache}, utils::WithStarredInfoQuery, webhook_util::{WebhookMessage, WebhookShared}, @@ -53,7 +56,7 @@ use windmill_common::{ utils::{ not_found_if_none, paginate, query_elems_from_hub, require_admin, Pagination, StripPath, }, - worker::{get_annotation_ts, to_raw_value}, + worker::to_raw_value, HUB_BASE_URL, }; use windmill_git_sync::{handle_deployment_metadata, DeployedObject}; @@ -132,6 +135,8 @@ pub fn workspaced_service() -> Router { .route("/archive/p/*path", post(archive_script_by_path)) .route("/get/draft/*path", get(get_script_by_path_w_draft)) .route("/get/p/*path", get(get_script_by_path)) + .route("/get_triggers_count/*path", get(get_triggers_count)) + .route("/list_tokens/*path", get(list_tokens)) .route("/raw/p/*path", get(raw_script_by_path)) .route("/raw_unpinned/p/*path", get(raw_script_by_path_unpinned)) .route("/exists/p/*path", get(exists_script_by_path)) @@ -601,8 +606,8 @@ async fn create_script_internal<'c>( }; let lang = if &ns.language == &ScriptLang::Bun || &ns.language == &ScriptLang::Bunnative { - let anns = get_annotation_ts(&ns.content); - if anns.native_mode { + let anns = windmill_common::worker::TypeScriptAnnotations::parse(&ns.content); + if anns.native { ScriptLang::Bunnative } else { ScriptLang::Bun @@ -874,6 +879,22 @@ async fn get_script_by_path( Ok(Json(script)) } +async fn list_tokens( + Extension(db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult> { + let path = path.to_path(); + list_tokens_internal(&db, &w_id, &path, false).await +} + +async fn get_triggers_count( + Extension(db): Extension, + Path((w_id, path)): Path<(String, StripPath)>, +) -> JsonResult { + let path = path.to_path(); + get_triggers_count_internal(&db, &w_id, &path, false).await +} + async fn get_script_by_path_w_draft( authed: ApiAuthed, Extension(user_db): Extension, diff --git a/backend/windmill-api/src/tracing_init.rs b/backend/windmill-api/src/tracing_init.rs index 1f93b941cb..60dab73810 100644 --- a/backend/windmill-api/src/tracing_init.rs +++ b/backend/windmill-api/src/tracing_init.rs @@ -9,6 +9,7 @@ use ::tracing::{field, Span}; use hyper::Response; use tower_http::trace::{MakeSpan, OnFailure, OnResponse}; +use uuid::Uuid; lazy_static::lazy_static! { static ref LOG_REQUESTS: bool = std::env::var("LOG_REQUESTS") @@ -45,17 +46,28 @@ impl OnFailure for MyOnFailure { // tracing::error!(latency = latency.as_millis(), "response") } } + +lazy_static::lazy_static! { + static ref TRACING_HEADER: String = std::env::var("TRACING_HEADER") + .ok().unwrap_or_else(|| "x-tracing-id".to_string()); +} #[derive(Clone)] pub struct MyMakeSpan {} impl MakeSpan for MyMakeSpan { fn make_span(&mut self, request: &hyper::Request) -> Span { + let tracing_id = request + .headers() + .get(TRACING_HEADER.as_str()) + .and_then(|x| x.to_str().map(|x| x.to_string()).ok()) + .unwrap_or(Uuid::new_v4().to_string()); tracing::info_span!( "request", method = %request.method(), uri = %request.uri(), username = field::Empty, workspace_id = field::Empty, + trace_id = tracing_id, email = field::Empty, ) } diff --git a/backend/windmill-api/src/triggers.rs b/backend/windmill-api/src/triggers.rs new file mode 100644 index 0000000000..dbc5306027 --- /dev/null +++ b/backend/windmill-api/src/triggers.rs @@ -0,0 +1,131 @@ +use axum::Json; +use serde::{Deserialize, Serialize}; +use sqlx::FromRow; +use windmill_common::error::JsonResult; + +use crate::db::DB; + +#[derive(Serialize, Deserialize, Debug)] +pub struct TriggerPrimarySchedule { + schedule: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct TriggersCount { + primary_schedule: Option, + schedule_count: i64, + http_routes_count: i64, + webhook_count: i64, + email_count: i64, +} +pub(crate) async fn get_triggers_count_internal( + db: &DB, + w_id: &str, + path: &str, + is_flow: bool, +) -> JsonResult { + let primary_schedule = sqlx::query_scalar!( + "SELECT schedule FROM schedule WHERE path = $1 AND script_path = $1 AND is_flow = $2 AND workspace_id = $3", + path, + is_flow, + w_id + ) + .fetch_optional(db) + .await?; + + let schedule_count = sqlx::query_scalar!( + "SELECT COUNT(*) FROM schedule WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3", + path, + is_flow, + w_id + ) + .fetch_one(db) + .await? + .unwrap_or(0); + + let http_routes_count = sqlx::query_scalar!( + "SELECT COUNT(*) FROM http_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3", + path, + is_flow, + w_id + ) + .fetch_one(db) + .await? + .unwrap_or(0); + + let webhook_count = (if is_flow { + sqlx::query_scalar!( + "SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + w_id, + path, + ) + + } else { + sqlx::query_scalar!( + "SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:' || $2]::text[]", + w_id, + path, + ) + }).fetch_one(db) + .await? + .unwrap_or(0); + + let email_count = (if is_flow { + sqlx::query_scalar!( + "SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + w_id, + path, + ) + + } else { + sqlx::query_scalar!( + "SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]", + w_id, + path, + ) + }).fetch_one(db) + .await? + .unwrap_or(0); + + Ok(Json(TriggersCount { + primary_schedule: primary_schedule.map(|s| TriggerPrimarySchedule { schedule: s }), + schedule_count, + http_routes_count, + webhook_count, + email_count, + })) +} + +#[derive(FromRow, Serialize)] +pub struct TruncatedTokenWithEmail { + pub label: Option, + pub token_prefix: Option, + pub expiration: Option>, + pub created_at: chrono::DateTime, + pub last_used_at: chrono::DateTime, + pub scopes: Option>, + pub email: Option, +} + +pub async fn list_tokens_internal( + db: &DB, + w_id: &str, + path: &str, + is_flow: bool, +) -> JsonResult> { + let tokens = if is_flow { + sqlx::query_as!( + TruncatedTokenWithEmail, + "SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]", + w_id, path).fetch_all(db) + .await? + } else { + sqlx::query_as!( + TruncatedTokenWithEmail, + "SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]", + w_id, path) + .fetch_all(db) + .await? + }; + Ok(Json(tokens)) +} diff --git a/backend/windmill-common/Cargo.toml b/backend/windmill-common/Cargo.toml index 546c339575..f3adbfde84 100644 --- a/backend/windmill-common/Cargo.toml +++ b/backend/windmill-common/Cargo.toml @@ -57,6 +57,7 @@ futures-core.workspace = true async-stream.workspace = true const_format.workspace = true crc.workspace = true +windmill-macros.workspace = true [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemalloc-ctl = { optional = true, workspace = true } diff --git a/backend/windmill-common/src/worker.rs b/backend/windmill-common/src/worker.rs index 89f2c148e0..37ae61c8d6 100644 --- a/backend/windmill-common/src/worker.rs +++ b/backend/windmill-common/src/worker.rs @@ -13,6 +13,7 @@ use std::{ sync::{atomic::AtomicBool, Arc}, }; use tokio::sync::RwLock; +use windmill_macros::annotations; use crate::{error, global_settings::CUSTOM_TAGS_SETTING, server::Smtp, DB}; @@ -303,64 +304,25 @@ fn parse_file(path: &str) -> Option { .flatten() } +#[annotations("#")] +pub struct PythonAnnotations { + pub no_cache: bool, + pub no_uv: bool, +} + +#[annotations("//")] pub struct TypeScriptAnnotations { - pub npm_mode: bool, - pub nodejs_mode: bool, - pub native_mode: bool, + pub npm: bool, + pub nodejs: bool, + pub native: bool, pub nobundling: bool, } -pub fn get_annotation_ts(inner_content: &str) -> TypeScriptAnnotations { - let annotations = inner_content - .lines() - .take_while(|x| x.starts_with("//")) - .map(|x| x.to_string().replace("//", "").trim().to_string()) - .collect_vec(); - let nodejs_mode: bool = annotations.contains(&"nodejs".to_string()); - let npm_mode: bool = annotations.contains(&"npm".to_string()); - let native_mode: bool = annotations.contains(&"native".to_string()); - - //TODO: remove || npm_mode when bun build is more powerful - let nobundling: bool = - annotations.contains(&"nobundling".to_string()) || nodejs_mode || *DISABLE_BUNDLING; - - TypeScriptAnnotations { npm_mode, nodejs_mode, native_mode, nobundling } -} - -pub struct PythonAnnotations { - pub no_uv: bool, - pub no_cache: bool, -} - -pub fn get_annotation_python(inner_content: &str) -> PythonAnnotations { - let annotations = inner_content - .lines() - .take_while(|x| x.starts_with("#")) - .map(|x| x.to_string().replace("#", "").trim().to_string()) - .collect_vec(); - - let no_uv: bool = annotations.contains(&"no_uv".to_string()); - let no_cache: bool = annotations.contains(&"no_cache".to_string()); - - PythonAnnotations { no_uv, no_cache } -} - +#[annotations("--")] pub struct SqlAnnotations { pub return_last_result: bool, } -pub fn get_sql_annotations(inner_content: &str) -> SqlAnnotations { - let annotations = inner_content - .lines() - .take_while(|x| x.starts_with("--")) - .map(|x| x.to_string().replace("--", "").trim().to_string()) - .collect_vec(); - - let return_last_result: bool = annotations.contains(&"return_last_result".to_string()); - - SqlAnnotations { return_last_result } -} - pub async fn load_cache(bin_path: &str, _remote_path: &str) -> (bool, String) { if tokio::fs::metadata(&bin_path).await.is_ok() { (true, format!("loaded from local cache: {}\n", bin_path)) diff --git a/backend/windmill-indexer/Cargo.toml b/backend/windmill-indexer/Cargo.toml index fa88503511..b345e02917 100644 --- a/backend/windmill-indexer/Cargo.toml +++ b/backend/windmill-indexer/Cargo.toml @@ -29,3 +29,4 @@ tempfile.workspace = true bytes.workspace = true object_store = { workspace = true, optional = true} tokio-tar.workspace = true +lazy_static.workspace = true diff --git a/backend/windmill-macros/Cargo.toml b/backend/windmill-macros/Cargo.toml new file mode 100644 index 0000000000..100b4678d3 --- /dev/null +++ b/backend/windmill-macros/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "windmill-macros" +version.workspace = true +authors.workspace = true +edition.workspace = true + +[lib] +proc-macro = true + +[dependencies] +proc-macro2.workspace = true +quote.workspace = true +syn.workspace = true + +# Dependencies for tests +[dev-dependencies] +# tests/annotation.rs +lazy_static.workspace = true +itertools.workspace = true +regex.workspace = true diff --git a/backend/windmill-macros/src/lib.rs b/backend/windmill-macros/src/lib.rs new file mode 100644 index 0000000000..25ff8cbaa2 --- /dev/null +++ b/backend/windmill-macros/src/lib.rs @@ -0,0 +1,95 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Ident, ItemStruct, Lit}; + +#[proc_macro_attribute] +pub fn annotations(attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemStruct); + let name = input.ident.clone(); + let fields = input + .fields + .iter() + .map(|f| f.ident.clone().unwrap()) + .collect::>(); + + // Match on the literal to extract the string value + let comm_lit = match parse_macro_input!(attr as Lit) { + Lit::Str(lit_str) => lit_str.value(), // This will give "#" without quotes + _ => panic!("Expected a string literal"), + }; + + // Generate regex + let mut reg = format!("^{}|", &comm_lit); + { + for field in fields.iter() { + reg.push_str(&(field.to_string())); + reg.push_str("\\b"); + } + + reg.push_str(r#"|\w+"#); + } + // Example of generated regex: + // ^# + // |ann1\b|ann2\b|ann3\b|ann4\b + // |\w+ + + TokenStream::from(quote! { + #[derive(Default, Debug)] + #input + + impl std::ops::BitOrAssign for #name{ + fn bitor_assign(&mut self, rhs: Self) { + // Unfold fields + // Read more: https://docs.rs/quote/latest/quote/macro.quote.html#interpolation + #( self.#fields |= rhs.#fields; )* + } + } + + impl #name { + /// Autogenerated by windmill-macros + pub fn parse(inner_content: &str) -> Self{ + let mut res = Self::default(); + lazy_static::lazy_static! { + static ref RE: regex::Regex = regex::Regex::new(#reg).unwrap(); + } + // Create lines stream + let mut lines = inner_content.lines(); + 'outer: while let Some(line) = lines.next() { + // If comment sign(s) on the right place + let mut comms = false; + // New instance + // We will apply it if in line only annotations + let mut new = Self::default(); + + 'inner: for (i, mat) in RE.find_iter(line).enumerate() { + + match mat.as_str(){ + #comm_lit if i == 0 => { + comms = true; + continue 'inner; + }, + + // Will expand into something like: + // "ann1" => new.ann1 = true, + // "ann2" => new.ann2 = true, + // "ann3" => new.ann3 = true, + #( stringify!(#fields) => new.#fields = true, )* + // Non annotations + _ => continue 'outer, + }; + } + + if !comms { + // We dont want to continue if line does not start with # + return res; + } + + // Apply changes + res |= new; + } + + res + } + } + }) +} diff --git a/backend/windmill-macros/tests/annotations.rs b/backend/windmill-macros/tests/annotations.rs new file mode 100644 index 0000000000..fd430dfaeb --- /dev/null +++ b/backend/windmill-macros/tests/annotations.rs @@ -0,0 +1,169 @@ +#[cfg(test)] +mod annotations_tests { + + extern crate windmill_macros; + use itertools::Itertools; + use windmill_macros::annotations; + + // Previous implementation. + // We have to make sure that new one works the same as old one + fn old(inner_content: &str) -> Annotations { + let annotations = inner_content + .lines() + .take_while(|x| x.starts_with("#")) + .map(|x| x.to_string().replace("#", "").trim().to_string()) + .collect_vec(); + + let ann1: bool = annotations.contains(&"ann1".to_string()); + let ann2: bool = annotations.contains(&"ann2".to_string()); + let ann3: bool = annotations.contains(&"ann3".to_string()); + let ann4: bool = annotations.contains(&"ann4".to_string()); + let ann5: bool = annotations.contains(&"ann5".to_string()); + + Annotations { ann1, ann2, ann3, ann4, ann5 } + } + + #[annotations("#")] + #[derive(Eq, PartialEq, Copy, Clone)] + pub struct Annotations { + pub ann1: bool, + pub ann2: bool, + pub ann3: bool, + pub ann4: bool, + pub ann5: bool, + } + + #[annotations("//")] + #[derive(Eq, PartialEq, Copy, Clone)] + pub struct SlashedAnnotations { + pub ann1: bool, + pub ann2: bool, + pub ann3: bool, + pub ann4: bool, + } + + #[annotations("--")] + #[derive(Eq, PartialEq, Copy, Clone)] + pub struct MinusedAnnotations { + pub ann1: bool, + pub ann2: bool, + } + + // e.g. rust, TS and JS + #[test] + fn slashed_annotations() { + let cont = "// ann1 +// ann2 +//ann3"; + assert_eq!( + SlashedAnnotations { ann1: true, ann2: true, ann3: true, ann4: false }, + SlashedAnnotations::parse(cont) + ); + } + + // e.g. Haskell, SQL + #[test] + fn minused_annotations() { + let cont = "-- ann1 +-- ann2"; + assert_eq!( + MinusedAnnotations { ann1: true, ann2: true }, + MinusedAnnotations::parse(cont) + ); + } + + #[test] + fn simple_integration() { + let cont = "# ann1"; + let expected = Annotations { ann1: true, ..Default::default() }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + + #[test] + fn multiline_integration() { + let cont = "# ann2 +# ann3 +# ann4 +# ann5 + "; + let expected = Annotations { + ann1: false, + ann2: true, + ann3: true, + ann4: true, + ann5: true, + // + }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + + #[test] + fn spacing_integration() { + // First line is ignored and not used + { + let cont = " +# ann2"; + let expected = Annotations { ..Default::default() }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + // Wrong spacing for ann3 + { + let cont = "# ann2 + # ann3"; + + let expected = Annotations { ann2: true, ..Default::default() }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + + // Drunk but valid spacing + { + let cont = "#ann1 +# ann2"; + let expected = Annotations { ann2: true, ann1: true, ..Default::default() }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + } + + #[test] + fn comments_inbetween_integration() { + let cont = "# ann2 +# Just comment, has nothing to do with annotations +# Another comment: ann1 ann2 ann3 +# ann4 is not valid annotation +# Actual annotation next line: +# ann5 + +# Should be ignored +# ann3 + "; + let expected = Annotations { ann2: true, ann5: true, ..Default::default() }; + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + + #[test] + fn hash_collision() { + // TODO + } + #[test] + fn non_matching_integration() { + { + let cont = r#" "ann1", ann2 "#; + let expected = Annotations::default(); + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + // Empty + { + let cont = ""; + let expected = Annotations::default(); + assert_eq!(expected, old(cont)); + assert_eq!(expected, Annotations::parse(cont)); + } + } +} diff --git a/backend/windmill-worker/nsjail/run.python3.config.proto b/backend/windmill-worker/nsjail/run.python3.config.proto index bbdf5ed306..06ced731c3 100644 --- a/backend/windmill-worker/nsjail/run.python3.config.proto +++ b/backend/windmill-worker/nsjail/run.python3.config.proto @@ -97,6 +97,13 @@ mount { is_bind: true } +mount { + dst: "/dev/shm" + fstype: "tmpfs" + rw: true + is_bind: false +} + mount { src: "/dev/random" dst: "/dev/random" diff --git a/backend/windmill-worker/src/bigquery_executor.rs b/backend/windmill-worker/src/bigquery_executor.rs index 1552686b79..2438392680 100644 --- a/backend/windmill-worker/src/bigquery_executor.rs +++ b/backend/windmill-worker/src/bigquery_executor.rs @@ -5,7 +5,6 @@ use futures::{FutureExt, TryFutureExt}; use serde_json::{json, value::RawValue, Value}; use windmill_common::error::to_anyhow; use windmill_common::jobs::QueuedJob; -use windmill_common::worker::get_sql_annotations; use windmill_common::{error::Error, worker::to_raw_value}; use windmill_parser_sql::{ parse_bigquery_sig, parse_db_resource, parse_sql_blocks, parse_sql_statement_named_params, @@ -238,7 +237,7 @@ pub async fn do_bigquery( return Err(Error::BadRequest("Missing database argument".to_string())); }; - let annotations = get_sql_annotations(query); + let annotations = windmill_common::worker::SqlAnnotations::parse(query); let service_account = CustomServiceAccount::from_json(&database) .map_err(|e| Error::ExecutionErr(e.to_string()))?; diff --git a/backend/windmill-worker/src/bun_executor.rs b/backend/windmill-worker/src/bun_executor.rs index 73511faada..0721918568 100644 --- a/backend/windmill-worker/src/bun_executor.rs +++ b/backend/windmill-worker/src/bun_executor.rs @@ -47,7 +47,7 @@ use windmill_common::{ get_latest_hash_for_path, jobs::{QueuedJob, PREPROCESSOR_FAKE_ENTRYPOINT}, scripts::ScriptLang, - worker::{exists_in_cache, get_annotation_ts, save_cache, write_file}, + worker::{exists_in_cache, save_cache, write_file}, DB, }; @@ -663,7 +663,7 @@ pub async fn prebundle_bun_script( if exists_in_cache(&local_path, &remote_path).await { return Ok(()); } - let annotation = get_annotation_ts(inner_content); + let annotation = windmill_common::worker::TypeScriptAnnotations::parse(inner_content); if annotation.nobundling { return Ok(()); } @@ -676,9 +676,9 @@ pub async fn prebundle_bun_script( &token, w_id, script_path, - if annotation.nodejs_mode { + if annotation.nodejs { LoaderMode::NodeBundle - } else if annotation.native_mode { + } else if annotation.native { LoaderMode::BrowserBundle } else { LoaderMode::BunBundle @@ -800,7 +800,7 @@ pub async fn handle_bun_job( new_args: &mut Option>>, occupancy_metrics: &mut OccupancyMetrics, ) -> error::Result> { - let mut annotation = windmill_common::worker::get_annotation_ts(inner_content); + let mut annotation = windmill_common::worker::TypeScriptAnnotations::parse(inner_content); let (mut has_bundle_cache, cache_logs, local_path, remote_path) = if requirements_o.is_some() && !annotation.nobundling && codebase.is_none() { @@ -822,7 +822,7 @@ pub async fn handle_bun_job( if !codebase.is_some() && !has_bundle_cache { let _ = write_file(job_dir, "main.ts", inner_content)?; - } else if !annotation.native_mode && codebase.is_none() { + } else if !annotation.native && codebase.is_none() { let _ = write_file(job_dir, "package.json", r#"{ "type": "module" }"#)?; }; @@ -830,7 +830,7 @@ pub async fn handle_bun_job( get_common_bun_proc_envs(Some(&base_internal_url)).await; if codebase.is_some() { - annotation.nodejs_mode = true + annotation.nodejs = true } let (main_override, apply_preprocessor) = match get_main_override(job.args.as_ref()) { Some(main_override) => { @@ -844,7 +844,7 @@ pub async fn handle_bun_job( }; #[cfg(not(feature = "enterprise"))] - if annotation.nodejs_mode || annotation.npm_mode { + if annotation.nodejs || annotation.npm { return Err(error::Error::ExecutionErr( "Nodejs / npm mode is an EE feature".to_string(), )); @@ -875,20 +875,20 @@ pub async fn handle_bun_job( pull_codebase(&job.workspace_id, codebase, job_dir).await?; } else if let Some(reqs) = requirements_o.as_ref() { let splitted = reqs.split(BUN_LOCKB_SPLIT).collect::>(); - if splitted.len() != 2 && !annotation.npm_mode { + if splitted.len() != 2 && !annotation.npm { return Err(error::Error::ExecutionErr( format!("Invalid requirements, expected to find //bun.lockb split pattern in reqs. Found: |{reqs}|") )); } let _ = write_file(job_dir, "package.json", &splitted[0])?; - let lockb = if annotation.npm_mode { "" } else { splitted[1] }; + let lockb = if annotation.npm { "" } else { splitted[1] }; if lockb != EMPTY_FILE { let mut skip_install = false; let mut create_buntar = false; let mut buntar_path = "".to_string(); - if !annotation.npm_mode { + if !annotation.npm { let _ = write_lockb(&splitted[1], job_dir).await?; let mut sha_path = sha2::Sha256::new(); @@ -921,7 +921,7 @@ pub async fn handle_bun_job( job_dir, worker_name, common_bun_proc_envs.clone(), - annotation.npm_mode, + annotation.npm, &mut Some(occupancy_metrics), ) .await?; @@ -963,7 +963,7 @@ pub async fn handle_bun_job( worker_name, false, None, - annotation.npm_mode, + annotation.npm, &mut Some(occupancy_metrics), ) .await?; @@ -971,19 +971,19 @@ pub async fn handle_bun_job( // } } - let mut init_logs = if annotation.native_mode { + let mut init_logs = if annotation.native { "\n\n--- NATIVE CODE EXECUTION ---\n".to_string() } else if has_bundle_cache { - if annotation.nodejs_mode { + if annotation.nodejs { "\n\n--- NODE BUNDLE SNAPSHOT EXECUTION ---\n".to_string() } else { "\n\n--- BUN BUNDLE SNAPSHOT EXECUTION ---\n".to_string() } } else if codebase.is_some() { "\n\n--- NODE CODEBASE SNAPSHOT EXECUTION ---\n".to_string() - } else if annotation.native_mode { + } else if annotation.native { "\n\n--- NATIVE CODE EXECUTION ---\n".to_string() - } else if annotation.nodejs_mode { + } else if annotation.nodejs { write_file(job_dir, "main.ts", &remove_pinned_imports(inner_content)?)?; "\n\n--- NODE CODE EXECUTION ---\n".to_string() } else { @@ -1003,7 +1003,7 @@ pub async fn handle_bun_job( } let write_wrapper_f = async { - if !has_bundle_cache && annotation.native_mode { + if !has_bundle_cache && annotation.native { return Ok(()) as error::Result<()>; } // let mut start = Instant::now(); @@ -1105,6 +1105,16 @@ try {{ if (step_id) {{ err["step_id"] = step_id; }} + const extra = {{}}; + Object.getOwnPropertyNames(e).forEach((key) => {{ + if (['line', 'name', 'stack', 'column', 'message', 'sourceURL', 'originalLine', 'originalColumn'].includes(key)) {{ + return; + }} + extra[key] = e[key]; + }}); + if (Object.keys(extra).length > 0) {{ + err["extra"] = extra; + }} await fs.writeFile("result.json", JSON.stringify(err)); process.exit(1); }} @@ -1116,7 +1126,7 @@ try {{ let reserved_variables_args_out_f = async { let args_and_out_f = async { - if !annotation.native_mode { + if !annotation.native { create_args_and_out_file(&client, job, job_dir, db).await?; } Ok(()) as Result<()> @@ -1133,7 +1143,7 @@ try {{ let build_cache = !has_bundle_cache && !annotation.nobundling && !codebase.is_some() - && (requirements_o.is_some() || annotation.native_mode); + && (requirements_o.is_some() || annotation.native); let write_loader_f = async { if build_cache { @@ -1143,9 +1153,9 @@ try {{ &client.get_token().await, &job.workspace_id, &job.script_path(), - if annotation.nodejs_mode { + if annotation.nodejs { LoaderMode::NodeBundle - } else if annotation.native_mode { + } else if annotation.native { LoaderMode::BrowserBundle } else { LoaderMode::BunBundle @@ -1161,7 +1171,7 @@ try {{ &client.get_token().await, &job.workspace_id, &job.script_path(), - if annotation.nodejs_mode { + if annotation.nodejs { LoaderMode::Node } else { LoaderMode::Bun @@ -1207,7 +1217,7 @@ try {{ } } } - if !annotation.native_mode { + if !annotation.native { let ex_wrapper = read_file_content(&format!("{job_dir}/wrapper.mjs")).await?; write_file( job_dir, @@ -1221,7 +1231,7 @@ try {{ } fs::remove_file(format!("{job_dir}/main.ts"))?; has_bundle_cache = true; - } else if annotation.nodejs_mode { + } else if annotation.nodejs { generate_wrapper_mjs( job_dir, &job.workspace_id, @@ -1237,9 +1247,14 @@ try {{ .await?; } } - if annotation.native_mode { + if annotation.native { #[cfg(not(feature = "deno_core"))] - return Ok(to_raw_value("").unwrap()); + { + tracing::error!( + r#""deno_core" feature is not activated, but "//native" annotation used. Returning empty value..."# + ); + return Ok(to_raw_value("").unwrap()); + } #[cfg(feature = "deno_core")] { @@ -1299,14 +1314,7 @@ try {{ job_dir, "run.config.proto", &NSJAIL_CONFIG_RUN_BUN_CONTENT - .replace( - "{LANG}", - if annotation.nodejs_mode { - "nodejs" - } else { - "bun" - }, - ) + .replace("{LANG}", if annotation.nodejs { "nodejs" } else { "bun" }) .replace("{JOB_DIR}", job_dir) .replace("{CACHE_DIR}", BUN_CACHE_DIR) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) @@ -1314,7 +1322,7 @@ try {{ "{SHARED_MOUNT}", &shared_mount.replace( "/tmp/shared", - if annotation.nodejs_mode { + if annotation.nodejs { "/tmp/nodejs/shared" } else { "/tmp/bun/shared" @@ -1324,7 +1332,7 @@ try {{ )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); - let args = if annotation.nodejs_mode { + let args = if annotation.nodejs { vec![ "--config", "run.config.proto", @@ -1368,7 +1376,7 @@ try {{ .stderr(Stdio::piped()); start_child_process(nsjail_cmd, NSJAIL_PATH.as_str()).await? } else { - let cmd = if annotation.nodejs_mode { + let cmd = if annotation.nodejs { let script_path = format!("{job_dir}/wrapper.mjs"); let mut bun_cmd = Command::new(&*NODE_BIN_PATH); @@ -1420,7 +1428,7 @@ try {{ start_child_process( cmd, - if annotation.nodejs_mode { + if annotation.nodejs { &*NODE_BIN_PATH } else { &*BUN_PATH @@ -1435,7 +1443,7 @@ try {{ mem_peak, canceled_by, child, - false, + !*DISABLE_NSJAIL, worker_name, &job.workspace_id, "bun run", @@ -1525,10 +1533,10 @@ pub async fn start_worker( let common_bun_proc_envs: HashMap = get_common_bun_proc_envs(Some(&base_internal_url)).await; - let mut annotation = windmill_common::worker::get_annotation_ts(inner_content); + let mut annotation = windmill_common::worker::TypeScriptAnnotations::parse(inner_content); //TODO: remove this when bun dedicated workers work without issues - annotation.nodejs_mode = true; + annotation.nodejs = true; let context = variables::get_reserved_variables( db, @@ -1582,7 +1590,7 @@ pub async fn start_worker( job_dir, worker_name, common_bun_proc_envs.clone(), - annotation.npm_mode, + annotation.npm, &mut None, ) .await?; @@ -1603,7 +1611,7 @@ pub async fn start_worker( worker_name, false, None, - annotation.npm_mode, + annotation.npm, &mut None, ) .await?; @@ -1681,7 +1689,7 @@ for await (const line of Readline.createInterface({{ input: process.stdin }})) { token, w_id, script_path, - if annotation.nodejs_mode { + if annotation.nodejs { LoaderMode::Node } else { LoaderMode::Bun @@ -1690,7 +1698,7 @@ for await (const line of Readline.createInterface({{ input: process.stdin }})) { .await?; } - if annotation.nodejs_mode && !codebase.is_some() { + if annotation.nodejs && !codebase.is_some() { generate_wrapper_mjs( job_dir, w_id, @@ -1706,7 +1714,7 @@ for await (const line of Readline.createInterface({{ input: process.stdin }})) { .await?; } - if annotation.nodejs_mode { + if annotation.nodejs { let script_path = format!("{job_dir}/wrapper.mjs"); handle_dedicated_process( diff --git a/backend/windmill-worker/src/deno_executor.rs b/backend/windmill-worker/src/deno_executor.rs index 491741b5f1..2a33bba2b5 100644 --- a/backend/windmill-worker/src/deno_executor.rs +++ b/backend/windmill-worker/src/deno_executor.rs @@ -126,6 +126,7 @@ pub async fn generate_deno_lock( "--unstable-http", "--lock=lock.json", "--frozen=false", + "--allow-import", "--import-map", &import_map_path, "main.ts", @@ -372,6 +373,7 @@ try {{ args.push(allow_read.as_str()); args.push("--allow-write=./"); args.push("--allow-env"); + args.push("--allow-import"); args.push("--allow-run=git,/usr/bin/chromium"); } else { args.push("-A"); diff --git a/backend/windmill-worker/src/handle_child.rs b/backend/windmill-worker/src/handle_child.rs index 791b60b9a6..6e7520daf8 100644 --- a/backend/windmill-worker/src/handle_child.rs +++ b/backend/windmill-worker/src/handle_child.rs @@ -414,9 +414,30 @@ async fn get_mem_peak(pid: Option, nsjail: bool) -> i32 { return -1; } let pid = if nsjail { - // This is a bit hacky, but the process id of the nsjail process is the pid of nsjail + 1. - // Ideally, we would get the number from fork() itself. This works in MOST cases. - pid.unwrap() + 1 + // Read /proc//task//children and extract pid + let nsjail_pid = pid.unwrap(); + let children_path = format!("/proc/{}/task/{}/children", nsjail_pid, nsjail_pid); + if let Ok(mut file) = File::open(children_path).await { + let mut contents = String::new(); + if tokio::io::AsyncReadExt::read_to_string(&mut file, &mut contents) + .await + .is_ok() + { + if let Some(child_pid) = contents.split_whitespace().next() { + if let Ok(child_pid) = child_pid.parse::() { + child_pid + } else { + return -1; + } + } else { + return -1; + } + } else { + return -1; + } + } else { + return -1; + } } else { pid.unwrap() }; diff --git a/backend/windmill-worker/src/js_eval.rs b/backend/windmill-worker/src/js_eval.rs index 15353ac4bc..da4eda39ef 100644 --- a/backend/windmill-worker/src/js_eval.rs +++ b/backend/windmill-worker/src/js_eval.rs @@ -247,7 +247,7 @@ pub async fn eval_timeout( #[cfg(not(feature = "deno_core"))] { #[allow(unreachable_code)] - return todo!(); + return Err(anyhow::anyhow!("Deno core is not enabled".to_string()).into()); } #[cfg(feature = "deno_core")] diff --git a/backend/windmill-worker/src/mssql_executor.rs b/backend/windmill-worker/src/mssql_executor.rs index f50bad4619..7c4724418c 100644 --- a/backend/windmill-worker/src/mssql_executor.rs +++ b/backend/windmill-worker/src/mssql_executor.rs @@ -9,7 +9,7 @@ use tokio::net::TcpStream; use tokio_util::compat::TokioAsyncWriteCompatExt; use uuid::Uuid; use windmill_common::error::{self, Error}; -use windmill_common::worker::{get_sql_annotations, to_raw_value}; +use windmill_common::worker::to_raw_value; use windmill_common::{error::to_anyhow, jobs::QueuedJob}; use windmill_parser_sql::{parse_db_resource, parse_mssql_sig}; use windmill_queue::{append_logs, CanceledBy}; @@ -68,7 +68,7 @@ pub async fn do_mssql( return Err(Error::BadRequest("Missing database argument".to_string())); }; - let annotations = get_sql_annotations(query); + let annotations = windmill_common::worker::SqlAnnotations::parse(query); let mut config = Config::new(); diff --git a/backend/windmill-worker/src/mysql_executor.rs b/backend/windmill-worker/src/mysql_executor.rs index 03cde1d508..3ed6a9bf34 100644 --- a/backend/windmill-worker/src/mysql_executor.rs +++ b/backend/windmill-worker/src/mysql_executor.rs @@ -13,7 +13,7 @@ use tokio::sync::Mutex; use windmill_common::{ error::{to_anyhow, Error}, jobs::QueuedJob, - worker::{get_sql_annotations, to_raw_value}, + worker::to_raw_value, }; use windmill_parser_sql::{ parse_db_resource, parse_mysql_sig, parse_sql_blocks, parse_sql_statement_named_params, @@ -148,7 +148,7 @@ pub async fn do_mysql( return Err(Error::BadRequest("Missing database argument".to_string())); }; - let annotations = get_sql_annotations(query); + let annotations = windmill_common::worker::SqlAnnotations::parse(query); let opts = OptsBuilder::default() .db_name(Some(database.database)) diff --git a/backend/windmill-worker/src/pg_executor.rs b/backend/windmill-worker/src/pg_executor.rs index 7c4192cf66..7702b73b03 100644 --- a/backend/windmill-worker/src/pg_executor.rs +++ b/backend/windmill-worker/src/pg_executor.rs @@ -30,7 +30,7 @@ use tokio_postgres::{ }; use uuid::Uuid; use windmill_common::error::{self, Error}; -use windmill_common::worker::{get_sql_annotations, to_raw_value, CLOUD_HOSTED}; +use windmill_common::worker::{to_raw_value, CLOUD_HOSTED}; use windmill_common::{error::to_anyhow, jobs::QueuedJob}; use windmill_parser::{Arg, Typ}; use windmill_parser_sql::{ @@ -191,7 +191,7 @@ pub async fn do_postgresql( return Err(Error::BadRequest("Missing database argument".to_string())); }; - let annotations = get_sql_annotations(query); + let annotations = windmill_common::worker::SqlAnnotations::parse(query); let sslmode = match database.sslmode.as_deref() { Some("allow") => "prefer".to_string(), diff --git a/backend/windmill-worker/src/php_executor.rs b/backend/windmill-worker/src/php_executor.rs index e62d96b3fd..b16e25f8ae 100644 --- a/backend/windmill-worker/src/php_executor.rs +++ b/backend/windmill-worker/src/php_executor.rs @@ -345,7 +345,7 @@ try {{ mem_peak, canceled_by, child, - false, + !*DISABLE_NSJAIL, worker_name, &job.workspace_id, "php run", diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 25a0d8756f..c2b486cd93 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -498,7 +498,10 @@ except BaseException as e: exc_type, exc_value, exc_traceback = sys.exc_info() tb = traceback.format_tb(exc_traceback) with open(result_json, 'w') as f: - err = {{ "message": str(e), "name": e.__class__.__name__, "stack": '\n'.join(tb[1:]) }} + err = {{ "message": str(e), "name": e.__class__.__name__, "stack": '\n'.join(tb[1:]) }} + extra = e.__dict__ + if extra and len(extra) > 0: + err['extra'] = extra flow_node_id = os.environ.get('WM_FLOW_STEP_ID') if flow_node_id: err['step_id'] = flow_node_id @@ -895,7 +898,7 @@ async fn handle_python_deps( let requirements = match requirements_o { Some(r) => r, None => { - let annotation = windmill_common::worker::get_annotation_python(inner_content); + let annotation = windmill_common::worker::PythonAnnotations::parse(inner_content); let mut already_visited = vec![]; let requirements = windmill_parser_py_imports::parse_python_imports( diff --git a/backend/windmill-worker/src/snowflake_executor.rs b/backend/windmill-worker/src/snowflake_executor.rs index bf9dae41ff..f89b29832a 100644 --- a/backend/windmill-worker/src/snowflake_executor.rs +++ b/backend/windmill-worker/src/snowflake_executor.rs @@ -9,7 +9,6 @@ use serde_json::{json, value::RawValue, Value}; use sha2::{Digest, Sha256}; use std::collections::HashMap; use windmill_common::error::to_anyhow; -use windmill_common::worker::get_sql_annotations; use windmill_common::jobs::QueuedJob; use windmill_common::{error::Error, worker::to_raw_value}; @@ -266,7 +265,7 @@ pub async fn do_snowflake( return Err(Error::BadRequest("Missing database argument".to_string())); }; - let annotations = get_sql_annotations(query); + let annotations = windmill_common::worker::SqlAnnotations::parse(query); let qualified_username = format!( "{}.{}", diff --git a/backend/windmill-worker/src/worker_lockfiles.rs b/backend/windmill-worker/src/worker_lockfiles.rs index e6458375cd..c2209d9e73 100644 --- a/backend/windmill-worker/src/worker_lockfiles.rs +++ b/backend/windmill-worker/src/worker_lockfiles.rs @@ -12,7 +12,7 @@ use windmill_common::flows::{FlowModule, FlowModuleValue}; use windmill_common::get_latest_deployed_hash_for_path; use windmill_common::jobs::JobPayload; use windmill_common::scripts::ScriptHash; -use windmill_common::worker::{get_annotation_ts, to_raw_value, to_raw_value_owned, write_file}; +use windmill_common::worker::{to_raw_value, to_raw_value_owned, write_file}; use windmill_common::{ error::{self, to_anyhow}, flows::FlowValue, @@ -953,10 +953,10 @@ async fn lock_modules<'c>( } if language == ScriptLang::Bun || language == ScriptLang::Bunnative { - let anns = get_annotation_ts(&content); - if anns.native_mode && language == ScriptLang::Bun { + let anns = windmill_common::worker::TypeScriptAnnotations::parse(&content); + if anns.native && language == ScriptLang::Bun { language = ScriptLang::Bunnative; - } else if !anns.native_mode && language == ScriptLang::Bunnative { + } else if !anns.native && language == ScriptLang::Bunnative { language = ScriptLang::Bun; }; } @@ -1003,10 +1003,10 @@ async fn lock_modules<'c>( fn skip_creating_new_lock(language: &ScriptLang, content: &str) -> bool { if language == &ScriptLang::Bun || language == &ScriptLang::Bunnative { - let anns = get_annotation_ts(&content); - if anns.native_mode && language == &ScriptLang::Bun { + let anns = windmill_common::worker::TypeScriptAnnotations::parse(&content); + if anns.native && language == &ScriptLang::Bun { return false; - } else if !anns.native_mode && language == &ScriptLang::Bunnative { + } else if !anns.native && language == &ScriptLang::Bunnative { return false; }; } @@ -1077,11 +1077,13 @@ async fn lock_modules_app( match new_lock { Ok(new_lock) => { append_logs(&job.id, &job.workspace_id, logs, db).await; - let anns = get_annotation_ts(&content); - let nlang = if anns.native_mode && language == ScriptLang::Bun { + let anns = + windmill_common::worker::TypeScriptAnnotations::parse( + &content, + ); + let nlang = if anns.native && language == ScriptLang::Bun { Some(ScriptLang::Bunnative) - } else if !anns.native_mode && language == ScriptLang::Bunnative - { + } else if !anns.native && language == ScriptLang::Bunnative { Some(ScriptLang::Bun) } else { None @@ -1437,7 +1439,7 @@ async fn capture_dependency_job( } ScriptLang::Bun | ScriptLang::Bunnative => { let npm_mode = npm_mode.unwrap_or_else(|| { - windmill_common::worker::get_annotation_ts(job_raw_code).npm_mode + windmill_common::worker::TypeScriptAnnotations::parse(job_raw_code).npm }); if !raw_deps { let _ = write_file(job_dir, "main.ts", job_raw_code)?; diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index 034f1109a4..a5d2740c7c 100644 --- a/benchmarks/lib.ts +++ b/benchmarks/lib.ts @@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts"; import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts"; import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts"; -export const VERSION = "v1.407.1"; +export const VERSION = "v1.409.2"; export async function login(email: string, password: string): Promise { return await windmill.UserService.login({ diff --git a/cli/apps.ts b/cli/apps.ts index 1330c3ba80..ca966e2112 100644 --- a/cli/apps.ts +++ b/cli/apps.ts @@ -1,6 +1,6 @@ // deno-lint-ignore-file no-explicit-any import { requireLogin, resolveWorkspace, validatePath } from "./context.ts"; -import { colors, Command, log, SEP, Table, yamlParse } from "./deps.ts"; +import { colors, Command, log, SEP, Table, yamlParseFile } from "./deps.ts"; import * as wmill from "./gen/services.gen.ts"; import { ListableApp, Policy } from "./gen/types.gen.ts"; @@ -25,7 +25,7 @@ export async function pushApp( return; } alreadySynced.push(localPath); - remotePath.replaceAll(SEP, "/"); + remotePath = remotePath.replaceAll(SEP, "/"); let app: any = undefined; // deleting old app if it exists in raw mode try { @@ -40,8 +40,8 @@ export async function pushApp( if (!localPath.endsWith(SEP)) { localPath += SEP; } - const localAppRaw = await Deno.readTextFile(localPath + "app.yaml"); - const localApp = yamlParse(localAppRaw) as AppFile; + const path = localPath + "app.yaml"; + const localApp = (await yamlParseFile(path)) as AppFile; function replaceInlineScripts(rec: any) { if (!rec) { diff --git a/cli/conf.ts b/cli/conf.ts index fa18de880b..eab154fec9 100644 --- a/cli/conf.ts +++ b/cli/conf.ts @@ -1,4 +1,4 @@ -import { log, yamlParse } from "./deps.ts"; +import { log, yamlParseFile } from "./deps.ts"; export interface SyncOptions { stateful?: boolean; @@ -40,9 +40,7 @@ export interface Codebase { export async function readConfigFile(): Promise { try { - const conf = yamlParse( - await Deno.readTextFile("wmill.yaml") - ) as SyncOptions; + const conf = (await yamlParseFile("wmill.yaml")) as SyncOptions; if (conf?.defaultTs == undefined) { log.warn( "No defaultTs defined in your wmill.yaml. Using 'bun' as default." diff --git a/cli/deps.ts b/cli/deps.ts index a8e14f0d3d..53e96a4f9c 100644 --- a/cli/deps.ts +++ b/cli/deps.ts @@ -21,7 +21,29 @@ export { copy } from "jsr:@std/io/copy"; export { readAll } from "jsr:@std/io/read-all"; export * as log from "jsr:@std/log"; -export { stringify as yamlStringify, parse as yamlParse } from "jsr:@std/yaml"; +export { stringify as yamlStringify } from "jsr:@std/yaml"; + +import { parse as yamlParse, ParseOptions } from "jsr:@std/yaml"; + +export async function yamlParseFile(path: string, options: ParseOptions = {}) { + try { + return yamlParse(await Deno.readTextFile(path), options); + } catch (e) { + throw new Error(`Error parsing yaml ${path}`, { cause: e }); + } +} + +export function yamlParseContent( + path: string, + content: string, + options: ParseOptions = {} +) { + try { + return yamlParse(content, options); + } catch (e) { + throw new Error(`Error parsing yaml ${path}`, { cause: e }); + } +} // other diff --git a/cli/flow.ts b/cli/flow.ts index 601f0be0bc..edca024f66 100644 --- a/cli/flow.ts +++ b/cli/flow.ts @@ -1,7 +1,7 @@ // deno-lint-ignore-file no-explicit-any import { GlobalOptions, isSuperset } from "./types.ts"; import { Confirm, SEP, log, yamlStringify } from "./deps.ts"; -import { colors, Command, Table, yamlParse } from "./deps.ts"; +import { colors, Command, Table, yamlParseFile } from "./deps.ts"; import * as wmill from "./gen/services.gen.ts"; import { requireLogin, resolveWorkspace, validatePath } from "./context.ts"; @@ -29,21 +29,23 @@ export function replaceInlineScripts( ) { modules.forEach((m) => { if (m.value.type == "rawscript") { - const path = m.value.content.split(" ")[1]; - m.value.content = Deno.readTextFileSync(localPath + path); - const lock = m.value.lock; - if (removeLocks && removeLocks.includes(path)) { - m.value.lock = undefined; - } else if ( - lock && - typeof lock == "string" && - lock.trimStart().startsWith("!inline ") - ) { - const path = lock.split(" ")[1]; - try { - m.value.lock = readInlinePathSync(localPath + path); - } catch { - log.error(`Lock file ${path} not found`); + if (m.value.content.startsWith("!inline")) { + const path = m.value.content.split(" ")[1]; + m.value.content = Deno.readTextFileSync(localPath + path); + const lock = m.value.lock; + if (removeLocks && removeLocks.includes(path)) { + m.value.lock = undefined; + } else if ( + lock && + typeof lock == "string" && + lock.trimStart().startsWith("!inline ") + ) { + const path = lock.split(" ")[1]; + try { + m.value.lock = readInlinePathSync(localPath + path); + } catch { + log.error(`Lock file ${path} not found`); + } } } } else if (m.value.type == "forloopflow") { @@ -87,8 +89,7 @@ export async function pushFlow( if (!localPath.endsWith(SEP)) { localPath += SEP; } - const localFlowRaw = await Deno.readTextFile(localPath + "flow.yaml"); - const localFlow = yamlParse(localFlowRaw) as FlowFile; + const localFlow = (await yamlParseFile(localPath + "flow.yaml")) as FlowFile; replaceInlineScripts(localFlow.value.modules, localPath, undefined); @@ -120,6 +121,7 @@ export async function pushFlow( }); } catch (e) { throw new Error( + //@ts-ignore `Failed to create flow ${remotePath}: ${e.body ?? e.message}` ); } diff --git a/cli/folder.ts b/cli/folder.ts index 0820cc0c9d..5cf2812670 100644 --- a/cli/folder.ts +++ b/cli/folder.ts @@ -73,6 +73,7 @@ export async function pushFolder( }, }); } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -87,6 +88,7 @@ export async function pushFolder( }, }); } catch (e) { + //@ts-ignore throw Error(`Failed to create folder ${name}: ${e.body ?? e.message}`); } } diff --git a/cli/gen/core/OpenAPI.ts b/cli/gen/core/OpenAPI.ts index 6af5246be2..cddc3f88de 100644 --- a/cli/gen/core/OpenAPI.ts +++ b/cli/gen/core/OpenAPI.ts @@ -54,7 +54,7 @@ export const OpenAPI: OpenAPIConfig = { PASSWORD: undefined, TOKEN: getEnv("WM_TOKEN"), USERNAME: undefined, - VERSION: '1.401.0', + VERSION: '1.407.2', WITH_CREDENTIALS: true, interceptors: { request: new Interceptors(), diff --git a/cli/gen/types.gen.ts b/cli/gen/types.gen.ts index 92bfe933d9..fe297f8bde 100644 --- a/cli/gen/types.gen.ts +++ b/cli/gen/types.gen.ts @@ -1015,6 +1015,9 @@ export type FlowModule = { skip_if_stopped?: boolean; expr: string; }; + skip_if?: { + expr: string; + }; sleep?: InputTransform; cache_ttl?: number; timeout?: number; @@ -1176,6 +1179,7 @@ export type FlowStatusModule = { approver: string; }>; failed_retries?: Array<(string)>; + skipped?: boolean; }; export type type4 = 'WaitingForPriorSteps' | 'WaitingForEvents' | 'WaitingForExecutor' | 'InProgress' | 'Success' | 'Failure'; diff --git a/cli/instance.ts b/cli/instance.ts index 30459d9ef6..bc3f0968b7 100644 --- a/cli/instance.ts +++ b/cli/instance.ts @@ -3,7 +3,7 @@ import { path, Confirm, yamlStringify, - yamlParse, + yamlParseFile, Command, setClient, Table, @@ -459,9 +459,9 @@ async function instancePush(opts: GlobalOptions & InstanceSyncOptions) { } try { - const workspaceSettings = yamlParse( - await Deno.readTextFile("settings.yaml") - ) as SimplifiedSettings; + const workspaceSettings = (await yamlParseFile( + "settings.yaml" + )) as SimplifiedSettings; await workspaceSetup( { token: instance.token, @@ -578,6 +578,7 @@ async function whoami(opts: {}) { log.info(JSON.stringify(whoamiInfo, null, 2)); } catch (error) { log.error( + //@ts-ignore colors.red(`Failed to retrieve whoami information: ${error.message}`) ); } @@ -620,7 +621,7 @@ const command = new Command() .description("Remove an instance") .complete("instance", async () => (await allInstances()).map((x) => x.name)) .arguments("") - .action(async (instance) => { + .action(async (instance: any) => { const instances = await allInstances(); const choice = (await Select.prompt({ diff --git a/cli/main.ts b/cli/main.ts index 161f00763e..b9c92ece0d 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -60,7 +60,7 @@ export { // } // }); -export const VERSION = "1.407.1"; +export const VERSION = "1.409.2"; const command = new Command() .name("wmill") diff --git a/cli/metadata.ts b/cli/metadata.ts index a3b4738cb7..92ac7dfc4b 100644 --- a/cli/metadata.ts +++ b/cli/metadata.ts @@ -1,6 +1,13 @@ // deno-lint-ignore-file no-explicit-any import { GlobalOptions } from "./types.ts"; -import { SEP, colors, log, path, yamlParse, yamlStringify } from "./deps.ts"; +import { + SEP, + colors, + log, + path, + yamlParseFile, + yamlStringify, +} from "./deps.ts"; import { ScriptMetadata, defaultScriptMetadata, @@ -119,9 +126,9 @@ export async function generateFlowLockInternal( return remote_path; } - const flowValue = yamlParse( - await Deno.readTextFile(folder! + SEP + "flow.yaml") - ) as FlowFile; + const flowValue = (await yamlParseFile( + folder! + SEP + "flow.yaml" + )) as FlowFile; if (!justUpdateMetadataLock) { const changedScripts = []; @@ -798,7 +805,7 @@ export async function parseMetadataFile( try { metadataFilePath = scriptPath + ".script.yaml"; await Deno.stat(metadataFilePath); - const payload: any = yamlParse(await Deno.readTextFile(metadataFilePath)); + const payload: any = await yamlParseFile(metadataFilePath); replaceLock(payload); return { @@ -840,9 +847,9 @@ export async function parseMetadataFile( codebases, false ); - scriptInitialMetadata = yamlParse( - await Deno.readTextFile(metadataFilePath) - ) as ScriptMetadata; + scriptInitialMetadata = (await yamlParseFile( + metadataFilePath + )) as ScriptMetadata; replaceLock(scriptInitialMetadata); } catch (e) { log.info( @@ -868,8 +875,7 @@ interface Lock { const WMILL_LOCKFILE = "wmill-lock.yaml"; export async function readLockfile(): Promise { try { - const lockfile = await Deno.readTextFile(WMILL_LOCKFILE); - const read = yamlParse(lockfile); + const read = await yamlParseFile(WMILL_LOCKFILE); if (typeof read == "object") { return read as Lock; } else { diff --git a/cli/settings.ts b/cli/settings.ts index b3a1b6a272..328a6d0e25 100644 --- a/cli/settings.ts +++ b/cli/settings.ts @@ -1,7 +1,7 @@ import { yamlStringify } from "./deps.ts"; import { Confirm } from "./deps.ts"; import { colors } from "./deps.ts"; -import { yamlParse } from "./deps.ts"; +import { yamlParseFile } from "./deps.ts"; import { log } from "./deps.ts"; import { compareInstanceObjects } from "./instance.ts"; import { isSuperset } from "./types.ts"; @@ -259,17 +259,24 @@ export async function pushWorkspaceKey( } } +export async function readInstanceSettings() { + let localSettings: GlobalSetting[] = []; + + try { + localSettings = (await yamlParseFile( + "instance_settings.yaml" + )) as GlobalSetting[]; + } catch { + log.warn("No instance_settings.yaml found"); + } + return localSettings; +} + export async function pullInstanceSettings(preview = false) { const remoteSettings = await wmill.listGlobalSettings(); if (preview) { - let localSettings: GlobalSetting[] = []; - - try { - localSettings = yamlParse( - await Deno.readTextFile("instance_settings.yaml") - ) as GlobalSetting[]; - } catch {} + const localSettings: GlobalSetting[] = await readInstanceSettings(); return compareInstanceObjects( remoteSettings, @@ -294,9 +301,7 @@ export async function pushInstanceSettings( baseUrl?: string ) { const remoteSettings = await wmill.listGlobalSettings(); - let localSettings = (await Deno.readTextFile("instance_settings.yaml") - .then((raw) => yamlParse(raw)) - .catch(() => [])) as GlobalSetting[]; + let localSettings: GlobalSetting[] = await readInstanceSettings(); if (baseUrl) { localSettings = localSettings.filter((s) => s.name !== "base_url"); @@ -354,6 +359,17 @@ export async function pushInstanceSettings( } } +export async function readLocalConfigs() { + let localConfigs: Config[] = []; + + try { + localConfigs = (await yamlParseFile("instance_configs.yaml")) as Config[]; + } catch { + log.warn("No instance_configs.yaml found"); + } + return localConfigs; +} + export async function pullInstanceConfigs(preview = false) { const remoteConfigs = (await wmill.listConfigs()).map((x) => { return { @@ -363,12 +379,7 @@ export async function pullInstanceConfigs(preview = false) { }); if (preview) { - let localConfigs: Config[] = []; - try { - localConfigs = yamlParse( - await Deno.readTextFile("instance_configs.yaml") - ) as Config[]; - } catch {} + const localConfigs: Config[] = await readLocalConfigs(); return compareInstanceObjects( remoteConfigs, @@ -395,9 +406,7 @@ export async function pushInstanceConfigs(preview: boolean = false) { name: removeWorkerPrefix(x.name), }; }); - const localConfigs = (await Deno.readTextFile("instance_configs.yaml") - .then((raw) => yamlParse(raw)) - .catch(() => [])) as Config[]; + const localConfigs = await readLocalConfigs(); if (preview) { return compareInstanceObjects( @@ -415,7 +424,9 @@ export async function pushInstanceConfigs(preview: boolean = false) { } try { await wmill.updateConfig({ - name: config.name.startsWith('worker__') ? config.name : `worker__${config.name}`, + name: config.name.startsWith("worker__") + ? config.name + : `worker__${config.name}`, requestBody: config.config, }); } catch (err) { diff --git a/cli/sync.ts b/cli/sync.ts index 3a12272b6e..ce539b7a1f 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -9,7 +9,7 @@ import { path, log, yamlStringify, - yamlParse, + yamlParseContent, SEP, } from "./deps.ts"; import * as wmill from "./gen/services.gen.ts"; @@ -112,7 +112,7 @@ async function addCodebaseDigestIfRelevant( if (isTs) { const c = findCodebase(path, codebases); if (c) { - const parsed: any = yamlParse(content); + const parsed: any = yamlParseContent(path, content); if (parsed && typeof parsed == "object") { parsed["codebase"] = c.digest; parsed["lock"] = undefined; @@ -660,7 +660,7 @@ export async function elementsToMap( if (json) { o = JSON.parse(content); } else { - o = yamlParse(content); + o = yamlParseContent(path, content); } if (o["is_secret"]) { continue; @@ -704,7 +704,7 @@ async function compareDynFSElement( function parseYaml(k: string, v: string) { if (k.endsWith(".script.yaml")) { - const o: any = yamlParse(v); + const o: any = yamlParseContent(k, v); if (typeof o == "object") { if (Array.isArray(o?.["lock"])) { o["lock"] = o["lock"].join("\n"); @@ -715,7 +715,7 @@ async function compareDynFSElement( } return o; } else if (k.endsWith(".app.yaml")) { - const o: any = yamlParse(v); + const o: any = yamlParseContent(k, v); const o2 = o["policy"]; if (typeof o2 == "object") { @@ -728,7 +728,7 @@ async function compareDynFSElement( } return o; } else { - return yamlParse(v); + return yamlParseContent(k, v); } } for (const [k, v] of Object.entries(m1)) { diff --git a/cli/types.ts b/cli/types.ts index 84691a37e2..e264521cb7 100644 --- a/cli/types.ts +++ b/cli/types.ts @@ -6,7 +6,7 @@ import { colors, log, path, - yamlParse, + yamlParseContent, yamlStringify, } from "./deps.ts"; import { pushApp } from "./apps.ts"; @@ -115,7 +115,7 @@ export async function pushObj( newObj: any, plainSecrets: boolean, alreadySynced: string[], - message?: string, + message?: string ) { const typeEnding = getTypeStrFromPath(p); @@ -155,7 +155,7 @@ export async function pushObj( export function parseFromPath(p: string, content: string): any { return p.endsWith(".yaml") - ? yamlParse(content) + ? yamlParseContent(p, content) : p.endsWith(".json") ? JSON.parse(content) : content; @@ -164,7 +164,7 @@ export function parseFromFile(p: string): any { if (p.endsWith(".json")) { return JSON.parse(Deno.readTextFileSync(p)); } else if (p.endsWith(".yaml") || p.endsWith(".yml")) { - return yamlParse(Deno.readTextFileSync(p)); + return yamlParseContent(p, Deno.readTextFileSync(p)); } else { throw new Error("Could not read file " + p); } @@ -227,7 +227,7 @@ export function getTypeStrFromPath( return typeEnding; } else { if (isFileResource(p)) { - return "resource" + return "resource"; } throw new Error("Could not infer type of path " + JSON.stringify(parsed)); } diff --git a/cli/user.ts b/cli/user.ts index f95747306a..2ddeb997c9 100644 --- a/cli/user.ts +++ b/cli/user.ts @@ -13,7 +13,7 @@ import { log, Table, yamlStringify, - yamlParse, + yamlParseFile, } from "./deps.ts"; import * as wmill from "./gen/services.gen.ts"; import { @@ -170,6 +170,7 @@ export async function pushWorkspaceUser( }, }); } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -189,6 +190,7 @@ export async function pushWorkspaceUser( }, }); } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -251,6 +253,7 @@ export async function pushGroup( }, }); } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -301,6 +304,7 @@ export async function pushGroup( }); } } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -329,6 +333,7 @@ export async function pushGroup( }, }); } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -368,11 +373,13 @@ export async function pushGroup( }); } } catch (e) { + //@ts-ignore console.error(e.body); throw e; } } } catch (e) { + //@ts-ignore console.error(e.body); throw e; } @@ -383,11 +390,7 @@ export async function pullInstanceUsers(preview: boolean = false) { const remoteUsers = await wmill.globalUsersExport(); if (preview) { - let localUsers: ExportedUser[] = []; - try { - const raw = await Deno.readTextFile("instance_users.yaml"); - localUsers = yamlParse(raw) as ExportedUser[]; - } catch {} + const localUsers: ExportedUser[] = await readInstanceUsers(); return compareInstanceObjects(remoteUsers, localUsers, "email", "user"); } else { log.info("Pulling users from instance..."); @@ -399,11 +402,31 @@ export async function pullInstanceUsers(preview: boolean = false) { } } +export async function readInstanceUsers() { + let localUsers: ExportedUser[] = []; + try { + localUsers = (await yamlParseFile("instance_users.yaml")) as ExportedUser[]; + } catch { + log.warn("No instance_users.yaml file found"); + } + return localUsers; +} + +export async function readInstanceGroups() { + let localGroups: InstanceGroup[] = []; + try { + localGroups = (await yamlParseFile( + "instance_groups.yaml" + )) as ExportedInstanceGroup[]; + } catch { + log.warn("No instance_groups.yaml file found"); + } + return localGroups; +} + export async function pushInstanceUsers(preview: boolean = false) { const remoteUsers = await wmill.globalUsersExport(); - const localUsers = (await Deno.readTextFile("instance_users.yaml") - .then((raw) => yamlParse(raw)) - .catch(() => [])) as ExportedUser[]; + const localUsers: ExportedUser[] = await readInstanceUsers(); if (preview) { return compareInstanceObjects(localUsers, remoteUsers, "email", "user"); @@ -421,11 +444,7 @@ export async function pullInstanceGroups(preview = false) { const remoteGroups = await wmill.exportInstanceGroups(); if (preview) { - let localGroups: InstanceGroup[] = []; - try { - const raw = await Deno.readTextFile("instance_groups.yaml"); - localGroups = yamlParse(raw) as InstanceGroup[]; - } catch {} + const localGroups = await readInstanceGroups(); return compareInstanceObjects(remoteGroups, localGroups, "name", "group"); } else { log.info("Pulling groups from instance..."); @@ -441,9 +460,7 @@ export async function pullInstanceGroups(preview = false) { export async function pushInstanceGroups(preview: boolean = false) { const remoteGroups = await wmill.exportInstanceGroups(); - const localGroups = (await Deno.readTextFile("instance_groups.yaml") - .then((raw) => yamlParse(raw)) - .catch(() => [])) as ExportedInstanceGroup[]; + const localGroups = await readInstanceGroups(); if (preview) { return compareInstanceObjects(localGroups, remoteGroups, "name", "group"); diff --git a/cli/utils.ts b/cli/utils.ts index 5f2de77f6b..fcb07bea9e 100644 --- a/cli/utils.ts +++ b/cli/utils.ts @@ -55,7 +55,10 @@ export function deepEqual(a: T, b: T): boolean { if (a.valueOf !== Object.prototype.valueOf) { return a.valueOf() === b.valueOf(); } - if (a.toString !== Object.prototype.toString) { + if ( + a.toString !== Object.prototype.toString && + typeof a.toString == "function" + ) { return a.toString() === b.toString(); } diff --git a/docker/RHEL9/Dockerfile b/docker/RHEL9/Dockerfile index 3a9ed24bb6..10e0f01096 100644 --- a/docker/RHEL9/Dockerfile +++ b/docker/RHEL9/Dockerfile @@ -4,11 +4,13 @@ ARG PYTHON_IMAGE=python:3.11.10-slim-bookworm FROM ${RUST_IMAGE} AS rust_base -RUN yum install -y rust-toolset - RUN yum update -y && \ yum install -y git openssl-devel npm nodejs rustfmt +# Install rust manually +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" + RUN CARGO_NET_GIT_FETCH_WITH_CLI=true cargo install cargo-chef --version ^0.1 WORKDIR /windmill @@ -35,7 +37,7 @@ COPY /backend/parsers/windmill-parser-wasm/pkg/ /backend/parsers/windmill-parser COPY /typescript-client/docs/ /frontend/static/tsdocs/ RUN npm run generate-backend-client -ENV NODE_OPTIONS "--max-old-space-size=8192" +ENV NODE_OPTIONS "--max-old-space-size=10240" RUN npm run build diff --git a/docker/RHEL9/README.md b/docker/RHEL9/README.md index af858d8be5..17d39b86ca 100644 --- a/docker/RHEL9/README.md +++ b/docker/RHEL9/README.md @@ -3,17 +3,16 @@ This directory contains the Dockerfiles for building Windmill binaries for Red Hat Linux 9. We build Windmill on the Red Hat Universal Base Image 9. Windmill requires the xmlsec1-devel package which is not available in the default UBI9 repositories. It is however included in the CodeReady Builder for RHEL9 repository which requires a RedHat subscription. -Moreover, only rust v1.75 is supported on Red Hat Linux 9. To make Windmill compatible with Rust v1.75, you need to pin the following libraries: -``` -aws-config = "=1.4.0" -aws-sdk-sts = "=1.25.0" -aws-sdk-ssooidc = "=1.25.0" -aws-sdk-sso = "=1.25.0" -``` - -Make sure to include `aws-sdk-ssooidc` and `aws-sdk-sso` in the Cargo.toml of windmill-common as well to enforce the correct versions of the nested dependencies. Make them optional and include them in the `parquet` feature. -It's also possible that you need to add `#[async_recursion]` to the `lock_modules` function in the `backend/windmill-worker/src/worker_lockfiles.rs` file for it to compile. Once the image is built, you can simply copy the binary on any Red Hat Linux 9 machine and run it. You will just need to install the xmlsec1 package which can be installed directly using `yum/dnf install xmlsec1`. - +## Notes + - you will need to register on Red Hat and have an individual developer subscription and pass the username and password to docker build: + ``` + docker build \ + -f docker/RHEL9/Dockerfile \ + --build-arg features="$features" \ + --secret id=rh_username,src=/path/to/rh_username \ + --secret id=rh_password,src=/path/to/rh_password \ + . + ``` \ No newline at end of file diff --git a/frontend/openapi-ts-error-1726231138297.log b/frontend/openapi-ts-error-1726231138297.log deleted file mode 100644 index f78fbf5b1c..0000000000 --- a/frontend/openapi-ts-error-1726231138297.log +++ /dev/null @@ -1,28 +0,0 @@ -Error parsing /git/windmill/backend/windmill-api/openapi.yaml: duplicated mapping key (8350:3) - - 8347 | application/json: - 8348 | schema: {} - 8349 | - 8350 | /w/{workspace}/job_helpers/loa ... -----------^ - 8351 | get: - 8352 | summary: Load a preview of ... -ParserError: Error parsing /git/windmill/backend/windmill-api/openapi.yaml: duplicated mapping key (8350:3) - - 8347 | application/json: - 8348 | schema: {} - 8349 | - 8350 | /w/{workspace}/job_helpers/loa ... -----------^ - 8351 | get: - 8352 | summary: Load a preview of ... - at Object.parse (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/parsers/yaml.js:44:23) - at getResult (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/util/plugins.js:116:22) - at runNextPlugin (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/util/plugins.js:64:32) - at /git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/util/plugins.js:55:9 - at new Promise () - at Object.run (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/util/plugins.js:54:12) - at parseFile (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/parse.js:130:38) - at parse (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/parse.js:56:30) - at async $RefParser.parse (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/index.js:115:28) - at async $RefParser.resolve (/git/windmill/frontend/node_modules/@apidevtools/json-schema-ref-parser/dist/lib/index.js:145:13) \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f417c3c288..87816755db 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.407.1", + "version": "1.409.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.407.1", + "version": "1.409.2", "license": "AGPL-3.0", "dependencies": { "@aws-crypto/sha256-js": "^4.0.0", diff --git a/frontend/package.json b/frontend/package.json index 0ee11de7ca..0a29d95564 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.407.1", + "version": "1.409.2", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/frontend/src/lib/components/ArgInput.svelte b/frontend/src/lib/components/ArgInput.svelte index 093d7010dc..80537e4d44 100644 --- a/frontend/src/lib/components/ArgInput.svelte +++ b/frontend/src/lib/components/ArgInput.svelte @@ -141,6 +141,9 @@ defaultValue?: any, nnullable?: boolean ) { + if (label == 'toString' && typeof value == 'function') { + value = undefined + } if ((value == undefined || value == null) && !ignoreValueUndefined) { value = defaultValue if (defaultValue === undefined || defaultValue === null) { diff --git a/frontend/src/lib/components/AssignableTags.svelte b/frontend/src/lib/components/AssignableTags.svelte index a09aaab4db..ce58c61d67 100644 --- a/frontend/src/lib/components/AssignableTags.svelte +++ b/frontend/src/lib/components/AssignableTags.svelte @@ -6,6 +6,7 @@ import AssignableTagsInner from './AssignableTagsInner.svelte' export let placement: 'bottom-end' | 'top-end' = 'bottom-end' + export let color: 'nord' | 'dark' = 'dark' - {/if} {/each} - {#each logins.filter((x) => !providersType?.includes(x)) as login} + {#each logins.filter((login) => !providersType?.includes(login.type)) as login} {/each} {/if} diff --git a/frontend/src/lib/components/OAuthSetting.svelte b/frontend/src/lib/components/OAuthSetting.svelte index 4e84f796ce..505db1c36a 100644 --- a/frontend/src/lib/components/OAuthSetting.svelte +++ b/frontend/src/lib/components/OAuthSetting.svelte @@ -50,6 +50,10 @@ > {#if enabled}
+
+