Skip to main content

Bash / PowerShell Quickstart

In this quick start guide, we will write our first script in Bash and PowerShell.


Scripts are the basic building blocks in Windmill. They can be run and scheduled as standalone, chained together to create Flows or displayed with a personalized User Interface as Apps.

Scripts consist of 2 parts:

  • Code.
  • Settings: settings & metadata about the Script such as its path, summary, description, jsonschema of its inputs (inferred from its signature).

When stored in a code repository, those 2 parts are stored separately at <path>.ts and <path>.script.yaml.

Below is a simple example of a script built in Bash/Powershell with Windmill:

# shellcheck shell=bash
# arguments of the form X="$I" are parsed as parameters X of type string
url="${1:-default value}"

status_code=$(curl -s -o /dev/null -w "%{http_code}" $url)

if [[ $status_code == 2* ]] || [[ $status_code == 3* ]]; then
echo "The URL is reachable!"
else
echo "The URL is not reachable."
fi

In this quick start guide, we'll create a script that greets the operator running it.

From the Home page, click +Script. This will take you to the first step of script creation: Metadata.

Settings

New script

As part of the settings menu, each script has metadata associated with it, enabling it to be defined and configured in depth.

  • Path is the Script's unique identifier that consists of the script's owner, and the script's name. The owner can be either a user, or a group (folder).
  • Summary (optional) is a short, human-readable summary of the Script. It will be displayed as a title across Windmill. If omitted, the UI will use the path by default.
  • Language of the script.
  • Description is where you can give instructions through the auto-generated UI to users on how to run your Script. It supports markdown.
  • Script kind: Action (by default), Trigger, Approval or Error Handler. This acts as a tag to filter appropriate scripts from the flow editor.

This menu also has additional settings, such as:

Now click on the code editor on the left side.

Code

Windmill provides an online editor to work on your Scripts. The left-side is the editor itself. The right-side previews the UI that Windmill will generate from the Script's signature - this will be visible to the users of the Script. You can preview that UI, provide input values, and test your script there.

Editor for Bash

Bash

As we picked Bash for this example, Windmill provided some Bash boilerplate. Let's take a look:

# shellcheck shell=bash
# arguments of the form X="$I" are parsed as parameters X of type string
msg="$1"
dflt="${2:-default value}"

# the last line of the stdout is the return value
echo "Hello $msg"

In Bash, the arguments are inferred from the arguments requiring a $1, $2, $3. Default arguments can be specified using the syntax above: dflt="${2:-default value}".

The last line of the output, here echo "Hello $msg", is the return value, which might be useful if the script is used in a flow or app to pass its result on.

PowerShell

As we picked PowerShell for this example, Windmill provided some PowerShell boilerplate. Let's take a look:

param($Msg, $Dflt = "default value", [int]$Nb = 3)

# Import-Module MyModule

# the last line of the stdout is the return value
Write-Output "Hello $Msg"

In PowerShell, the arguments are inferred from the param instruction. It has to be first in the script. Default arguments can be specified using the syntax above: $argument_name = "Its default value".

The last line of the output, here Write-Output "Hello $Msg", is the return value, which might be useful if the script is used in a flow or app to pass its result on.

Instant Preview & Testing

Look at the UI preview on the right: it was updated to match the input signature. Run a test (Ctrl + Enter) to verify everything works.


You can change how the UI behaves by changing the main signature. For example, if you add a default for the name argument, the UI won't consider this field as required anymore.

argument_name="${1:-Its default value}"

Now let's go to the last step: the "Generated UI" settings.

Customize UI

From the Settings menu, the "Generated UI" tab lets you customize the script's arguments.

The UI is generated from the Script's main function signature, but you can add additional constraints here. For example, we could use the Customize property: add a regex by clicking on Pattern to make sure users are providing a name with only alphanumeric characters: ^[A-Za-z0-9]+$. Let's still allow numbers in case you are some tech billionaire's kid.

Advanced settings for Bash

Run!

We're done! Now let's look at what users of the script will do. Click on the Deploy button to load the script. You'll see the user input form we defined earlier.

Note that Scripts are versioned in Windmill, and each script version is uniquely identified by a hash.

Fill in the input field, then hit "Run". You should see a run view, as well as your logs. All script runs are also available in the Runs menu on the left.

Run Hello in Bash

You can also choose to run the script from the CLI with the pre-made Command-Line Interface call.

JSON result

The last line returned by the script will be the string result. To use a json result instead, output your result in ./result.json and it will be automatically picked-up and considered as the JSON result for Bash and Powershell scripts.

Run Docker Containers

In some cases where your task requires a complex set of dependencies or is implemented in a non-supported language, you can still include it as a flow step or individual script.

Windmill supports running any docker container through its Bash support. As a pre-requisite, the host docker daemon needs to be mounted into the worker container. This is done through a simple volume mount: /var/run/docker.sock:/var/run/docker.sock.

What's next?

This script is a minimal working example, but there's a few more steps that can be useful in a real-world use case:

Scripts are immutable and there is an hash for each deployment of a given script. Scripts are never overwritten and referring to a script by path is referring to the latest deployed hash at that path.

For each script, a UI is autogenerated from the jsonchema inferred from the script signature, and can be customized further as standalone or embedded into rich UIs using the App builder.

In addition to the UI, sync and async webhooks are generated for each deployment.