mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 00:02:23 +00:00
feat: interactive slack approvals (#4942)
* feat: interactive slack approvals * move form creation logic to backend * adding python client * polish messages * date time picker and default values * Initial commit * Initial commit * refactor * cleanup * cleanup * cleanup * cleanup, treating numbers/integers/booleans * adding slack to ts dependencies * sqlx prepare * gitignore, adding package.lock * ellipsis comments * Update typescript-client/client.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * refactor to move everything serverside + modal * sqlx prep * reverting slack dependency * python client update * fix build errors * Update pyproject.toml --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
+20
-5
@@ -6,7 +6,13 @@ cp ../backend/windmill-api/openapi.yaml openapi/openapi.yaml
|
||||
|
||||
npx @redocly/openapi-cli@latest bundle openapi/openapi.yaml > openapi-bundled.yaml
|
||||
|
||||
sed -z 's/FlowModuleValue:/FlowModuleValue2:/' openapi-bundled.yaml > openapi-decycled.yaml
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# sed -z is not supported on macOS, use perl instead
|
||||
perl -0777 -pe 's/FlowModuleValue:/FlowModuleValue2:/g' openapi-bundled.yaml > openapi-decycled.yaml
|
||||
else
|
||||
sed -z 's/FlowModuleValue:/FlowModuleValue2:/' openapi-bundled.yaml > openapi-decycled.yaml
|
||||
fi
|
||||
|
||||
echo " FlowModuleValue: {}" >> openapi-decycled.yaml
|
||||
npx @redocly/openapi-cli@latest bundle openapi-decycled.yaml --ext json -d > openapi-deref.json
|
||||
|
||||
@@ -20,9 +26,19 @@ rm -rf openapi/
|
||||
rm openapi*
|
||||
|
||||
cp LICENSE windmill-api/
|
||||
sed -i '5 i license = "Apache-2.0"' windmill-api/pyproject.toml
|
||||
|
||||
sed -i 's/authors = \[\]/authors = \["Ruben Fiszel <ruben@windmill.dev>"\]/g' windmill-api/pyproject.toml
|
||||
# Check if running on macOS
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS version
|
||||
sed -i '' '5 i\
|
||||
license = "Apache-2.0"' windmill-api/pyproject.toml
|
||||
sed -i '' 's/authors = \[\]/\nauthors = \["Ruben Fiszel <ruben@windmill.dev>"\]/g' windmill-api/pyproject.toml
|
||||
else
|
||||
# Linux version
|
||||
sed -i '5 i license = "Apache-2.0"' windmill-api/pyproject.toml
|
||||
|
||||
sed -i 's/authors = \[\]/authors = \["Ruben Fiszel <ruben@windmill.dev>"\]/g' windmill-api/pyproject.toml
|
||||
fi
|
||||
|
||||
echo "# Autogenerated Windmill OpenApi Client" >> windmill-api/README.md.tmp
|
||||
echo "This is the raw autogenerated api client. You are most likely more interested \
|
||||
@@ -33,8 +49,7 @@ user friendly experience. We use \
|
||||
|
||||
echo "" >> windmill-api/README.md.tmp
|
||||
|
||||
|
||||
head -n -13 windmill-api/README.md >> windmill-api/README.md.tmp
|
||||
tail -r windmill-api/README.md | tail -n +14 | tail -r >> windmill-api/README.md.tmp
|
||||
mv windmill-api/README.md.tmp windmill-api/README.md
|
||||
|
||||
cd windmill-api && poetry build
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/env nu
|
||||
|
||||
let cache = "/tmp/windmill/cache/pip/"
|
||||
let cache = "/tmp/windmill/cache/python_311/"
|
||||
|
||||
# Clean cache
|
||||
def "main clean" [] {
|
||||
@@ -42,7 +42,7 @@ def main [
|
||||
rm -rf ($cache ++ wmill*/wmill/*)
|
||||
|
||||
# Copy files from local ./dist to every wm-client version in cache
|
||||
ls /tmp/windmill/cache/pip/wmill* | each {
|
||||
ls /tmp/windmill/cache/python_311/wmill* | each {
|
||||
|i|
|
||||
|
||||
let path = $i | get name;
|
||||
|
||||
@@ -623,6 +623,46 @@ class Windmill:
|
||||
params={"approver": approver},
|
||||
).json()
|
||||
|
||||
def request_interactive_slack_approval(
|
||||
self,
|
||||
slack_resource_path: str,
|
||||
channel_id: str,
|
||||
message: str = None,
|
||||
approver: str = None,
|
||||
) -> None:
|
||||
"""
|
||||
Request interactive Slack approval
|
||||
:param slack_resource_path: Slack resource path
|
||||
:param channel_id: Slack channel
|
||||
:param message: Message to send to Slack
|
||||
:param approver: Approver name
|
||||
"""
|
||||
workspace = self.workspace
|
||||
flow_job_id = os.environ.get("WM_FLOW_JOB_ID")
|
||||
|
||||
if not flow_job_id:
|
||||
raise Exception(
|
||||
"You can't use 'request_interactive_slack_approval' function in a standalone script or flow step preview. Please use it in a flow or a flow preview."
|
||||
)
|
||||
|
||||
# Only include non-empty parameters
|
||||
params = {}
|
||||
if message:
|
||||
params["message"] = message
|
||||
if approver:
|
||||
params["approver"] = approver
|
||||
if slack_resource_path:
|
||||
params["slack_resource_path"] = slack_resource_path
|
||||
if channel_id:
|
||||
params["channel_id"] = channel_id
|
||||
if os.environ.get("WM_FLOW_STEP_ID"):
|
||||
params["flow_step_id"] = os.environ.get("WM_FLOW_STEP_ID")
|
||||
|
||||
self.get(
|
||||
f"/w/{workspace}/jobs/slack_approval/{os.environ.get('WM_JOB_ID', 'NO_JOB_ID')}",
|
||||
params=params,
|
||||
)
|
||||
|
||||
def username_to_email(self, username: str) -> str:
|
||||
"""
|
||||
Get email from workspace username
|
||||
@@ -972,6 +1012,19 @@ def get_state_path() -> str:
|
||||
def get_resume_urls(approver: str = None) -> dict:
|
||||
return _client.get_resume_urls(approver)
|
||||
|
||||
@init_global_client
|
||||
def request_interactive_slack_approval(
|
||||
slack_resource_path: str,
|
||||
channel_id: str,
|
||||
message: str = None,
|
||||
approver: str = None,
|
||||
) -> None:
|
||||
return _client.request_interactive_slack_approval(
|
||||
slack_resource_path=slack_resource_path,
|
||||
channel_id=channel_id,
|
||||
message=message,
|
||||
approver=approver,
|
||||
)
|
||||
|
||||
@init_global_client
|
||||
def cancel_running() -> dict:
|
||||
|
||||
Reference in New Issue
Block a user