fix: windmill_status_code script now properly return + script bash default arg

This commit is contained in:
Ruben Fiszel
2023-10-21 02:32:47 +02:00
parent 9655834cd8
commit 255dd53ed3
9 changed files with 105 additions and 75 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
DATABASE_URL: postgres://postgres:changeme@postgres:5432/windmill
LICENSE_KEY: ${{ secrets.WM_LICENSE_KEY_CI }}
WORKER_GROUP: main
WORKER_TAGS: deno,bun,go,python3,bash,dependency,flow
WORKER_TAGS: deno,bun,go,python3,bash,dependency,flow,nativets
options: >-
--pull always --health-interval 10s --health-timeout 5s
--health-retries 5 --health-cmd "curl
@@ -57,7 +57,7 @@ fn parse_bash_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
typ: Typ::Str(None),
default: default.clone().map(|x| json!(x)),
otyp: None,
has_default: false,
has_default: default.is_some(),
});
} else {
break;
@@ -113,6 +113,8 @@ token="$1"
image="$2"
digest="${3:-latest with spaces}"
text="$4" # with comment
non_required="${5:-}"
"#;
//println!("{}", serde_json::to_string()?);
@@ -141,7 +143,7 @@ text="$4" # with comment
name: "digest".to_string(),
typ: Typ::Str(None),
default: Some(json!("latest with spaces")),
has_default: false
has_default: true
},
Arg {
otyp: None,
@@ -149,6 +151,13 @@ text="$4" # with comment
typ: Typ::Str(None),
default: None,
has_default: false
},
Arg {
otyp: None,
name: "non_required".to_string(),
typ: Typ::Str(None),
default: Some(json!("")),
has_default: true
}
]
}
@@ -3,7 +3,7 @@
"collaborators": [
"Ruben Fiszel <ruben@windmill.dev>"
],
"version": "1.180.0",
"version": "1.186.0",
"files": [
"windmill_parser_wasm_bg.wasm",
"windmill_parser_wasm.js",
@@ -97,15 +97,6 @@ function getInt32Memory0() {
return cachedInt32Memory0;
}
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
@@ -124,6 +115,15 @@ function getFloat64Memory0() {
return cachedFloat64Memory0;
}
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let cachedBigInt64Memory0 = null;
function getBigInt64Memory0() {
@@ -495,7 +495,7 @@ function __wbg_get_imports() {
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_eval_2e5c54091872c19c = function(arg0, arg1) {
imports.wbg.__wbg_eval_4cf9c172060c8b3d = function(arg0, arg1) {
const ret = eval(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
@@ -507,10 +507,6 @@ function __wbg_get_imports() {
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_boolean_get = function(arg0) {
const v = getObject(arg0);
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
@@ -528,6 +524,10 @@ function __wbg_get_imports() {
const ret = getObject(arg0) === getObject(arg1);
return ret;
};
imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
const ret = BigInt.asUintN(64, arg0);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'number' ? obj : undefined;
@@ -543,8 +543,8 @@ function __wbg_get_imports() {
const ret = getObject(arg0) in getObject(arg1);
return ret;
};
imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
const ret = BigInt.asUintN(64, arg0);
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
+34 -25
View File
@@ -1757,12 +1757,17 @@ impl Drop for Guard {
}
}
#[derive(Deserialize)]
pub struct WindmillStatusCode {
windmill_status_code: Option<u16>,
result: Option<Box<RawValue>>,
}
async fn run_wait_result<T>(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
uuid: Uuid,
Path((w_id, _)): Path<(String, T)>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
let mut result;
let timeout = SERVER_CONFIG.read().await.timeout_wait_result.clone();
let timeout_ms = if timeout <= 0 {
@@ -1781,16 +1786,16 @@ async fn run_wait_result<T>(
let fast_poll_duration = *WAIT_RESULT_FAST_POLL_DURATION_SECS as u64 * 1000;
let mut accumulated_delay = 0 as u64;
loop {
let mut tx = user_db.clone().begin(&authed).await?;
result = sqlx::query_scalar!(
"SELECT result FROM completed_job WHERE id = $1 AND workspace_id = $2",
uuid,
&w_id
)
.fetch_optional(&mut *tx)
.await?
.flatten();
result =
sqlx::query("SELECT result FROM completed_job WHERE id = $1 AND workspace_id = $2")
.bind(uuid)
.bind(&w_id)
.fetch_optional(&mut *tx)
.await?;
drop(tx);
if result.is_some() {
@@ -1810,14 +1815,18 @@ async fn run_wait_result<T>(
}
if let Some(result) = result {
g.done = true;
let status_code = result
.get("windmill_status_code")
.and_then(|x| x.as_i64())
.and_then(|x| StatusCode::from_u16(x as u16).ok());
if let Some(status_code) = status_code {
return Err(Error::CustomStatusCode(status_code, result));
let result = RawResult::from_row(&result)?.result;
let status_code = serde_json::from_str::<WindmillStatusCode>(result.get());
match status_code {
Ok(WindmillStatusCode { windmill_status_code: Some(status_code), result }) => {
Err(Error::CustomStatusCode(
StatusCode::from_u16(status_code).unwrap_or_else(|_| StatusCode::IM_A_TEAPOT),
result,
))
}
_ => Ok(Json(result).into_response()),
}
Ok(Json(result))
} else {
Err(Error::ExecutionErr(format!("timeout after {}s", timeout)))
}
@@ -1870,12 +1879,12 @@ pub async fn run_wait_result_job_by_path_get(
Extension(db): Extension<DB>,
Path((w_id, script_path)): Path<(String, StripPath)>,
Query(run_query): Query<RunJobQuery>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
#[cfg(feature = "enterprise")]
check_license_key_valid().await?;
if method == http::Method::HEAD {
return Ok(Json(serde_json::json!("")));
return Ok(Json(serde_json::json!("")).into_response());
}
let payload_r = run_query
.payload
@@ -1935,12 +1944,12 @@ pub async fn run_wait_result_flow_by_path_get(
Path((w_id, flow_path)): Path<(String, StripPath)>,
Query(run_query): Query<RunJobQuery>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
#[cfg(feature = "enterprise")]
check_license_key_valid().await?;
if method == http::Method::HEAD {
return Ok(Json(serde_json::json!("")));
return Ok(Json(serde_json::json!("")).into_response());
}
let payload_r = run_query
.payload
@@ -1970,7 +1979,7 @@ pub async fn run_wait_result_script_by_path(
Path((w_id, script_path)): Path<(String, StripPath)>,
Query(run_query): Query<RunJobQuery>,
args: PushArgs<HashMap<String, Box<JsonRawValue>>>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
#[cfg(feature = "enterprise")]
check_license_key_valid().await?;
@@ -1996,7 +2005,7 @@ async fn run_wait_result_script_by_path_internal(
user_db: UserDB,
w_id: String,
args: PushArgs<HashMap<String, Box<JsonRawValue>>>,
) -> Result<Json<serde_json::Value>, Error> {
) -> error::Result<Response> {
check_queue_too_long(&db, QUEUE_LIMIT_WAIT_RESULT.or(run_query.queue_limit)).await?;
let script_path = script_path.to_path();
check_scopes(&authed, || format!("run:script/{script_path}"))?;
@@ -2042,7 +2051,7 @@ pub async fn run_wait_result_script_by_hash(
Path((w_id, script_hash)): Path<(String, ScriptHash)>,
Query(run_query): Query<RunJobQuery>,
args: PushArgs<HashMap<String, Box<JsonRawValue>>>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
#[cfg(feature = "enterprise")]
check_license_key_valid().await?;
@@ -2107,7 +2116,7 @@ pub async fn run_wait_result_flow_by_path(
Path((w_id, flow_path)): Path<(String, StripPath)>,
Query(run_query): Query<RunJobQuery>,
args: PushArgs<HashMap<String, Box<JsonRawValue>>>,
) -> error::JsonResult<serde_json::Value> {
) -> error::Result<Response> {
#[cfg(feature = "enterprise")]
check_license_key_valid().await?;
@@ -2126,7 +2135,7 @@ async fn run_wait_result_flow_by_path_internal(
user_db: UserDB,
args: PushArgs<HashMap<String, Box<JsonRawValue>>>,
w_id: String,
) -> Result<Json<serde_json::Value>, Error> {
) -> error::Result<Response> {
check_queue_too_long(&db, run_query.queue_limit).await?;
let flow_path = flow_path.to_path();
+34 -22
View File
@@ -15,6 +15,7 @@ use axum::{
};
use hyper::StatusCode;
use serde_json::value::RawValue;
#[cfg(feature = "sqlx")]
use sqlx::migrate::MigrateError;
use thiserror::Error;
@@ -65,7 +66,7 @@ pub enum Error {
#[error("Error: {0:#?}")]
JsonErr(serde_json::Value),
#[error("Custom Status Code: {0:#?}")]
CustomStatusCode(StatusCode, serde_json::Value),
CustomStatusCode(StatusCode, Option<Box<RawValue>>),
#[error("{0}")]
OpenAIError(String),
}
@@ -84,30 +85,41 @@ pub fn to_anyhow<T: 'static + std::error::Error + Send + Sync>(e: T) -> anyhow::
#[cfg(feature = "axum")]
impl IntoResponse for Error {
fn into_response(self) -> axum::response::Response<BoxBody> {
let e = &self;
let body = body::boxed(body::Full::from(e.to_string()));
let status = match self {
Self::NotFound(_) => axum::http::StatusCode::NOT_FOUND,
Self::NotAuthorized(_) => axum::http::StatusCode::UNAUTHORIZED,
Self::RequireAdmin(_) => axum::http::StatusCode::FORBIDDEN,
Self::CustomStatusCode(code, _) => code,
Self::SqlErr(_) | Self::BadRequest(_) | Self::OpenAIError(_) => {
axum::http::StatusCode::BAD_REQUEST
match self {
Self::CustomStatusCode(code, result) => {
let mut res = Json(result).into_response();
let status_mut = res.status_mut();
*status_mut = code;
res
}
_ => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
};
_ => {
let e = &self;
let body = body::boxed(body::Full::from(e.to_string()));
if matches!(status, axum::http::StatusCode::NOT_FOUND) {
tracing::warn!(not_found = e.to_string());
} else {
tracing::error!(error = e.to_string());
};
let status = match self {
Self::NotFound(_) => axum::http::StatusCode::NOT_FOUND,
Self::NotAuthorized(_) => axum::http::StatusCode::UNAUTHORIZED,
Self::RequireAdmin(_) => axum::http::StatusCode::FORBIDDEN,
Self::CustomStatusCode(code, _) => code,
Self::SqlErr(_) | Self::BadRequest(_) | Self::OpenAIError(_) => {
axum::http::StatusCode::BAD_REQUEST
}
_ => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
};
axum::response::Response::builder()
.header("Content-Type", "text/plain")
.status(status)
.body(body)
.unwrap()
if matches!(status, axum::http::StatusCode::NOT_FOUND) {
tracing::warn!(not_found = e.to_string());
} else {
tracing::error!(error = e.to_string());
};
axum::response::Response::builder()
.header("Content-Type", "text/plain")
.status(status)
.body(body)
.unwrap()
}
}
}
}
+7 -7
View File
@@ -47,7 +47,7 @@
"svelte-tiny-virtual-list": "^2.0.5",
"tailwind-merge": "^1.13.2",
"vscode-ws-jsonrpc": "3.0.0",
"windmill-parser-wasm": "^1.180.0",
"windmill-parser-wasm": "^1.186.0",
"y-monaco": "^0.1.4",
"y-websocket": "^1.5.0",
"yjs": "^13.6.7"
@@ -9946,9 +9946,9 @@
}
},
"node_modules/windmill-parser-wasm": {
"version": "1.180.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.180.0.tgz",
"integrity": "sha512-ikkyfiAdILGUZT0g+eiZ9dgPYFHCjtZVFCRUAkw7PlbK+8bT6ROa+mv1ZRxkc3LZLGsWEwteojdcjfopPFTTAQ=="
"version": "1.186.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.186.0.tgz",
"integrity": "sha512-xoeGloTQHl54WWp97rmy94Us6bzY4ckU+Y7+f4NcR4l9DG9XpzsHQrjwzZH1Ak9zM91oIQDdgTBZkrAsZ5N97w=="
},
"node_modules/wordwrap": {
"version": "1.0.0",
@@ -17012,9 +17012,9 @@
}
},
"windmill-parser-wasm": {
"version": "1.180.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.180.0.tgz",
"integrity": "sha512-ikkyfiAdILGUZT0g+eiZ9dgPYFHCjtZVFCRUAkw7PlbK+8bT6ROa+mv1ZRxkc3LZLGsWEwteojdcjfopPFTTAQ=="
"version": "1.186.0",
"resolved": "https://registry.npmjs.org/windmill-parser-wasm/-/windmill-parser-wasm-1.186.0.tgz",
"integrity": "sha512-xoeGloTQHl54WWp97rmy94Us6bzY4ckU+Y7+f4NcR4l9DG9XpzsHQrjwzZH1Ak9zM91oIQDdgTBZkrAsZ5N97w=="
},
"wordwrap": {
"version": "1.0.0",
+1 -1
View File
@@ -124,7 +124,7 @@
"svelte-tiny-virtual-list": "^2.0.5",
"tailwind-merge": "^1.13.2",
"vscode-ws-jsonrpc": "3.0.0",
"windmill-parser-wasm": "^1.180.0",
"windmill-parser-wasm": "^1.186.0",
"y-monaco": "^0.1.4",
"y-websocket": "^1.5.0",
"yjs": "^13.6.7"