import * as wmillclient from "npm:windmill-client@1.333.4";
import wmill from "https://deno.land/x/wmill@v1.333.4/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least one staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    try {
        await sh_run(undefined, "git", "push", "--porcelain");
    } catch {
        console.log("Could not push, trying to rebase first");
        await sh_run(undefined, "git", "pull", "--rebase");
        await sh_run(undefined, "git", "push", "--porcelain");
    }
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${nargs.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw Error(err);
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by admin 471 days ago
import * as wmillclient from "npm:windmill-client@1.333.4";
import wmill from "https://deno.land/x/wmill@v1.333.4/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${nargs.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw Error(err);
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 489 days ago
import * as wmillclient from "npm:windmill-client@1.333.4";
import wmill from "https://deno.land/x/wmill@v1.333.4/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 533 days ago
import * as wmillclient from "npm:windmill-client@1.333.3";
import wmill from "https://deno.land/x/wmill@v1.333.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 533 days ago
import * as wmillclient from "npm:windmill-client@1.321.2";
import wmill from "https://deno.land/x/wmill@v1.321.2/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 554 days ago
import * as wmillclient from "npm:windmill-client@1.320.3";
import wmill from "https://deno.land/x/wmill@v1.320.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 555 days ago
import * as wmillclient from "npm:windmill-client@1.320.1";
import wmill from "https://deno.land/x/wmill@v1.320.1/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing ${path_type} ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } if (path_type == "app") {
    return `${path}.app/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 555 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.293.1/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  let repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const azureMatch = repo_url.match(/AZURE_DEVOPS_TOKEN\((?<url>.+)\)/);
  if (azureMatch) {
    console.log(
      "Requires Azure DevOps service account access token, requesting..."
    );
    const azureResource = await wmillclient.getResource(azureMatch.groups.url);
    const response = await fetch(
      `https://login.microsoftonline.com/${azureResource.azureTenantId}/oauth2/token`,
      {
        method: "POST",
        body: new URLSearchParams({
          client_id: azureResource.azureClientId,
          client_secret: azureResource.azureClientSecret,
          grant_type: "client_credentials",
          resource: "499b84ac-1321-427f-aa17-267ca6975798/.default",
        }),
      }
    );
    const { access_token } = await response.json();
    repo_url = repo_url.replace(azureMatch[0], access_token);
  }
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${(path ?? parent_path)
        ?.split("/")
        .slice(0, 2)
        .join("__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${(
        path ?? parent_path
      )?.replaceAll("/", "__")}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 561 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.293.1/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
  group_by_folder = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
    group_by_folder
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret,
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
  group_by_folder: boolean,
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName = group_by_folder
    ? `wm_deploy/${workspace_id}/${
      (path ?? parent_path)?.split("/").slice(0, 2).join("__")
    }`
    : `wm_deploy/${workspace_id}/${path_type}/${
      (path ?? parent_path)?.replaceAll(
        "/",
        "__",
      )
    }`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? "",
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? "",
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position;
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(
        " ",
      )
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean,
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 578 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.293.1/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 592 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.293.1.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-1, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 592 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.293.1.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-2, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 592 days ago
import * as wmillclient from "npm:windmill-client@1.293.1";
import wmill from "https://deno.land/x/wmill@v1.289.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-2, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position < 0) {
    secret_position = nargs.length - 1 + secret_position
  }
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 592 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.289.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-2, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch || path_type === "user" || path_type === "group") {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else if (path_type == "user") {
    return `${path}.user.*`;
  } else if (path_type == "group") {
    return `${path}.group.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule"
    | "user"
    | "group",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--include-users",
    "--include-groups",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 602 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`
  );
  await wmill_sync_pull(
    path_type,
    workspace_id,
    path,
    parent_path,
    skip_secret
  );
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = ["clone", "--quiet", "--depth", "1"];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(-2, "git", ...args);
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(undefined, "git", "sparse-checkout", "add", subfolder);
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName =
    path !== undefined
      ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
      : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll(
          "/",
          "__"
        )}`;
  try {
    await sh_run(undefined, "git", "checkout", branchName);
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`
    );
    try {
      await sh_run(undefined, "git", "checkout", "-b", branchName);
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true"
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? ""
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? ""
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(undefined, "git", "add", `${parent_path}**`);
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(undefined, "git", "diff", "--cached", "--quiet");
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(undefined, "git", "commit", "-m", commit_msg);
    await sh_run(undefined, "git", "push", "--porcelain");
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${args.join(
      " "
    )}' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  path: string
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type:
    | "script"
    | "flow"
    | "app"
    | "folder"
    | "resource"
    | "variable"
    | "resourcetype"
    | "schedule",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--includes",
    includes.join(",")
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "");
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 609 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  skip_secret = true,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path, skip_secret);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined
    ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${
      parent_path.replaceAll("/", "__")
    }`;
  try {
    await sh_run(
      undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? '',
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? '',
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
  skip_secret: boolean,
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    skip_secret ? "--skip-secrets" : "",
    "--include-schedules",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd = cmd.filter((elt) => elt !== "")
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 631 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined
    ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${
      parent_path.replaceAll("/", "__")
    }`;
  try {
    await sh_run(
      undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL") ?? '',
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME") ?? '',
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  const nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else if (path_type == "resourcetype") {
    return `${path}.resource-type.*`;
  } else if (path_type == "resource") {
    return `${path}.resource.*`;
  } else if (path_type == "variable") {
    return `${path}.variable.*`;
  } else if (path_type == "schedule") {
    return `${path}.schedule.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type: "script" | "flow" | "app" | "folder" | "resource" | "variable" | "resourcetype" | "schedule",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
) {
  const includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--include-schedules",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  const cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 631 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app" | "folder",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined
    ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${
      parent_path.replaceAll("/", "__")
    }`;
  try {
    await sh_run(
      undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  let nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type: "script" | "flow" | "app" | "folder",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type: "script" | "flow" | "app" | "folder",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
) {
  let includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs;
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--include-schedules",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 632 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app" | "folder",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined
    ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${
      parent_path.replaceAll("/", "__")
    }`;
  try {
    await sh_run(
      undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  let nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type: "script" | "flow" | "app" | "folder",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type: "script" | "flow" | "app" | "folder",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
) {
  let includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs;
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 632 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app" | "folder",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(
    `Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`,
  );
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(
    workspace_id,
    path_type,
    path,
    parent_path,
    use_individual_branch,
  );
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined
    ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}`
    : `wm_deploy/${workspace_id}/${path_type}/${
      parent_path.replaceAll("/", "__")
    }`;
  try {
    await sh_run(
      undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`);
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`);
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(
  secret_position: number | undefined,
  cmd: string,
  ...args: string[]
) {
  let nargs = secret_position != undefined ? args.slice() : args;
  if (secret_position != undefined) {
    nargs[secret_position] = "***";
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(
  path_type: "script" | "flow" | "app" | "folder",
  path: string,
) {
  if (path_type == "flow") {
    return `${path}.flow/*`;
  } else if (path_type == "folder") {
    return `${path}/folder.meta.*`;
  } else {
    return `${path}.*`;
  }
}
async function wmill_sync_pull(
  path_type: "script" | "flow" | "app" | "folder",
  workspace_id: string,
  path: string | undefined,
  parent_path: string | undefined,
) {
  let includes = [];
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path));
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path));
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs;
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes",
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice();
  cmd2[secret_position] = "***";
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 634 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice()
  cmd2[secret_position] = '***'
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice()
  cmd2[secret_position] = '***'
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  let cmd2 = cmd.slice()
  cmd2[secret_position] = '***'
  console.log(`Running 'wmill ${cmd2.join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(secret_position: number, ...cmd: string[]) {
  cmd[secret_position] = '***'
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    6,
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? ""
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    3,
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(...cmd: string[], secret_position: number) {
  cmd[secret_position] = '***'
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    "workspace",
    "add",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(...cmd: string[]) {
  cmd[3] = '***'
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    -2,
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      undefined,
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
    undefined,
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        undefined,
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        undefined,
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    undefined,
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    undefined,
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}**, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        undefined,
        "git",
        "add",
        `${parent_path}**`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      undefined,
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      undefined,
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      undefined,
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(secret_position: number | undefined, cmd: string, ...args: string[]) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${path}*, ${e}`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch (e) {
      console.log(`Unable to stage files matching ${parent_path}, ${e}`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[], secret_position?: number) {
  let nargs = secret_position != undefined ? args.slice() : args
  if (secret_position != undefined) {
    nargs[secret_position] = '***'
  }
  console.log(`Running '${cmd} ${nargs.join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(","),
    3
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path_type, workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function regexFromPath(path_type: "script" | "flow" | "app", path: string ) {
    if (path_type == 'flow') {
        return `${path}.flow/*`
    } else {
        return `${path}.*`
    }
}
async function wmill_sync_pull(path_type: "script" | "flow" | "app", workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(regexFromPath(path_type, path))
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(regexFromPath(path_type, parent_path))
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(",")
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 635 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(`${path}*`)
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(`${parent_path}*`)
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--includes", 
    includes.join(",")
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 643 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(`${path}*`)
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(`${parent_path}*`)
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--excludes",
    "**",
    "--includes", 
    includes.join(",")
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 643 days ago
import * as wmillclient from "npm:windmill-client@1.258.3";
import wmill from "https://deno.land/x/wmill@v1.258.3/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let includes = []
  if (path !== undefined && path !== null && path !== "") {
    includes.push(`${path}*`)
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    includes.push(`${parent_path}*`)
  }
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  let includesArgs
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
    "--excludes"
    "**"
    "--includes", 
    includes.join(",")
  );
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 643 days ago
import * as wmillclient from "npm:windmill-client@1.258.2";
import wmill from "https://deno.land/x/wmill@v1.258.2/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let wmillignore = `*\n`
  if (path !== undefined && path !== null && path !== "") {
    wmillignore = `${wmillignore}\n!${path}*\n`
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    wmillignore = `${wmillignore}\n!${parent_path}*\n`
  }
  await Deno.writeTextFile(".wmillignore", wmillignore);
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 643 days ago
import * as wmillclient from "npm:windmill-client@1.253.8";
import wmill from "https://deno.land/x/wmill@v1.253.8/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let wmillignore = `*\n`
  if (path !== undefined && path !== null && path !== "") {
    wmillignore = `${wmillignore}\n!${path}*\n`
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    wmillignore = `${wmillignore}\n!${parent_path}*\n`
  }
  await Deno.writeTextFile(".wmillignore", wmillignore);
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 649 days ago
import * as wmillclient from "npm:windmill-client@1.253.7";
import wmill from "https://deno.land/x/wmill@v1.253.7/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let wmillignore = `*\n`
  if (path !== undefined && path !== null && path !== "") {
    wmillignore = `${wmillignore}\n!${path}*\n`
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    wmillignore = `${wmillignore}\n!${parent_path}*\n`
  }
  await Deno.writeTextFile(".wmillignore", wmillignore);
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by rubenfiszel 649 days ago
import * as wmillclient from "npm:windmill-client@1.240.0";
import wmill from "https://deno.land/x/wmill@v1.240.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  workspace_id: string,
  repo_url_resource_path: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(workspace_id, path_type, path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(workspace_id, path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  workspace_id: string,
  path_type: "script" | "flow" | "app",
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${workspace_id}/${path_type}/${path.replaceAll("/", "__")}` : `wm_deploy/${workspace_id}/${path_type}/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(workspace_id: string, path: string | undefined, parent_path: string | undefined) {
  let wmillignore = `*\n`
  if (path !== undefined && path !== null && path !== "") {
    wmillignore = `${wmillignore}\n!${path}*\n`
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    wmillignore = `${wmillignore}\n!${parent_path}*\n`
  }
  await Deno.writeTextFile(".wmillignore", wmillignore);
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    workspace_id,
    workspace_id,
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    workspace_id,
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 660 days ago
import * as wmillclient from "npm:windmill-client@1.240.0";
import wmill from "https://deno.land/x/wmill@v1.240.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string | undefined,
  parent_path: string | undefined,
  commit_msg: string,
  use_individual_branch = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path ?? ""} with parent ${parent_path ?? ""}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(path, parent_path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path, parent_path);
  await git_push(path, parent_path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  path: string | undefined,
  parent_path: string | undefined,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = path !== undefined ? `wm_deploy/${path.replaceAll("/", "__")}` : `wm_deploy/${parent_path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string | undefined, parent_path: string | undefined, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  if (path !== undefined && path !== null && path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${path}*`)
    }
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    try {
      await sh_run(
        "git",
        "add",
        `${parent_path}*`,
      );
    } catch {
      console.log(`Unable to stage files matching ${parent_path}*`)
    }
  }
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(path: string | undefined, parent_path: string | undefined) {
  let wmillignore = `*\n`
  if (path !== undefined && path !== null && path !== "") {
    wmillignore = `${wmillignore}\n!${path}*\n`
  }
  if (parent_path !== undefined && parent_path !== null && parent_path !== "") {
    wmillignore = `${wmillignore}\n!${parent_path}*\n`
  }
  await Deno.writeTextFile(".wmillignore", wmillignore);
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 663 days ago
import * as wmillclient from "npm:windmill-client@1.235.0";
import wmill from "https://deno.land/x/wmill@v1.235.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
  use_individual_branch: boolean = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path);
  await git_push(path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  path: string,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = `wm_deploy/${path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  await sh_run(
    "git",
    "add",
    `${path}*`,
  );
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version",
  );
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 668 days ago
import * as wmillclient from "npm:windmill-client@1";
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
  use_individual_branch: boolean = false,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path}`);
  const repo_name = await git_clone(cwd, repo_resource, use_individual_branch);
  await move_to_git_branch(path, use_individual_branch);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(
    `Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`,
  );
  await wmill_sync_pull(path);
  await git_push(path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(
  cwd: string,
  repo_resource: any,
  use_individual_branch: boolean,
): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (use_individual_branch) {
    args.push("--no-single-branch"); // needed in case the asset branch already exists in the repo
  }
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`,
    );
    throw err;
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(
      `Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`,
    );
    throw err;
  }
  return repo_name;
}
async function move_to_git_branch(
  path: string,
  use_individual_branch: boolean,
) {
  if (!use_individual_branch) {
    return;
  }
  const branchName = `wm_deploy/${path.replaceAll("/", "__")}`;
  try {
    await sh_run(
      "git",
      "checkout",
      branchName,
    );
  } catch (err) {
    console.log(
      `Error checking out branch ${branchName}. It is possible it doesn't exist yet, tentatively creating it... Error was:\n${err}`,
    );
    try {
      await sh_run(
        "git",
        "checkout",
        "-b",
        branchName,
      );
      await sh_run(
        "git",
        "config",
        "--add",
        "--bool",
        "push.autoSetupRemote",
        "true",
      );
    } catch (err) {
      console.log(
        `Error checking out branch '${branchName}'. Error was:\n${err}`,
      );
      throw err;
    }
  }
  console.log(`Successfully switched to branch ${branchName}`);
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  await sh_run(
    "git",
    "add",
    `${path}*`,
  );
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`);
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout));
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr));
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`;
    throw err;
  }
  console.log("Command successfully executed");
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version",
  );
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`);
  await wmill.parse(cmd);
  console.log("Command successfully executed");
}
 Submitted by hugo697 670 days ago
import * as wmillclient from "npm:windmill-client@1";
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path}`);
  const repo_name = await git_clone(cwd, repo_resource);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(`Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`);
  await wmill_sync_pull(path);
  await git_push(path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(cwd: string, repo_resource: any): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  try {
    Deno.chdir(`${cwd}/${repo_name}`);
  } catch (err) {
    console.log(`Error changing directory to '${cwd}/${repo_name}'. Error was:\n${err}`)
    throw err
  }
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  try {
    Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  } catch (err) {
    console.log(`Error changing directory to '${cwd}/${repo_name}/${subfolder}'. Error was:\n${err}`)
    throw err
  }
  return repo_name;
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  await sh_run(
    "git",
    "add",
    `${path}*`,
  );
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
      "--porcelain"
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  console.log(`Running '${cmd} ${args.slice(0, 1).join(" ")} ...'`)
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout, stderr } = await command.output();
  if (stdout.length > 0) {
    console.log(new TextDecoder().decode(stdout))
  }
  if (stderr.length > 0) {
    console.log(new TextDecoder().decode(stderr))
  }
  if (code !== 0) {
    const err = `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}.`
    throw err;
  }
  console.log("Command successfully executed")
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version",
  );
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  console.log(`Running 'wmill ${cmd.slice(0, 1).join(" ")} ...'`)
  await wmill.parse(cmd);
  console.log("Command successfully executed")
}
 Submitted by hugo697 694 days ago
import * as wmillclient from "npm:windmill-client@1";
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  const repo_resource = await wmillclient.getResource(repo_url_resource_path);
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path}`);
  const repo_name = await git_clone(cwd, repo_resource);
  const subfolder = repo_resource.folder ?? "";
  const branch_or_default = repo_resource.branch ?? "<DEFAULT>";
  console.log(`Pushing to repository ${repo_name} in subfolder ${subfolder} on branch ${branch_or_default}`);
  await wmill_sync_pull(path);
  await git_push(path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(cwd: string, repo_resource: any): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = repo_resource.url;
  const subfolder = repo_resource.folder ?? "";
  const branch = repo_resource.branch ?? "";
  const repo_name = basename(repo_url, ".git");
  const args = [
    "clone",
    "--quiet",
    "--depth",
    "1",
  ];
  if (subfolder !== "") {
    args.push("--sparse");
  }
  if (branch !== "") {
    args.push("--branch");
    args.push(branch);
  }
  args.push(repo_url);
  args.push(repo_name);
  await sh_run(
    "git",
    ...args,
  );
  Deno.chdir(`${cwd}/${repo_name}`);
  if (subfolder !== "") {
    await sh_run(
      "git",
      "sparse-checkout",
      "add",
      subfolder,
    );
  }
  Deno.chdir(`${cwd}/${repo_name}/${subfolder}`);
  return repo_name;
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  await sh_run(
    "git",
    "add",
    `${path}*`,
  );
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  // console.log(`Running '${cmd} ${args.join(" ")}'`)
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout: _stdout, stderr: _stderr } = await command.output();
  if (code !== 0) {
    throw `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}`;
  }
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version",
  );
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  await wmill.parse(cmd);
}
 Submitted by hugo697 694 days ago
import * as wmillclient from "npm:windmill-client@1";
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  const cwd = Deno.cwd();
  Deno.env.set("HOME", ".");
  console.log(`Syncing script/flow/app ${path}`);
  const repo_name = await git_clone(repo_url_resource_path);
  Deno.chdir(`${cwd}/${repo_name}`);
  console.log(`Pushing to repository ${repo_name}`);
  await wmill_sync_pull(path);
  await git_push(path, commit_msg);
  console.log("Finished syncing");
  Deno.chdir(`${cwd}`);
}
async function git_clone(repo_resource_path: string): Promise<string> {
  // TODO: handle private SSH keys as well
  const repo_url = (await wmillclient.getResource(repo_resource_path)).url;
  const repo_name = basename(repo_url, ".git");
  await sh_run(
    "git",
    "clone",
    "--quiet",
    "--depth",
    "1",
    // TODO: We could maybe use --sparse here to make the clone more lightweight
    // TODO: It will use the default branch - we could add the branch name to the resource if needed
    repo_url,
    repo_name,
  );
  return repo_name;
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get("WM_EMAIL"),
  );
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get("WM_USERNAME"),
  );
  await sh_run(
    "git",
    "add",
    `${path}*`,
  );
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet",
    );
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg,
    );
    await sh_run(
      "git",
      "push",
    );
    return;
  }
  console.log("No changes detected, nothing to commit. Returning...");
}
async function sh_run(cmd: string, ...args: string[]) {
  // console.log(`Running '${cmd} ${args.join(" ")}'`)
  const command = new Deno.Command(cmd, {
    args: args,
  });
  const { code, stdout: _stdout, stderr: _stderr } = await command.output();
  if (code !== 0) {
    throw `SH command '${cmd} ${
      args.join(" ")
    }' returned with a non-zero status ${code}`;
  }
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version",
  );
  console.log("Adding Windmill workspace");
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("WM_WORKSPACE"),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
  );
  console.log("Pulling workspace into git repo");
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? "",
    "--workspace",
    Deno.env.get("WM_WORKSPACE"),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  );
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  await wmill.parse(cmd);
}
 Submitted by hugo697 697 days ago
import * as wmillclient from "npm:windmill-client@1"
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts"
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts"
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  let cwd = Deno.cwd()
  Deno.env.set("HOME", ".")
  console.log(`Syncing script/flow/app ${path}`)
  let repo_name = await git_clone(repo_url_resource_path)
  Deno.chdir(`${cwd}/${repo_name}`)
  console.log(`Pushing to repository ${repo_name}`)
  await wmill_sync_pull(path)
  await git_push(path, commit_msg)
  console.log("Finished syncing")
  Deno.chdir(`${cwd}`)
}
async function git_clone(repo_resource_path: string): string {
  // TODO: handle private SSH keys as well
  let repo_url = (await wmillclient.getResource(repo_resource_path)).url
  let repo_name = basename(repo_url, ".git")
  await sh_run(
    "git",
    "clone",
    "--quiet",
    "--depth",
    "1",
    // TODO: We could maybe use --sparse here to make the clone more lightweight
    // TODO: It will use the default branch - we could add the branch name to the resource if needed
    repo_url,
    repo_name
  )
  return repo_name
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get('WM_EMAIL')
  )
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get('WM_USERNAME')
  )
  await sh_run(
    "git",
    "add",
    `${path}*`
  )
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet"
    )
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg
    )
    await sh_run(
      "git",
      "push"
    )
    return
  }
  console.log("No changes detected, nothing to commit. Returning...")
}
async function sh_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  let proc = Deno.run({ 
    cmd: cmd,
  })
  let status = await proc.status()
  if (!status.success) {
    throw `SH command '${cmd.join(" ")}' returned with a non-zero status ${status.code}`
  }
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`)
  await wmill_run(
    "version"
  )
  console.log("Adding Windmill workspace")
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
  )
  console.log("Pulling workspace into git repo")
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
    "--workspace",
    Deno.env.get('WM_WORKSPACE'),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  )
  await Deno.remove(".wmillignore")
}
async function wmill_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  await wmill.parse(cmd)
}
 Submitted by hugo697 699 days ago
import * as wmillclient from "npm:windmill-client@1"
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  let cwd = Deno.cwd();
  console.log(`Syncing script/flow/app ${path}`)
  let repo_name = await git_clone(repo_url_resource_path)
  Deno.chdir(`${cwd}/${repo_name}`);
  console.log(`Pushing to repository ${repo_name}`)
  await wmill_sync_pull(path)
  await git_push(path, commit_msg)
  console.log("Finished syncing")
  Deno.chdir(`${cwd}`)
}
async function git_clone(repo_resource_path: string): string {
  // TODO: handle private SSH keys as well
  let repo_url = (await wmillclient.getResource(repo_resource_path)).url
  let repo_name = basename(repo_url, ".git")
  await sh_run(
    "git",
    "clone",
    "--quiet",
    "--depth",
    "1",
    // TODO: We could maybe use --sparse here to make the clone more lightweight
    // TODO: It will use the default branch - we could add the branch name to the resource if needed
    repo_url,
    repo_name
  )
  return repo_name
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get('WM_EMAIL')
  )
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get('WM_USERNAME')
  )
  await sh_run(
    "git",
    "add",
    `${path}*`
  )
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet"
    )
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg
    )
    await sh_run(
      "git",
      "push"
    )
    return
  }
  console.log("No changes detected, nothing to commit. Returning...")
}
async function sh_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  let proc = Deno.run({ 
    cmd: cmd,
  })
  let status = await proc.status()
  if (!status.success) {
    throw `SH command '${cmd.join(" ")}' returned with a non-zero status ${status.code}`
  }
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version"
  );
  console.log("Adding Windmill workspace")
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
  );
  console.log("Pulling workspace into git repo")
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
    "--workspace",
    Deno.env.get('WM_WORKSPACE'),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  )
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  await wmill.parse(cmd);
}
 Submitted by hugo697 704 days ago
import * as wmillclient from "npm:windmill-client@1"
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  path: string,
  commit_msg: string,
) {
  let cwd = Deno.cwd();
  console.log(`Syncing script/flow/app ${path}`)
  let repo_name = await git_clone(repo_url_resource_path)
  Deno.chdir(`${cwd}/${repo_name}`);
  console.log(`Pushing to repository ${repo_name}`)
  await wmill_sync_pull(path)
  await git_push(path, commit_msg)
  console.log("Finished syncing")
  Deno.chdir(`${cwd}`)
}
async function git_clone(repo_resource_path: string): string {
  // TODO: handle private SSH keys as well
  let repo_url = (await wmillclient.getResource(repo_resource_path)).url
  let repo_name = basename(repo_url, ".git")
  await sh_run(
    "git",
    "clone",
    "--quiet",
    "--depth",
    "1",
    // we could use --sparse here
    // Will use the default branch - we could askl the user to use a custom branch instead
    repo_url,
    repo_name
  )
  return repo_name
}
async function git_push(path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get('WM_EMAIL')
  )
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get('WM_USERNAME')
  )
  await sh_run(
    "git",
    "add",
    `${path}*`
  )
  try {
    await sh_run(
      "git",
      "diff",
      "--cached",
      "--quiet"
    )
  } catch {
    // git diff returns exit-code = 1 when there's at least on staged changes
    await sh_run(
      "git",
      "commit",
      "-m",
      commit_msg
    )
    await sh_run(
      "git",
      "push"
    )
    return
  }
  console.log("No changes detected, nothing to commit. Returning...")
}
async function sh_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  let proc = Deno.run({ 
    cmd: cmd,
  })
  let status = await proc.status()
  if (!status.success) {
    throw `SH command '${cmd.join(" ")}' returned with a non-zero status ${status.code}`
  }
}
async function wmill_sync_pull(path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${path}`);
  await wmill_run(
    "version"
  );
  console.log("Adding Windmill workspace")
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
  );
  console.log("Pulling workspace into git repo")
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
    "--workspace",
    Deno.env.get('WM_WORKSPACE'),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  )
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  await wmill.parse(cmd);
}
 Submitted by hugo697 704 days ago
import * as wmillclient from "npm:windmill-client@1"
import wmill from "https://deno.land/x/wmill@v1.218.0/main.ts";
import { basename } from "https://deno.land/std@0.208.0/path/mod.ts";
export async function main(
  repo_url_resource_path: string,
  script_path: string,
  commit_msg: string,
) {
  let cwd = Deno.cwd();
  console.log(`Syncing script ${script_path}`)
  let repo_name = await git_clone(repo_url_resource_path)
  Deno.chdir(`${cwd}/${repo_name}`);
  console.log(`Pushing to repository ${repo_name}`)
  await wmill_sync_pull(script_path)
  await git_push(script_path, commit_msg)
  console.log("Finished syncing")
  Deno.chdir(`${cwd}`)
}
async function git_clone(repo_resource_path: string): string {
  // TODO: handle private SSH keys as well
  let repo_url = (await wmillclient.getResource(repo_resource_path)).url
  let repo_name = basename(repo_url, ".git")
  await sh_run(
    "git",
    "clone",
    "--quiet",
    "--depth",
    "1",
    // TODO: We could maybe use --sparse here to make the clone more lightweight
    // TODO: Will use the default branch - we could add the branch name to the resource if needed
    repo_url,
    repo_name
  )
  return repo_name
}
async function git_push(script_path: string, commit_msg: string) {
  await sh_run(
    "git",
    "config",
    "user.email",
    Deno.env.get('WM_EMAIL')
  )
  await sh_run(
    "git",
    "config",
    "user.name",
    Deno.env.get('WM_USERNAME')
  )
  await sh_run(
    "git",
    "add",
    `${script_path}*`
  )
  await sh_run(
    "git",
    "commit",
    "--allow-empty",
    "-m",
    commit_msg
  )
  await sh_run(
    "git",
    "push"
  )
}
async function sh_run(...cmd: string[]) {
  // console.log(`Running '${cmd.join(" ")}'`)
  let proc = Deno.run({ 
    cmd: cmd,
  })
  let status = await proc.status()
  if (!status.success) {
    throw `SH command '${cmd.join(" ")}' returned with a non-zero status ${status.code}`
  }
}
async function wmill_sync_pull(script_path: string) {
  await Deno.writeTextFile(".wmillignore", `*\n!${script_path}`);
  await wmill_run(
    "version"
  );
  console.log("Adding Windmill workspace")
  await wmill_run(
    "workspace",
    "add",
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get('WM_WORKSPACE'),
    Deno.env.get("BASE_INTERNAL_URL") + "/",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
  );
  console.log("Pulling workspace into git repo")
  await wmill_run(
    "sync",
    "pull",
    "--token",
    Deno.env.get("WM_TOKEN") ?? '',
    "--workspace",
    Deno.env.get('WM_WORKSPACE'),
    "--yes",
    "--raw",
    "--skip-variables",
    "--skip-secrets",
    "--skip-resources",
  )
  await Deno.remove(".wmillignore");
}
async function wmill_run(...cmd: string[]) {
  await wmill.parse(cmd);
} Submitted by hugo697 705 days ago