From 36dad2c7a29e4880bdf0198611e07a4366b01edf Mon Sep 17 00:00:00 2001 From: wendrul <53628737+wendrul@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:18:39 +0100 Subject: [PATCH] fix: Raw apps deployment UI (and merge UI) (#7725) --- backend/windmill-api/openapi.yaml | 15 ++- .../lib/components/CompareWorkspaces.svelte | 73 +++++++++--- .../src/lib/components/DeployWorkspace.svelte | 104 ++++++++++++++---- 3 files changed, 151 insertions(+), 41 deletions(-) diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 0e6a153778..1d32c4dfab 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -7703,16 +7703,19 @@ paths: schema: type: boolean - /w/{workspace}/apps/get_data/{version}/{path}: + /w/{workspace}/apps/get_data/v/{secretWithExtension}: get: - summary: get app by path + summary: get raw app data by operationId: getRawAppData tags: - - raw_app + - app parameters: - $ref: "#/components/parameters/WorkspaceId" - - $ref: "#/components/parameters/VersionId" - - $ref: "#/components/parameters/ScriptPath" + - name: secretWithExtension + in: path + required: true + schema: + type: string responses: "200": description: app details @@ -22688,4 +22691,4 @@ components: required: - id - name - - path \ No newline at end of file + - path diff --git a/frontend/src/lib/components/CompareWorkspaces.svelte b/frontend/src/lib/components/CompareWorkspaces.svelte index 2cdb36f3e7..77325e3450 100644 --- a/frontend/src/lib/components/CompareWorkspaces.svelte +++ b/frontend/src/lib/components/CompareWorkspaces.svelte @@ -427,20 +427,67 @@ path: path }) if (alreadyExists) { - await AppService.updateApp({ - workspace: workspaceToDeployTo, - path: path, - requestBody: { - ...app - } - }) + if (app.raw_app) { + const secret = await AppService.getPublicSecretOfLatestVersionOfApp({ + workspace: workspaceFrom, + path: app.path + }) + const js = await AppService.getRawAppData({ + secretWithExtension: `${secret}.js`, + workspace: workspaceFrom + }) + const css = await AppService.getRawAppData({ + secretWithExtension: `${secret}.css`, + workspace: workspaceFrom + }) + await AppService.updateAppRaw({ + workspace: workspaceToDeployTo, + path: path, + formData: { + app, + css, + js + } + }) + } else { + await AppService.updateApp({ + workspace: workspaceToDeployTo, + path: path, + requestBody: { + ...app + } + }) + } } else { - await AppService.createApp({ - workspace: workspaceToDeployTo, - requestBody: { - ...app - } - }) + if (app.raw_app) { + const secret = await AppService.getPublicSecretOfLatestVersionOfApp({ + workspace: workspaceFrom, + path: app.path + }) + const js = await AppService.getRawAppData({ + secretWithExtension: `${secret}.js`, + workspace: workspaceFrom + }) + const css = await AppService.getRawAppData({ + secretWithExtension: `${secret}.css`, + workspace: workspaceFrom + }) + await AppService.createAppRaw({ + workspace: workspaceToDeployTo, + formData: { + app, + css, + js + } + }) + } else { + await AppService.createApp({ + workspace: workspaceToDeployTo, + requestBody: { + ...app + } + }) + } } } else if (kind == 'variable') { const variable = await VariableService.getVariable({ diff --git a/frontend/src/lib/components/DeployWorkspace.svelte b/frontend/src/lib/components/DeployWorkspace.svelte index 5d3a378d4d..c1d1871604 100644 --- a/frontend/src/lib/components/DeployWorkspace.svelte +++ b/frontend/src/lib/components/DeployWorkspace.svelte @@ -34,6 +34,7 @@ import type { App } from './apps/types' import { getAllGridItems } from './apps/editor/appUtils' import { isRunnableByPath } from './apps/inputType' + import type { Runnable } from './raw_apps/utils' const dispatch = createEventDispatcher() @@ -150,18 +151,30 @@ } else if (kind == 'app') { const app = await AppService.getAppByPath({ workspace: $workspaceStore!, path }) console.log('app', app) - let appValue = app.value as App let result: { kind: Kind; path: string }[] = [] - getAllGridItems(appValue).forEach((gridItem) => { - const ci = gridItem.data.componentInput - if (ci?.type == 'runnable' && isRunnableByPath(ci.runnable)) { - if (ci.runnable.runType == 'script') { - result.push({ kind: 'script', path: ci.runnable.path }) - } else if (ci.runnable.runType == 'flow') { - result.push({ kind: 'flow', path: ci.runnable.path }) + if (app.raw_app) { + for (const runnable of Object.values(app.value.runnables as Record)) { + if (isRunnableByPath(runnable)) { + if (runnable.runType == 'script') { + result.push({ kind: 'script', path: runnable.path }) + } else if (runnable.runType == 'flow') { + result.push({ kind: 'flow', path: runnable.path }) + } } } - }) + } else { + let appValue = app.value as App + getAllGridItems(appValue).forEach((gridItem) => { + const ci = gridItem.data.componentInput + if (ci?.type == 'runnable' && isRunnableByPath(ci.runnable)) { + if (ci.runnable.runType == 'script') { + result.push({ kind: 'script', path: ci.runnable.path }) + } else if (ci.runnable.runType == 'flow') { + result.push({ kind: 'flow', path: ci.runnable.path }) + } + } + }) + } return result } else if (kind == 'resource') { const res = await ResourceService.getResource({ workspace: $workspaceStore!, path }) @@ -344,20 +357,67 @@ path: path }) if (alreadyExists) { - await AppService.updateApp({ - workspace: workspaceToDeployTo!, - path: path, - requestBody: { - ...app - } - }) + if (app.raw_app) { + const secret = await AppService.getPublicSecretOfLatestVersionOfApp({ + workspace: $workspaceStore!, + path: app.path + }) + const js = await AppService.getRawAppData({ + secretWithExtension: `${secret}.js`, + workspace: $workspaceStore! + }) + const css = await AppService.getRawAppData({ + secretWithExtension: `${secret}.css`, + workspace: $workspaceStore! + }) + await AppService.updateAppRaw({ + workspace: workspaceToDeployTo!, + path: path, + formData: { + app, + css, + js + } + }) + } else { + await AppService.updateApp({ + workspace: workspaceToDeployTo!, + path: path, + requestBody: { + ...app + } + }) + } } else { - await AppService.createApp({ - workspace: workspaceToDeployTo!, - requestBody: { - ...app - } - }) + if (app.raw_app) { + const secret = await AppService.getPublicSecretOfLatestVersionOfApp({ + workspace: $workspaceStore!, + path: app.path + }) + const js = await AppService.getRawAppData({ + secretWithExtension: `${secret}.js`, + workspace: $workspaceStore! + }) + const css = await AppService.getRawAppData({ + secretWithExtension: `${secret}.css`, + workspace: $workspaceStore! + }) + await AppService.createAppRaw({ + workspace: workspaceToDeployTo!, + formData: { + app, + css, + js + } + }) + } else { + await AppService.createApp({ + workspace: workspaceToDeployTo!, + requestBody: { + ...app + } + }) + } } } else if (kind == 'variable') { const variable = await VariableService.getVariable({