mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
6339775404
* update: add migration for gcp_trigger table, add cli method gcp and add gcp_trigger args for github ci * update: add gcp module and routing it in lib.rs * update: added gcp type to TRIGGER KIND type in db, add new feature condition to try_get_fn and added gcp_trigger feature in cargo file * update: add ui for gcp trigger, added missing triggers type for job kin, add gcp trigger in deploy to functionallity * adding google cloud crate * update: handle pull and push delivery * update: handle pull and push delivery * update: handle push event, changed front ui * update: ui * fix: capture for gcp * update: automatically manage pub sub subscription and refactoring * capture done * update cli types * fix: wrong func argument and type openapi * fix: missing import * update .sqlx * update: svg color and remove pulse button for capture push gcp * update: handle deployto * update script helper and link to hub gcp script/flow * update gcp representation * update: add confirmation modal * add unique index to mitigate same subscriber id, fix `zombie worker`, update test connection logic * Update frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update cli/gen/services.gen.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * nits * update repo ref * fix feature function * update dependencies * update .sqlx * fix missing import * update: handle existing subscription and creating new one or update it * fix ee build * handle existing config properly * update .sqlx * update .sqlx * remove unused * update documentation link fix ci * use on instance of empty_string_as_none fn * update refo ref * updat script_helper * update ui * update migration * add missing arguments * fix and nits * update repo ref * remove unused * nits * add doc links * nits * Update frontend/src/lib/components/triggers/gcp/GcpTriggerPanel.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update frontend/src/lib/components/triggers/gcp/GcpTriggerEditorInner.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * use trigger path as default route path * update .sqlx * update repo ref * update ref * update route path * update types * fix deploy to * nits * update repo ref * update .sqlx * Update frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * nits * nits * nits * remove dupliacte fn and update repo ref * remove unused import * fix missing import * fix: wong name var * update script helper and template script * Update frontend/src/lib/script_helpers.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update ee-repo-ref.txt --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> Co-authored-by: HugoCasa <hugo@casademont.ch>
290 lines
8.2 KiB
TypeScript
290 lines
8.2 KiB
TypeScript
// deno-lint-ignore-file no-explicit-any
|
|
|
|
import {
|
|
Diff,
|
|
SEP,
|
|
colors,
|
|
log,
|
|
path,
|
|
yamlParseContent,
|
|
yamlStringify,
|
|
} from "./deps.ts";
|
|
import { pushApp } from "./apps.ts";
|
|
import { pushFolder } from "./folder.ts";
|
|
import { pushFlow } from "./flow.ts";
|
|
import { pushResource } from "./resource.ts";
|
|
import { pushResourceType } from "./resource-type.ts";
|
|
import { pushVariable } from "./variable.ts";
|
|
import { yamlOptions } from "./sync.ts";
|
|
import { showDiffs } from "./main.ts";
|
|
import { deepEqual, isFileResource } from "./utils.ts";
|
|
import { pushSchedule } from "./schedule.ts";
|
|
import { pushWorkspaceUser } from "./user.ts";
|
|
import { pushGroup } from "./user.ts";
|
|
import { pushWorkspaceSettings, pushWorkspaceKey } from "./settings.ts";
|
|
import { pushTrigger } from "./trigger.ts";
|
|
|
|
export interface DifferenceCreate {
|
|
type: "CREATE";
|
|
path: (string | number)[];
|
|
value: any;
|
|
}
|
|
|
|
export interface DifferenceRemove {
|
|
type: "REMOVE";
|
|
path: (string | number)[];
|
|
oldValue: any;
|
|
}
|
|
|
|
export interface DifferenceChange {
|
|
type: "CHANGE";
|
|
path: (string | number)[];
|
|
value: any;
|
|
oldValue: any;
|
|
}
|
|
|
|
export type Difference = DifferenceCreate | DifferenceRemove | DifferenceChange;
|
|
|
|
export type GlobalOptions = {
|
|
baseUrl: string | undefined;
|
|
workspace: string | undefined;
|
|
token: string | undefined;
|
|
};
|
|
|
|
export function isSuperset(
|
|
subset: Record<string, any>,
|
|
superset: Record<string, any>
|
|
): boolean {
|
|
return Object.keys(subset).every((key) => {
|
|
const eq = deepEqual(subset[key], superset[key]);
|
|
if (!eq && showDiffs) {
|
|
const sub = subset[key];
|
|
const supers = superset[key];
|
|
if (!supers) {
|
|
log.info(`Key ${key} not found in remote`);
|
|
} else {
|
|
log.info(`Found diff for ${key}:`);
|
|
showDiff(
|
|
yamlStringify(sub, yamlOptions),
|
|
yamlStringify(supers, yamlOptions)
|
|
);
|
|
}
|
|
}
|
|
return eq;
|
|
});
|
|
}
|
|
|
|
export function showDiff(local: string, remote: string) {
|
|
let finalString = "";
|
|
if (local?.length > 20000 || remote?.length > 20000) {
|
|
log.info("Diff too large to display");
|
|
return;
|
|
}
|
|
|
|
for (const part of Diff.diffLines(local ?? "", remote ?? "")) {
|
|
if (part.removed) {
|
|
// print red if removed without newline
|
|
finalString += `\x1b[31m${part.value}\x1b[0m`;
|
|
} else if (part.added) {
|
|
// print green if added
|
|
finalString += `\x1b[32m${part.value}\x1b[0m`;
|
|
} else {
|
|
let lines = part.value.split("\n");
|
|
|
|
if (lines.length > 4) {
|
|
lines = lines.slice(0, 2);
|
|
lines.push("...");
|
|
lines = lines.concat(part.value.split("\n").slice(-2));
|
|
}
|
|
// print white if unchanged
|
|
finalString += `\x1b[37m${lines.join("\n")}\x1b[0m`;
|
|
}
|
|
}
|
|
log.info(finalString);
|
|
}
|
|
|
|
export function showConflict(path: string, local: string, remote: string) {
|
|
log.info(colors.yellow(`- ${path}`));
|
|
showDiff(local, remote);
|
|
log.info("\x1b[31mlocal\x1b[31m - \x1b[32mremote\x1b[32m");
|
|
log.info("\n");
|
|
}
|
|
|
|
export async function pushObj(
|
|
workspace: string,
|
|
p: string,
|
|
befObj: any,
|
|
newObj: any,
|
|
plainSecrets: boolean,
|
|
alreadySynced: string[],
|
|
message?: string
|
|
) {
|
|
const typeEnding = getTypeStrFromPath(p);
|
|
|
|
if (typeEnding === "app") {
|
|
const appName = p.split(".app" + SEP)[0];
|
|
await pushApp(workspace, appName, appName + ".app", message);
|
|
} else if (typeEnding === "folder") {
|
|
await pushFolder(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "variable") {
|
|
await pushVariable(workspace, p, befObj, newObj, plainSecrets);
|
|
} else if (typeEnding === "flow") {
|
|
const flowName = p.split(".flow" + SEP)[0];
|
|
await pushFlow(workspace, flowName, flowName + ".flow", message);
|
|
} else if (typeEnding === "resource") {
|
|
if (!alreadySynced.includes(p)) {
|
|
alreadySynced.push(p);
|
|
await pushResource(workspace, p, befObj, newObj);
|
|
}
|
|
} else if (typeEnding === "resource-type") {
|
|
await pushResourceType(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "schedule") {
|
|
await pushSchedule(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "http_trigger") {
|
|
await pushTrigger("http", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "websocket_trigger") {
|
|
await pushTrigger("websocket", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "kafka_trigger") {
|
|
await pushTrigger("kafka", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "nats_trigger") {
|
|
await pushTrigger("nats", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "postgres_trigger") {
|
|
await pushTrigger("postgres", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "mqtt_trigger") {
|
|
await pushTrigger("mqtt", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "sqs_trigger") {
|
|
await pushTrigger("sqs", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "gcp_trigger") {
|
|
await pushTrigger("gcp", workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "user") {
|
|
await pushWorkspaceUser(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "group") {
|
|
await pushGroup(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "settings") {
|
|
await pushWorkspaceSettings(workspace, p, befObj, newObj);
|
|
} else if (typeEnding === "encryption_key") {
|
|
await pushWorkspaceKey(workspace, p, befObj, newObj);
|
|
} else {
|
|
throw new Error(
|
|
`The item ${p} has an unrecognized type ending ${typeEnding}`
|
|
);
|
|
}
|
|
}
|
|
|
|
export function parseFromPath(p: string, content: string): any {
|
|
return p.endsWith(".yaml")
|
|
? yamlParseContent(p, content)
|
|
: p.endsWith(".json")
|
|
? JSON.parse(content)
|
|
: content;
|
|
}
|
|
export function parseFromFile(p: string): any {
|
|
if (p.endsWith(".json")) {
|
|
return JSON.parse(Deno.readTextFileSync(p));
|
|
} else if (p.endsWith(".yaml") || p.endsWith(".yml")) {
|
|
return yamlParseContent(p, Deno.readTextFileSync(p));
|
|
} else {
|
|
throw new Error("Could not read file " + p);
|
|
}
|
|
}
|
|
export function getTypeStrFromPath(
|
|
p: string
|
|
):
|
|
| "script"
|
|
| "variable"
|
|
| "flow"
|
|
| "resource"
|
|
| "resource-type"
|
|
| "folder"
|
|
| "app"
|
|
| "schedule"
|
|
| "http_trigger"
|
|
| "websocket_trigger"
|
|
| "kafka_trigger"
|
|
| "nats_trigger"
|
|
| "postgres_trigger"
|
|
| "mqtt_trigger"
|
|
| "sqs_trigger"
|
|
| "gcp_trigger"
|
|
| "user"
|
|
| "group"
|
|
| "settings"
|
|
| "encryption_key" {
|
|
if (p.includes(".flow" + SEP)) {
|
|
return "flow";
|
|
}
|
|
if (p.includes(".app" + SEP)) {
|
|
return "app";
|
|
}
|
|
const parsed = path.parse(p);
|
|
if (
|
|
parsed.ext == ".go" ||
|
|
parsed.ext == ".ts" ||
|
|
parsed.ext == ".sh" ||
|
|
parsed.ext == ".py" ||
|
|
parsed.ext == ".sql" ||
|
|
parsed.ext == ".gql" ||
|
|
parsed.ext == ".ps1" ||
|
|
parsed.ext == ".js" ||
|
|
parsed.ext == ".php" ||
|
|
parsed.ext == ".rs" ||
|
|
parsed.ext == ".cs" ||
|
|
parsed.ext == ".nu" ||
|
|
parsed.ext == ".java" ||
|
|
// for related places search: ADD_NEW_LANG
|
|
(parsed.ext == ".yml" && parsed.name.split(".").pop() == "playbook")
|
|
) {
|
|
return "script";
|
|
}
|
|
|
|
if (parsed.name === "folder.meta") {
|
|
return "folder";
|
|
}
|
|
|
|
const typeEnding = parsed.name.split(".").at(-1);
|
|
if (
|
|
typeEnding === "script" ||
|
|
typeEnding === "variable" ||
|
|
typeEnding === "resource" ||
|
|
typeEnding === "resource-type" ||
|
|
typeEnding === "app" ||
|
|
typeEnding === "schedule" ||
|
|
typeEnding === "http_trigger" ||
|
|
typeEnding === "websocket_trigger" ||
|
|
typeEnding === "kafka_trigger" ||
|
|
typeEnding === "nats_trigger" ||
|
|
typeEnding === "postgres_trigger" ||
|
|
typeEnding === "mqtt_trigger" ||
|
|
typeEnding === "sqs_trigger" ||
|
|
typeEnding === "gcp_trigger" ||
|
|
typeEnding === "user" ||
|
|
typeEnding === "group" ||
|
|
typeEnding === "settings" ||
|
|
typeEnding === "encryption_key"
|
|
) {
|
|
return typeEnding;
|
|
} else {
|
|
if (isFileResource(p)) {
|
|
return "resource";
|
|
}
|
|
throw new Error("Could not infer type of path " + JSON.stringify(parsed));
|
|
}
|
|
}
|
|
|
|
export function removeType(str: string, type: string) {
|
|
if (
|
|
!str.endsWith("." + type + ".yaml") &&
|
|
!str.endsWith("." + type + ".json")
|
|
) {
|
|
throw new Error(str + " does not end with ." + type + ".(yaml|json)");
|
|
}
|
|
return str.slice(0, str.length - type.length - 6);
|
|
}
|
|
|
|
export function removePathPrefix(str: string, prefix: string) {
|
|
if (!str.startsWith(prefix + "/")) {
|
|
throw new Error(str + " does not start with " + prefix);
|
|
}
|
|
return str.slice(prefix.length + 1);
|
|
}
|