Git Product home page Git Product logo

windmill-labs / windmill Goto Github PK

View Code? Open in Web Editor NEW
9.2K 38.0 410.0 141.04 MB

Open-source developer platform to turn scripts into workflows and UIs. Fastest workflow engine (5x vs Airflow). Open-source alternative to Airplane and Retool.

Home Page: https://windmill.dev

License: Other

Shell 0.10% Dockerfile 0.07% Rust 12.28% Python 0.56% JavaScript 3.23% CSS 0.47% HTML 55.11% TypeScript 6.76% Svelte 21.23% PLpgSQL 0.02% Go 0.04% PowerShell 0.14%
low-code open-source platform python typescript postgresql self-hostable

windmill's Introduction

windmill.dev

Open-source developer infrastructure for internal tools (APIs, background jobs, workflows and UIs). Self-hostable alternative to Retool, Pipedream, Superblocks and a simplified Temporal with autogenerated UIs and custom UIs to trigger workflows and scripts as internal apps.

Scripts are turned into sharable UIs automatically, and can be composed together into flows or used into richer apps built with low-code. Supported script languages supported are: Python, TypeScript, Go, Bash, SQL, and GraphQL.

Package version Docker Image CI Package version

Commit activity Discord Shield

Try it - Docs - Discord - Hub - Contributor's guide

Windmill - Developer platform for APIs, background jobs, workflows and UIs

Windmill is fully open-sourced (AGPLv3) and Windmill Labs offers dedicated instance and commercial support and licenses.

Windmill Diagram

main.mp4

Main Concepts

  1. Define a minimal and generic script in Python, TypeScript, Go or Bash that solves a specific task. The code can be defined in the provided Web IDE or synchronized with your own GitHub repo (e.g. through VS Code extension):

    Step 1

  2. Your scripts parameters are automatically parsed and generate a frontend.

Step 2

Step 3

  1. Make it flow! You can chain your scripts or scripts made by the community shared on WindmillHub.

    Step 3

  2. Build complex UIs on top of your scripts and flows.

    Step 4

Scripts and flows can also be triggered by a cron schedule (e.g. '_/5 _ * * *') or through webhooks.

You can build your entire infra on top of Windmill!

Show me some actual script code

//import any dependency  from npm
import * as wmill from "windmill-client"
import * as cowsay from '[email protected]';

// fill the type, or use the +Resource type to get a type-safe reference to a resource
type Postgresql = {
  host: string;
  port: number;
  user: string;
  dbname: string;
  sslmode: string;
  password: string;
};

export async function main(
  a: number,
  b: "my" | "enum",
  c: Postgresql,
  d = "inferred type string from default arg",
  e = { nested: "object" }
  //f: wmill.Base64
) {
  const email = process.env["WM_EMAIL"];
  // variables are permissioned and by path
  let variable = await wmill.getVariable("f/company-folder/my_secret");
  const lastTimeRun = await wmill.getState();
  // logs are printed and always inspectable
  console.log(cowsay.say({ text: "hello " + email + " " + lastTimeRun }));
  await wmill.setState(Date.now());

  // return is serialized as JSON
  return { foo: d, variable };
}

CLI

We have a powerful CLI to interact with the windmill platform and sync your scripts from local files, GitHub repos and to run scripts and flows on the instance from local commands. See more details.

CLI Screencast

Running scripts locally

You can run your script locally easily, you simply need to pass the right environment variables for the wmill client library to fetch resources and variables from your instance if necessary. See more: https://www.windmill.dev/docs/advanced/local_development.

To develop & test locally scripts & flows, we recommend using the Windmill VS Code extension: https://www.windmill.dev/docs/cli_local_dev/vscode-extension.

Stack

  • Postgres as the database.
  • Backend in Rust with the following highly-available and horizontally scalable. Architecture:
    • Stateless API backend.
    • Workers that pull jobs from a queue in Postgres (and later, Kafka or Redis. Upvote #173 if interested).
  • Frontend in Svelte.
  • Scripts executions are sandboxed using Google's nsjail.
  • Javascript runtime is the deno_core rust library (which itself uses the rusty_v8 and hence V8 underneath).
  • TypeScript runtime is Bun and deno.
  • Python runtime is python3.
  • Golang runtime is 1.19.1.

Fastest Self-Hostable Workflow Engine

We have compared Windmill to other self-hostable workflow engines (Airflow, Prefect & Temporal) and Windmill is the most performant solution for both benchmarks: one flow composed of 40 lightweight tasks & one flow composed of 10 long-running tasks.

All methodology & results on our Benchmarks page.

Fastest workflow engine

Security

Sandboxing

Windmill can use nsjail. It is production multi-tenant grade secure. Do not take our word for it, take fly.io's one.

Secrets, credentials and sensitive values

There is one encryption key per workspace to encrypt the credentials and secrets stored in Windmill's K/V store.

In addition, we strongly recommend that you encrypt the whole Postgres database. That is what we do at https://app.windmill.dev.

Performance

Once a job started, there is no overhead compared to running the same script on the node with its corresponding runner (Deno/Go/Python/Bash). The added latency from a job being pulled from the queue, started, and then having its result sent back to the database is ~50ms. A typical lightweight deno job will take around 100ms total.

Architecture

How to self-host

We only provide docker-compose setup here. For more advanced setups, like compiling from source or using without a postgres super user, see Self-Host documentation.

Docker compose

Windmill can be deployed using 3 files: (docker-compose.yml, Caddyfile and a .env) in a single command.

Make sure Docker is started, and run:

curl https://raw.githubusercontent.com/windmill-labs/windmill/main/docker-compose.yml -o docker-compose.yml
curl https://raw.githubusercontent.com/windmill-labs/windmill/main/Caddyfile -o Caddyfile
curl https://raw.githubusercontent.com/windmill-labs/windmill/main/.env -o .env

docker compose up -d

Go to http://localhost et voilà :)

The default super-admin user is: [email protected] / changeme.

From there, you can follow the setup app and create other users.

More details in Self-Host Documention.

Kubernetes (k8s) and Helm charts

We publish helm charts at: https://github.com/windmill-labs/windmill-helm-charts.

Run from binaries

Each release includes the corresponding binaries for x86_64. You can simply download the latest windmill binary using the following set of bash commands.

BINARY_NAME='windmill-amd64' # or windmill-ee-amd64 for the enterprise edition
LATEST_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/windmill-labs/windmill/releases/latest)
LATEST_VERSION=$(echo $LATEST_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/')
ARTIFACT_URL="https://github.com/windmill-labs/windmill/releases/download/$LATEST_VERSION/$BINARY_NAME"
wget "$ARTIFACT_URL" -O windmill

OAuth, SSO & SMTP

Windmill Community Edition allows to configure the OAuth, SSO (including Google Workspace SSO, Microsoft/Azure and Okta) directly from the UI in the superadmin settings. Do note that there is a limit of 10 SSO users on the community edition.

See documentation.

Commercial license

To self-host Windmill, you must respect the terms of the AGPLv3 license which you do not need to worry about for personal uses. For business uses, you should be fine if you do not re-expose Windmill in any way to your users and are comfortable with AGPLv3.

To re-expose any Windmill parts to your users as a feature of your product, or to build a feature on top of Windmill, to comply with AGPLv3 your product must be AGPLv3 or you must get a commercial license. Contact us at [email protected] if you have any doubts.

In addition, a commercial license grants you a dedicated engineer to transition your current infrastructure to Windmill, support with tight SLA, and our global cache sync for high-performance/no dependency cache miss of cluster from 10+ nodes to 200+ nodes.

Integrations

In Windmill, integrations are referred to as resources and resource types. Each Resource has a Resource Type that defines the schema that the resource needs to implement.

On self-hosted instances, you might want to import all the approved resource types from WindmillHub. A setup script will prompt you to have it being synced automatically everyday.

Environment Variables

Environment Variable name Default Description Api Server/Worker/All
DATABASE_URL The Postgres database url. All
WORKER_GROUP default The worker group the worker belongs to and get its configuration pulled from Worker
MODE standalone The mode if the binary. Possible values: standalone, worker, server All
METRICS_ADDR None (ee only) The socket addr at which to expose Prometheus metrics at the /metrics path. Set to "true" to expose it on port 8001 All
JSON_FMT false Output the logs in json format instead of logfmt All
BASE_URL http://localhost:8000 The base url that is exposed publicly to access your instance. Is overriden by the instance settings if any. Server
SCRIPT_TOKEN_EXPIRY 900 The default duration period of the ephemeral-token generated at the beginning of a script Worker
ZOMBIE_JOB_TIMEOUT 30 The timeout after which a job is considered to be zombie if the worker did not send pings about processing the job (every server check for zombie jobs every 30s) Server
RESTART_ZOMBIE_JOBS true If true then a zombie job is restarted (in-place with the same uuid and some logs), if false the zombie job is failed Server
SLEEP_QUEUE 50 The number of ms to sleep in between the last check for new jobs in the DB. It is multiplied by NUM_WORKERS such that in average, for one worker instance, there is one pull every SLEEP_QUEUE ms. Worker
MAX_LOG_SIZE 500000 The maximum number of characters a job can emit (log + result) Worker
DISABLE_NUSER false If Nsjail is enabled, disable the nsjail's clone_newuser setting Worker
KEEP_JOB_DIR false Keep the job directory after the job is done. Useful for debugging. Worker
LICENSE_KEY (EE only) None License key checked at startup for the Enterprise Edition of Windmill Worker
S3_CACHE_BUCKET (EE only) None The S3 bucket to sync the cache of the workers to Worker
SLACK_SIGNING_SECRET None The signing secret of your Slack app. See Slack documentation Server
COOKIE_DOMAIN None The domain of the cookie. If not set, the cookie will be set by the browser based on the full origin Server
DENO_PATH /usr/bin/deno The path to the deno binary. Worker
PYTHON_PATH /usr/local/bin/python3 The path to the python binary. Worker
GO_PATH /usr/bin/go The path to the go binary. Worker
GOPRIVATE The GOPRIVATE env variable to use private go modules Worker
GOPROXY The GOPROXY env variable to use Worker
NETRC The netrc content to use a private go registry Worker
PIP_INDEX_URL None The index url to pass for pip. Worker
PIP_EXTRA_INDEX_URL None The extra index url to pass to pip. Worker
PIP_TRUSTED_HOST None The trusted host to pass to pip. Worker
PATH None The path environment variable, usually inherited Worker
HOME None The home directory to use for Go and Bash , usually inherited Worker
DATABASE_CONNECTIONS 50 (Server)/3 (Worker) The max number of connections in the database connection pool All
SUPERADMIN_SECRET None A token that would let the caller act as a virtual superadmin [email protected] Server
TIMEOUT_WAIT_RESULT 20 The number of seconds to wait before timeout on the 'run_wait_result' endpoint Worker
QUEUE_LIMIT_WAIT_RESULT None The number of max jobs in the queue before rejecting immediately the request in 'run_wait_result' endpoint. Takes precedence on the query arg. If none is specified, there are no limit. Worker
DENO_AUTH_TOKENS None Custom DENO_AUTH_TOKENS to pass to worker to allow the use of private modules Worker
DISABLE_RESPONSE_LOGS false Disable response logs Server

Run a local dev setup

only Frontend

This will use the backend of https://app.windmill.dev but your own frontend with hot-code reloading.

  1. Install caddy
  2. Go to frontend/:
    1. npm install, npm run generate-backend-client then npm run dev
    2. In another shell sudo caddy run --config CaddyfileRemote
  3. Et voilà, windmill should be available at http://localhost/

Backend + Frontend

See the ./frontend/README_DEV.md file for all running options.

  1. Create a Postgres Database for Windmill and create an admin role inside your Postgres setup. The easiest way to get a working db is to run
    cargo install sqlx-cli
    env DATABASE_URL=<YOUR_DATABASE_URL> sqlx migrate run
    
    This will also avoid compile time issue with sqlx's query! macro
  2. Install nsjail and have it accessible in your PATH
  3. Install deno and python3, have the bins at /usr/bin/deno and /usr/local/bin/python3
  4. Install caddy
  5. Install the lld linker
  6. Go to frontend/:
    1. npm install, npm run generate-backend-client then npm run dev
    2. You might need to set some extra heap space for the node runtime export NODE_OPTIONS="--max-old-space-size=4096"
    3. In another shell npm run build otherwise the backend will not find the frontend/build folder and will not compile.
    4. In another shell sudo caddy run --config Caddyfile
  7. Go to backend/: env DATABASE_URL=<DATABASE_URL_TO_YOUR_WINDMILL_DB> RUST_LOG=info cargo run
  8. Et voilà, windmill should be available at http://localhost/

Contributors

Copyright

Windmill Labs, Inc 2023

windmill's People

Contributors

adam-kov avatar antrix avatar audriusbutkevicius avatar axelbdt avatar axisofentropy avatar bgoosmanviz avatar d10sfan avatar dependabot[bot] avatar ex0ns avatar fatonramadani avatar gbouv avatar github-actions[bot] avatar hcourdent avatar hugocasa avatar hurricankai avatar imsingee avatar invakid404 avatar jaller94 avatar jneeee avatar knowsuchagency avatar lfanew avatar lplit avatar martysohio avatar mogul avatar mrl5 avatar rubenfiszel avatar ryanrich avatar sindresvendby avatar sqwishy avatar wendrul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

windmill's Issues

Add opt-in and very user & privacy friendly telemetry for self-hosting

There are no metrics on self-hosting usage which means there are no metrics usable on that front

To avoid self-host installation to have to dig hole into their firewalls, one idea is to a soft telemetry frontend side:

  1. For first time user, opt-in prompt to ping at the beginning of a session a telemetry endpoint, and to include in that ping one installation id
  2. Have a flag in the installation to completely disable that prompt

Approval step for flows starting with interactive slack message to approver

Step of flows are solely script or other flows for now.

An approval step could be defined as: This step sends an approval request using one of the selected channel and is waiting for an external signal that correspond to the approval to go to the next step.

This could be used for instance to ask permission to the right resource owner or manager before proceeding with the rest of the flow.

More e2e playwright tests

A few scenarios to cover

  • Add a variable + edit it + delete
  • Add a resource type + create a resource of that resource + edit it + delete resource + delete resource type
  • Write a new script + preview it + save it + run it + edit it + run it
  • Write a new Push flow + preview it + save it + run it + edit it + run it
  • Write a new Pull flow with a schedule + preview it + run it + edit it + run it
  • New schedule + run it + edit it + run it

Make it easy for contributors to run their own stack for debugging

My personal way of debugging a PR quickly is to run:

docker run --privileged --rm -it --network=host -e="RUST_LOG=info" -e "DATABASE_URL=postgres://postgres:changeme@localhost/windmill?sslmode=disable" registry.wimill.xyz/windmill-labs/windmill:pr-<PR_NUMBER>

It requires:

  • The local private registry registry.wimill.xyz to be accessible
  • A local postgres instance

Makes this kind of setup accessible for external contributors

Make python lsp support arbitrary imports

Currently the python lsp relies for the dependencies import on having had all its import being pre-defined in a Pipfile. That makes the experience brittle (the version of the dependencies are as old as the Dockerfile itself and limited: only the imports selected in the Pipfile have a great support.

One strategy would be to spawn one venv by websocket session, and catch dependencies changes or relevant commands to install locally the imports. For performance purpose, one would share a cache between all the sessions

Add internal variable to store state of stateful flows (enabling triggers)

Triggers are essentially a script/action + schedule + a state.

The state can be stored as a variable that is specific to the instance of flows in which it is.

We can imagine the following syntax:

wmill.getInternalState("mykey", myvalue)
wmill.setInternalState("mykey", myvalue)

which would implicitly (through the env variable WM_FLOW) take the flow id and use the user-hidden variable i/<flow_id>/<step>/mykey

Classify scripts by category + Icon + search

The current product makes sense for a tiny set of community scripts.

We want an exhaustive set (see #15 ) and as such we need to better categorize the scripts (which for now have no category concepts).

For improved UX, we are likely to also want to have an medium size icon for each category

Last but not least, for every interactions that could pick from a community scripts, we want to display a sample of it ("Most popular? Most relevant given context ?) and have a search field to search for the relevant script.

The search function should use keyword from summary, description.

We can imagine later using neural net search engine and encode scripts in a manifold. A simpler version of this is to start with tags.

bug: script execution does not work on arm64

Describe the bug A clear and concise description of what the bug is.
after cloned the project I login as admin. and then I create a script. and click run preview

To Reproduce Steps to reproduce the behavior:

  1. cloned the project
  2. run docker volume create caddy_data && docker-compose up
  3. go to ui, login as admin
  4. create a script, and run preview
  5. check the log window

Expected behavior A clear and concise description of what you expected to
happen.
the script is expected to run successfully

Screenshots If applicable, add screenshots to help explain your problem.
image

Additional context Add any other context about the problem here.

Rework visibility of runs for script belonging to groups

The default visibility of runs is the one of the permissioned_as which might not be sensible for groups given the current UX. Indeed, even for scripts belong to group, currently only yourself may be able to see the run.

Option 1:
Keep visibility as-is but provided a "Run as " trigger button. Complexify the product overall as now users have to be aware that the one running the script might have lessened his privilege

Option 2:
Provide a flag: Share run with the group owning the script that could be toggled by default or not.

Option 2 seems more intuitive to me atm

Setup minimal e2e test

And run it as part of ci:

Login -> Create Script -> Run preview -> Save script -> Run Script with arbitrary arguments -> Check results in a timely manner

Internal server error when saving script with syntax error

Describe the bug
Internal server error reported in the browser when saving invalid python script.

To Reproduce
Steps to reproduce the behavior:

  1. Scripts -> New script
  2. Set valid "name" for the script
  3. Click "Next"
  4. Modify example python script and make syntax error in it.
  5. Click "Save (commit)"

Current behaviour:
There will be "Internal server error" reported (see screenshot)

Expected behaviour:
Error pointing to script error (second message on the screenshot).

Screenshots
image

First class concept of script triggers

Script triggers are scripts that are solely meant as trigger of flows.
They are essentially a normal script + schedule + internal variables. This will unlock automations with external services that do not rely on configuring webhooks

feature: Editor console auto-scroll down

It would be great if the editor console could automatically scroll down with the page rather than having to manually expand and close it to see further content.

Screenshot 2022-06-07 at 10 32 28

--- --- ---

Screenshot 2022-06-07 at 10 20 33

Typo on site homepage

Describe the bug
Typo under "UI? Done" section of homepage. Need a space between "scripts.Gain"

To Reproduce
Steps to reproduce the behavior:

  1. Go to windmill.dev
  2. Error

Expected behavior
A space between "scripts." and "Gain"

Let me know if you need more details. 😄

Generalize queue and worker to being able to be run on external systems

Windmill should always be able to work out-of-the box but we should generalize the queue and worker component such that for instance the queue instead of being on postgres would have an adapter for:

  • kafka
  • redis
  • ...

and the worker could be run on:

  • cloudflare worker
  • AWS Lambda
  • GCP cloud function
  • GCP cloud run
  • ....

bug: Windmill logging into undefined user and workspace

Describe the bug A clear and concise description of what the bug is.
Windmill automatically logging into undefined user and undefined workspace.

To Reproduce Steps to reproduce the behavior:

  1. Go to 'Windmil'
  2. Click on Windmill Cloud button'https://app.windmill.dev/user/login'
  3. See error in undefined user and workspace

Expected behavior A clear and concise description of what you expected to
happen.

Windmill should sign into my user account and default workspace or ask me to select a workspace

Screenshots If applicable, add screenshots to help explain your problem.
Screenshot 2022-06-03 at 14 41 02
Screenshot 2022-06-03 at 14 41 47
Screenshot 2022-06-03 at 14 42 20

Windmill version "Running windmill version (backend): v. v1.8.6-36-g0fe276b".

Additional context Add any other context about the problem here.

Use typescript type system to enable narrower types inferring

//JSONSCHEMA => type string + regex constraint
type string_regex<S extends string> = String

//JSONSCHEMA => type string + email format
type string_email = String

//JSONSCHEMA => type object + resource type as passed in the S literal type
type ResourceType<S extends string> = {}

// one can even extends that type to pass field hints to the script if wanted
interface MyType extends ResourceType<"my_type"> {
    myfield: number
}

// examples

let a: string_regex<"/s.*/"> = "s"

const c: ResourceType<"postgres"> = {
    host: "localhost",
    ...
}

//The description of the function will be used as script description, the description of the params as ... params description
/**
 * my function description
 * @param pg my ph description
 * @param pg_2 my p second description
 * @param reg my z description
 */
function main(pg: ResourceType<"postgres">, pg_2: MyType,
    reg: string_regex<"my_regex">, e: "alt1" | "alt2", ls: string[]) {
}

Make it explicit in the list of the tokens which one is the one of the current session

Describe the bug Can not delete token and "undefined" email displayed in user settings

To Reproduce:

  1. login with default admin account using "login without third party"
  2. go to "user settings"
  3. change default password
  4. click red "delete" in list of tokens
  5. Error message is displayed
  6. refresh page
  7. "undefined" is shown instead of email address

Am I partially logged out after that? (i am guessing that i am trying to remove token used in current session)

image

Windmill version: windmill.dev backend v. v1.6.1-4-g02c8bea

In-Flow script editor

Currently when building flows, and the script needed for a particular step does not exist yet, an user has to iterate separately on the script, save and go back and forth with the flows.

A much better UX would be to allow for edition and embedding of scripts directly in the flow builder. The embedded script editor must have an option to save permanently the script

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.