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 143 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 161 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 205 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 205 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 226 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 228 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 228 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 234 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 250 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 265 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 265 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 265 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 265 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 275 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 281 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 304 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 304 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 304 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 304 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 307 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 307 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 307 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 307 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 307 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 307 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 307 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 307 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 308 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 308 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 315 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 315 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 315 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,
);
}