Skip to main content

Check out Port for yourself 

Windmill job

This example helps internal developer teams to trigger Windmill job using Port's self service actions. In particular, you will create a blueprint for windmillJob that will be connected to a backend action. You will then add some configuration files (invocations.json) to control the payload and trigger your Windmill job directly from Port using async/sync execution method.

Prerequisites

  • This guide assumes you have Kafka credentials available and ready to use within your Port account.
  • You will need an accessible k8s cluster. If you don't have one, here is how to quickly set-up a minikube cluster.
  • Helm - required to install the Port Agent with Windmill job setup.

Windmill - Async execution

  1. Create a Windmill job blueprint in Port.

    Windmill job blueprint (Click to expand)
    {
    "identifier": "windmillJob",
    "description": "This blueprint represents a windmill job in our software catalog",
    "title": "Windmill",
    "icon": "DefaultProperty",
    "schema": {
    "properties": {
    "workspace": {
    "type": "string",
    "title": "Workspace"
    },
    "path": {
    "type": "string",
    "title": "File Path"
    },
    "trigerredBy": {
    "type": "string",
    "title": "Triggered By",
    "format": "user"
    },
    "createdAt": {
    "type": "string",
    "format": "date-time",
    "title": "Created At"
    }
    },
    "required": []
    },
    "mirrorProperties": {},
    "calculationProperties": {},
    "relations": {}
    }
  2. Create a Port action using the following JSON definition:

    Port action (Click to expand)
    [
    {
    "identifier":"trigger_windmill_pipeline",
    "title":"Trigger Windmill Pipeline",
    "icon":"DefaultProperty",
    "userInputs":{
    "properties":{
    "workspace":{
    "title":"Workspace",
    "description":"The Workspace identifier",
    "type":"string"
    },
    "file_path":{
    "title":"File Path",
    "description":"The path of the job script in the workspace, including the /u and /f prefix",
    "type":"string"
    },
    "job_data":{
    "title":"Job Data",
    "description":"The data to be passed to the job in order to execute successfully",
    "type":"object"
    }
    },
    "required":[
    "workspace",
    "file_path",
    "job_data"
    ],
    "order":[
    "workspace",
    "file_path",
    "job_data"
    ]
    },
    "invocationMethod":{
    "type":"WEBHOOK",
    "agent":true,
    "synchronized":false,
    "method":"POST",
    "url":"https://app.windmill.dev/api"
    },
    "trigger":"CREATE",
    "requiredApproval":false
    }
    ]
  3. Create a JSON file (invocations.json) in your working directory.

    Invocation Mapping (Click to expand)
    invocations.json
    [
    {
    "enabled": ".action == \"trigger_windmill_pipeline\"",
    "url": "\"https://app.windmill.dev\" as $baseUrl | .payload.properties.workspace as $workspace | .payload.properties.file_path as $path | $baseUrl + \"/api/w/\" + $workspace + \"/jobs/run/f/\" + $path",
    "headers": {
    "Authorization": "\"Bearer \" + env.WINDMILL_TOKEN",
    "Content-Type": "\"application/json\""
    },
    "body": ".payload.properties.job_data",
    "report": {
    "status": "if .response.statusCode == 201 and (.response.text != null) then \"SUCCESS\" else \"FAILURE\" end",
    "link": "\"https://app.windmill.dev/api/w/\" + .body.payload.properties.workspace + \"/jobs/run/f/\" + .body.payload.properties.file_path",
    "externalRunId": ".response.text"
    }
    }
    ]
  4. Run the helm command below to install port agent for Windmill job.

    Port agent installation for a Windmill job (Click to expand)

    Remember to replace the boilerplate credentials in the helm command with your actual credentials.

    helm repo add port-labs https://port-labs.github.io/helm-charts

    helm repo update

    helm install my-port-agent port-labs/port-agent \
    --create-namespace --namespace port-agent \
    --set env.normal.PORT_ORG_ID=YOUR_ORG_ID \
    --set env.normal.KAFKA_CONSUMER_GROUP_ID=YOUR_KAFKA_CONSUMER_GROUP \
    --set env.secret.KAFKA_CONSUMER_USERNAME=YOUR_KAFKA_USERNAME \
    --set env.secret.KAFKA_CONSUMER_PASSWORD=YOUR_KAFKA_PASSWORD
    --set env.normal.KAFKA_CONSUMER_BROKERS=PORT_KAFKA_BROKERS \
    --set env.normal.STREAMER_NAME=KAFKA \
    --set env.normal.KAFKA_CONSUMER_AUTHENTICATION_MECHANISM=SCRAM-SHA-512 \
    --set env.normal.KAFKA_CONSUMER_AUTO_OFFSET_RESET=earliest \
    --set env.normal.KAFKA_CONSUMER_SECURITY_PROTOCOL=SASL_SSL \
    --set env.secret.WINDMILL_TOKEN=YOUR_WINDMILL_TOKEN \
    --set-file controlThePayloadConfig=./invocations.json
  5. Run this action with some input:

    {
    "workspace": "demo",
    "file_path": "f/examples/ban_user_example",
    "job_data": {
    "value": "batman",
    "reason": "Gotham city in need of superhero",
    "database": "$res:f/examples/demo_windmillshowcases",
    "username": "Jack",
    "slack_channel": "bans"
    }
    }

Windmill - Sync execution

  1. Create a windmill job blueprint in Port.

    Windmill job blueprint (Click to expand)
    {
    "identifier": "windmillJob",
    "description": "This blueprint represents a windmill job in our software catalog",
    "title": "Windmill",
    "icon": "DefaultProperty",
    "schema": {
    "properties": {
    "workspace": {
    "type": "string",
    "title": "Workspace"
    },
    "path": {
    "type": "string",
    "title": "File Path"
    },
    "trigerredBy": {
    "type": "string",
    "title": "Triggered By",
    "format": "user"
    },
    "createdAt": {
    "type": "string",
    "format": "date-time",
    "title": "Created At"
    }
    },
    "required": []
    },
    "mirrorProperties": {},
    "calculationProperties": {},
    "relations": {}
    }
  2. Create a Port action using the following JSON definition:

    Port action (Click to expand)
    [
    {
    "identifier":"trigger_windmill_pipeline",
    "title":"Trigger Windmill Pipeline",
    "icon":"DefaultProperty",
    "userInputs":{
    "properties":{
    "workspace":{
    "title":"Workspace",
    "description":"The Workspace identifier",
    "type":"string"
    },
    "file_path":{
    "title":"File Path",
    "description":"The path of the job script in the workspace, including the /u and /f prefix",
    "type":"string"
    },
    "job_data":{
    "title":"Job Data",
    "description":"The data to be passed to the job in order to execute successfully",
    "type":"object"
    }
    },
    "required":[
    "workspace",
    "file_path",
    "job_data"
    ],
    "order":[
    "workspace",
    "file_path",
    "job_data"
    ]
    },
    "invocationMethod":{
    "type":"WEBHOOK",
    "agent":true,
    "synchronized":false,
    "method":"POST",
    "url":"https://app.windmill.dev/api"
    },
    "trigger":"CREATE",
    "requiredApproval":false
    }
    ]
  3. Create a JSON file (invocations.json) in your working directory.

    Invocation Mapping (Click to expand)
    invocations.json
    [
    {
    "enabled": ".action == \"trigger_windmill_pipeline\"",
    "url": "\"https://app.windmill.dev\" as $baseUrl | .payload.properties.workspace as $workspace | .payload.properties.file_path as $path | $baseUrl + \"/api/w/\" + $workspace + \"/jobs/run_wait_result/f/\" + $path",
    "headers": {
    "Authorization": "\"Bearer \" + env.WINDMILL_TOKEN",
    "Content-Type": "\"application/json\""
    },
    "body": ".payload.properties.job_data",
    "report": {
    "status": "if .response.statusCode == 201 and (.response.json.error | not) then \"SUCCESS\" else \"FAILURE\" end",
    "link": "\"https://app.windmill.dev/api/w/\" + .body.payload.properties.workspace + \"/jobs/run_wait_result/f/\" + .body.payload.properties.file_path"
    }
    }
    ]
  4. Run the helm command below to install a port agent for Windmill job.

    Port agent installation for a Windmill job (Click to expand)

    Remember to replace the boilerplate credentials in the helm command with your actual credentials.

    helm repo add port-labs https://port-labs.github.io/helm-charts

    helm repo update

    helm install my-port-agent port-labs/port-agent \
    --create-namespace --namespace port-agent \
    --set env.normal.PORT_ORG_ID=YOUR_ORG_ID \
    --set env.normal.KAFKA_CONSUMER_GROUP_ID=YOUR_KAFKA_CONSUMER_GROUP \
    --set env.secret.KAFKA_CONSUMER_USERNAME=YOUR_KAFKA_USERNAME \
    --set env.secret.KAFKA_CONSUMER_PASSWORD=YOUR_KAFKA_PASSWORD
    --set env.normal.KAFKA_CONSUMER_BROKERS=PORT_KAFKA_BROKERS \
    --set env.normal.STREAMER_NAME=KAFKA \
    --set env.normal.KAFKA_CONSUMER_AUTHENTICATION_MECHANISM=SCRAM-SHA-512 \
    --set env.normal.KAFKA_CONSUMER_AUTO_OFFSET_RESET=earliest \
    --set env.normal.KAFKA_CONSUMER_SECURITY_PROTOCOL=SASL_SSL \
    --set env.secret.WINDMILL_TOKEN=YOUR_WINDMILL_TOKEN \
    --set-file controlThePayloadConfig=./invocations.json
  5. Run this action with some input:

    {
    "workspace": "demo",
    "file_path": "f/examples/ban_user_example",
    "job_data": {
    "value": "batman",
    "reason": "Gotham city in need of superhero",
    "database": "$res:f/examples/demo_windmillshowcases",
    "username": "Jack",
    "slack_channel": "bans"
    }
    }