diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index add4c936d2..bbc48903a7 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -1101,7 +1101,7 @@ struct ArchiveQueryParams { } #[inline] -pub fn to_string_without_metadata(value: &T) -> Result +pub fn to_string_without_metadata(value: &T, preserve_extra_perms: bool) -> Result where T: ?Sized + Serialize, { @@ -1129,6 +1129,10 @@ where } } + if !preserve_extra_perms && obj.contains_key("extra_perms") { + obj.remove("extra_perms"); + } + serde_json::to_string_pretty(&obj).ok() }) .flatten() @@ -1166,7 +1170,7 @@ async fn tarball_workspace( for folder in folders { archive .write_to_archive( - &to_string_without_metadata(&folder).unwrap(), + &to_string_without_metadata(&folder, true).unwrap(), &format!("f/{}/folder.meta.json", folder.name), ) .await?; @@ -1224,7 +1228,7 @@ async fn tarball_workspace( .await?; for resource in resources { - let resource_str = &to_string_without_metadata(&resource).unwrap(); + let resource_str = &to_string_without_metadata(&resource, false).unwrap(); archive .write_to_archive(&resource_str, &format!("{}.resource.json", resource.path)) .await?; @@ -1241,7 +1245,7 @@ async fn tarball_workspace( .await?; for resource_type in resource_types { - let resource_str = &to_string_without_metadata(&resource_type).unwrap(); + let resource_str = &to_string_without_metadata(&resource_type, false).unwrap(); archive .write_to_archive( &resource_str, @@ -1260,7 +1264,7 @@ async fn tarball_workspace( .await?; for flow in flows { - let flow_str = &to_string_without_metadata(&flow).unwrap(); + let flow_str = &to_string_without_metadata(&flow, false).unwrap(); archive .write_to_archive(&flow_str, &format!("{}.flow.json", flow.path)) .await?; @@ -1276,7 +1280,7 @@ async fn tarball_workspace( .await?; for var in variables { - let var_str = &to_string_without_metadata(&var).unwrap(); + let var_str = &to_string_without_metadata(&var, false).unwrap(); archive .write_to_archive(&var_str, &format!("{}.variable.json", var.path)) .await?; @@ -1296,7 +1300,7 @@ async fn tarball_workspace( .await?; for app in apps { - let app_str = &to_string_without_metadata(&app).unwrap(); + let app_str = &to_string_without_metadata(&app, false).unwrap(); archive .write_to_archive(&app_str, &format!("{}.app.json", app.path)) .await?; diff --git a/cli/script.ts b/cli/script.ts index c161b90ece..889a1a5550 100644 --- a/cli/script.ts +++ b/cli/script.ts @@ -79,8 +79,21 @@ async function push( console.log(colors.bold.underline.green("Script successfully pushed")); } -export async function handleFile(path: string, content: string, workspace: string): Promise { +export async function handleScriptMetadata(path: string, workspace: string, alreadySynced: string[]): Promise { + if (path.endsWith(".script.json")) { + const contentPath = await findContentFile(path) + return handleFile(contentPath, await Deno.readTextFile(contentPath), workspace, alreadySynced) + } else { + return false + } +} + +export async function handleFile(path: string, content: string, workspace: string, alreadySynced: string[]): Promise { if (path.endsWith(".ts") || path.endsWith(".py") || path.endsWith(".go") || path.endsWith(".sh")) { + if (alreadySynced.includes(path)) { + return true + } + alreadySynced.push(path) const remotePath = path.substring(0, path.length - 3); const metaPath = remotePath + ".script.json"; let typed = undefined @@ -90,6 +103,7 @@ export async function handleFile(path: string, content: string, workspace: strin typed = decoverto.type(ScriptFile).plainToInstance(typed); } catch { } const language = inferContentTypeFromFilePath(path); + try { const remote = await ScriptService.getScriptByPath({ workspace, @@ -105,12 +119,12 @@ export async function handleFile(path: string, content: string, workspace: strin summary: typed.summary, is_template: typed.is_template, kind: typed.kind, - lock: undefined, + lock: typed.lock, parent_hash: remote.hash, schema: typed.schema, }, }); - + console.log(colors.yellow.bold(`Creating script with a parent ${remotePath}`)) } catch { // no parent hash await ScriptService.createScript({ @@ -123,11 +137,13 @@ export async function handleFile(path: string, content: string, workspace: strin summary: typed.summary, is_template: typed.is_template, kind: typed.kind, - lock: undefined, + lock: typed.lock, parent_hash: undefined, schema: typed.schema, }, }); + console.log(colors.yellow.bold(`Creating script without parent ${remotePath}`)) + } return true } @@ -135,7 +151,6 @@ export async function handleFile(path: string, content: string, workspace: strin } export async function findContentFile(filePath: string) { - console.log("Searching " + filePath); const candidates = [ filePath.replace(".script.json", ".ts"), filePath.replace(".script.json", ".py"), diff --git a/cli/sync.ts b/cli/sync.ts index 231ec05fea..1c98f15ef1 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -26,6 +26,7 @@ import { downloadZip } from "./pull.ts"; import { FolderFile } from "./folder.ts"; import { ResourceTypeFile } from "./resource-type.ts"; import { + handleScriptMetadata, ScriptFile, } from "./script.ts"; import { ResourceFile } from "./resource.ts"; @@ -195,7 +196,8 @@ async function compareDynFSElement( await Deno.writeTextFile("/tmp/k", m2[k]) await Deno.writeTextFile("/tmp/v", v) console.log(k) - Deno.exit(1) + if (k.includes("variable")) + Deno.exit(1) changes.push({ name: "edited", path: k, after: v, before: m2[k] }); } } @@ -306,7 +308,7 @@ async function pull( } } } - console.log(colors.green.underline(`Done! All ${changes.length} changes applied locally.`)); + console.log(colors.green.underline(`Done! All ${changes.length} changes pushed to the remote.`)); } @@ -404,12 +406,13 @@ async function push(opts: GlobalOptions & { raw: boolean, yes: boolean }) { return } console.log(`Applying changes to files ...`); + const alreadySynced: string[] = [] for await (const change of changes) { const stateTarget = path.join(Deno.cwd(), ".wmill", change.path) if (change.name === "edited") { - if (change.path.endsWith(".script.json")) { + if (await handleScriptMetadata(change.path, workspace.workspaceId, alreadySynced)) { continue - } else if (await handleFile(change.path, change.after, workspace.workspaceId)) { + } else if (await handleFile(change.path, change.after, workspace.workspaceId, alreadySynced)) { continue } if (!opts.raw) { @@ -431,7 +434,7 @@ async function push(opts: GlobalOptions & { raw: boolean, yes: boolean }) { } else if (change.name === "added") { if (change.path.endsWith(".script.json")) { continue - } else if (await handleFile(change.path, change.content, workspace.workspaceId)) { + } else if (await handleFile(change.path, change.content, workspace.workspaceId, alreadySynced)) { continue } if (!opts.raw) { diff --git a/cli/variable.ts b/cli/variable.ts index 270fb27191..2b0157637d 100644 --- a/cli/variable.ts +++ b/cli/variable.ts @@ -105,7 +105,7 @@ export class VariableFile implements Resource, PushDiffs { console.log(changeset); } else { - console.log(colors.yellow("Creating new variable...")); + console.log(colors.yellow.bold("Creating new variable...")); await VariableService.createVariable({ workspace, alreadyEncrypted: true,