mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 08:03:50 +00:00
Merge branch 'main' into dieri/change-workspace-id-async
This commit is contained in:
@@ -62,7 +62,9 @@ pub async fn increase_trigger_version(tx: &mut PgConnection) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn generate_route_path_key(route_path: &str) -> String {
|
||||
ROUTE_PATH_KEY_RE.replace_all(route_path, "/*").to_string()
|
||||
ROUTE_PATH_KEY_RE
|
||||
.replace_all(route_path, "${1}${2}key")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub async fn route_path_key_exists(
|
||||
@@ -322,7 +324,7 @@ async fn check_if_route_exist(
|
||||
workspace_id: &str,
|
||||
trigger_path: Option<&str>,
|
||||
) -> Result<String> {
|
||||
let route_path_key = ROUTE_PATH_KEY_RE.replace_all(&config.route_path, ":key");
|
||||
let route_path_key = generate_route_path_key(&config.route_path);
|
||||
|
||||
let exists = route_path_key_exists(
|
||||
&route_path_key,
|
||||
@@ -340,7 +342,7 @@ async fn check_if_route_exist(
|
||||
));
|
||||
}
|
||||
|
||||
Ok(route_path_key.into_owned())
|
||||
Ok(route_path_key)
|
||||
}
|
||||
|
||||
pub struct HttpTrigger;
|
||||
|
||||
@@ -192,8 +192,9 @@ impl<'de> Deserialize<'de> for HttpConfigRequest {
|
||||
|
||||
// Regex patterns for route validation
|
||||
lazy_static::lazy_static! {
|
||||
static ref ROUTE_PATH_KEY_RE: regex::Regex = regex::Regex::new(r"/?:[-\w]+").unwrap();
|
||||
static ref VALID_ROUTE_PATH_RE: regex::Regex = regex::Regex::new(r"^:?[-\w]+(/:?[-\w]+)*$").unwrap();
|
||||
// Matches named params like :id or wildcards like :* or *
|
||||
static ref ROUTE_PATH_KEY_RE: regex::Regex = regex::Regex::new(r"(/)?(:|\*)[-\w]+").unwrap();
|
||||
static ref VALID_ROUTE_PATH_RE: regex::Regex = regex::Regex::new(r"^(\*[-\w]+$|:?[-\w]+)(/(\*[-\w]+$|:?[-\w]+))*$").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@@ -409,10 +409,6 @@ fn format_pull_query(peek: String) -> String {
|
||||
raw_flow, script_entrypoint_override, preprocessed
|
||||
FROM v2_job
|
||||
WHERE id = (SELECT id FROM peek)
|
||||
), delete_debounce AS NOT MATERIALIZED (
|
||||
DELETE FROM debounce_key
|
||||
USING j
|
||||
WHERE j.kind::text != 'flowdependencies' AND j.kind::text != 'appdependencies' AND j.kind::text != 'dependencies' AND debounce_key.job_id = j.id
|
||||
) SELECT j.id, j.workspace_id, j.parent_job, j.created_by, started_at, scheduled_for,
|
||||
j.runnable_id, j.runnable_path, j.args, canceled_by,
|
||||
canceled_reason, j.kind, j.trigger, j.trigger_kind, j.permissioned_as,
|
||||
@@ -430,7 +426,7 @@ fn format_pull_query(peek: String) -> String {
|
||||
",
|
||||
peek
|
||||
);
|
||||
// tracing::debug!("pull query: {}", r);
|
||||
tracing::debug!("pull query: {}", r);
|
||||
r
|
||||
}
|
||||
|
||||
|
||||
@@ -3622,8 +3622,8 @@ pub async fn push<'c, 'd>(
|
||||
cache_ttl,
|
||||
dedicated_worker,
|
||||
_low_level_priority,
|
||||
custom_debounce_key,
|
||||
debounce_delay_s,
|
||||
mut custom_debounce_key,
|
||||
mut debounce_delay_s,
|
||||
) = match job_payload {
|
||||
JobPayload::ScriptHash {
|
||||
hash,
|
||||
@@ -4391,6 +4391,14 @@ pub async fn push<'c, 'd>(
|
||||
),
|
||||
};
|
||||
|
||||
if custom_debounce_key.is_some() {
|
||||
tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_key");
|
||||
custom_debounce_key = None;
|
||||
}
|
||||
if debounce_delay_s.is_some() {
|
||||
tracing::warn!("debouncing has been disabled temporarily, ignoring debounce_delay_s");
|
||||
debounce_delay_s = None;
|
||||
}
|
||||
// Enforce concurrency limit on all dependency jobs.
|
||||
// TODO: We can ignore this for scripts djobs. The main reason we need all djobs to be sequential is because we have
|
||||
// nodes_to_relock and we need all locks whose corresponding steps aren't in nodes_to_relock be already present.
|
||||
|
||||
@@ -142,7 +142,7 @@ export async function findResourceFile(path: string) {
|
||||
if (validCandidates.length > 1) {
|
||||
throw new Error(
|
||||
"Found two resource files for the same resource" +
|
||||
validCandidates.join(", ")
|
||||
validCandidates.join(", ")
|
||||
);
|
||||
}
|
||||
if (validCandidates.length < 1) {
|
||||
@@ -214,7 +214,8 @@ export async function handleFile(
|
||||
if (codebase.customBundler) {
|
||||
log.info(`Using custom bundler ${codebase.customBundler} for ${path}`);
|
||||
bundleContent = execSync(
|
||||
codebase.customBundler + " " + path
|
||||
codebase.customBundler + " " + path,
|
||||
{ maxBuffer: 1024 * 1024 * 50 }
|
||||
).toString();
|
||||
log.info("Custom bundler executed for " + path);
|
||||
} else {
|
||||
@@ -273,20 +274,20 @@ export async function handleFile(
|
||||
let typed = opts?.skipScriptsMetadata
|
||||
? undefined
|
||||
: (
|
||||
await parseMetadataFile(
|
||||
remotePath,
|
||||
opts
|
||||
? {
|
||||
...opts,
|
||||
path,
|
||||
workspaceRemote: workspace,
|
||||
schemaOnly: codebase ? true : undefined,
|
||||
}
|
||||
: undefined,
|
||||
globalDeps,
|
||||
codebases
|
||||
)
|
||||
)?.payload;
|
||||
await parseMetadataFile(
|
||||
remotePath,
|
||||
opts
|
||||
? {
|
||||
...opts,
|
||||
path,
|
||||
workspaceRemote: workspace,
|
||||
schemaOnly: codebase ? true : undefined,
|
||||
}
|
||||
: undefined,
|
||||
globalDeps,
|
||||
codebases
|
||||
)
|
||||
)?.payload;
|
||||
|
||||
const workspaceId = workspace.workspaceId;
|
||||
|
||||
@@ -373,19 +374,19 @@ export async function handleFile(
|
||||
deepEqual(typed.schema, remote.schema) &&
|
||||
typed.tag == remote.tag &&
|
||||
(typed.ws_error_handler_muted ?? false) ==
|
||||
remote.ws_error_handler_muted &&
|
||||
remote.ws_error_handler_muted &&
|
||||
typed.dedicated_worker == remote.dedicated_worker &&
|
||||
typed.cache_ttl == remote.cache_ttl &&
|
||||
typed.concurrency_time_window_s ==
|
||||
remote.concurrency_time_window_s &&
|
||||
remote.concurrency_time_window_s &&
|
||||
typed.concurrent_limit == remote.concurrent_limit &&
|
||||
Boolean(typed.restart_unless_cancelled) ==
|
||||
Boolean(remote.restart_unless_cancelled) &&
|
||||
Boolean(remote.restart_unless_cancelled) &&
|
||||
Boolean(typed.visible_to_runner_only) ==
|
||||
Boolean(remote.visible_to_runner_only) &&
|
||||
Boolean(remote.visible_to_runner_only) &&
|
||||
Boolean(typed.no_main_func) == Boolean(remote.no_main_func) &&
|
||||
Boolean(typed.has_preprocessor) ==
|
||||
Boolean(remote.has_preprocessor) &&
|
||||
Boolean(remote.has_preprocessor) &&
|
||||
typed.priority == Boolean(remote.priority) &&
|
||||
typed.timeout == remote.timeout &&
|
||||
//@ts-ignore
|
||||
@@ -478,8 +479,7 @@ async function createScript(
|
||||
});
|
||||
} catch (e: any) {
|
||||
throw Error(
|
||||
`Script creation for ${body.path} with parent ${
|
||||
body.parent_hash
|
||||
`Script creation for ${body.path} with parent ${body.parent_hash
|
||||
} was not successful: ${e.body ?? e.message} `
|
||||
);
|
||||
}
|
||||
@@ -505,8 +505,7 @@ async function createScript(
|
||||
});
|
||||
if (req.status != 201) {
|
||||
throw Error(
|
||||
`Script snapshot creation was not successful: ${req.status} - ${
|
||||
req.statusText
|
||||
`Script snapshot creation was not successful: ${req.status} - ${req.statusText
|
||||
} - ${await req.text()} `
|
||||
);
|
||||
}
|
||||
@@ -518,8 +517,8 @@ export async function findContentFile(filePath: string) {
|
||||
const candidates = filePath.endsWith("script.json")
|
||||
? exts.map((x) => filePath.replace(".script.json", x))
|
||||
: filePath.endsWith("script.lock")
|
||||
? exts.map((x) => filePath.replace(".script.lock", x))
|
||||
: exts.map((x) => filePath.replace(".script.yaml", x));
|
||||
? exts.map((x) => filePath.replace(".script.lock", x))
|
||||
: exts.map((x) => filePath.replace(".script.yaml", x));
|
||||
|
||||
const validCandidates = (
|
||||
await Promise.all(
|
||||
@@ -538,7 +537,7 @@ export async function findContentFile(filePath: string) {
|
||||
if (validCandidates.length > 1) {
|
||||
throw new Error(
|
||||
"No content path given and more than one candidate found: " +
|
||||
validCandidates.join(", ")
|
||||
validCandidates.join(", ")
|
||||
);
|
||||
}
|
||||
if (validCandidates.length < 1) {
|
||||
|
||||
+6
-2
@@ -20,6 +20,7 @@
|
||||
additionalExitAction?: () => void
|
||||
triggerOnSearchParamsChange?: boolean
|
||||
onDiscardChanges?: () => void
|
||||
tabMode?: boolean
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -27,7 +28,8 @@
|
||||
diffDrawer = undefined,
|
||||
additionalExitAction = () => {},
|
||||
triggerOnSearchParamsChange = false,
|
||||
onDiscardChanges = undefined
|
||||
onDiscardChanges = undefined,
|
||||
tabMode = false
|
||||
}: Props = $props()
|
||||
let savedValue: Value | undefined = $state(undefined)
|
||||
let modifiedValue: Value | undefined = $state(undefined)
|
||||
@@ -66,7 +68,9 @@
|
||||
orderedJsonStringify(replaceFalseWithUndefined(draftOrDeployed)) ===
|
||||
orderedJsonStringify(replaceFalseWithUndefined(current))
|
||||
) {
|
||||
bypassBeforeNavigate = true
|
||||
if (!tabMode) {
|
||||
bypassBeforeNavigate = true
|
||||
}
|
||||
additionalExitAction?.()
|
||||
} else {
|
||||
await openModal()
|
||||
|
||||
@@ -54,7 +54,11 @@
|
||||
clearTimeout(validateTimeout)
|
||||
}
|
||||
validateTimeout = setTimeout(async () => {
|
||||
if (!routePath || !method || !/^:?[-\w]+(\/:?[-\w]+)*$/.test(routePath)) {
|
||||
if (
|
||||
!routePath ||
|
||||
!method ||
|
||||
!/^(\*[-\w]+$|:?[-\w]+)(\/(\*[-\w]+$|:?[-\w]+))*$/.test(routePath)
|
||||
) {
|
||||
routeError = 'Endpoint not valid'
|
||||
} else if (await routeExists(routePath, method, workspaced_route)) {
|
||||
routeError = 'Endpoint already taken'
|
||||
@@ -140,7 +144,9 @@
|
||||
bind:value={route_path}
|
||||
error={routeError !== ''}
|
||||
/>
|
||||
<div class="text-2xs text-secondary"> ':myparam' for path params </div>
|
||||
<div class="text-2xs text-secondary">
|
||||
Use ':myparam' for path params and '*mywildcard' for wildcards
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
|
||||
@@ -1047,6 +1047,7 @@
|
||||
getInitialAndModifiedValues={getAllUnsavedChanges}
|
||||
onDiscardChanges={discardAllChanges}
|
||||
triggerOnSearchParamsChange={true}
|
||||
tabMode={true}
|
||||
/>
|
||||
|
||||
<style>
|
||||
|
||||
Reference in New Issue
Block a user