Compare commits
8 Commits
tests/flow
...
v1.417.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e87a860626 | ||
|
|
00748f43fe | ||
|
|
021ed5a38b | ||
|
|
e92a338432 | ||
|
|
a1c0f676ca | ||
|
|
372f5f4335 | ||
|
|
ea40331ab7 | ||
|
|
57d59bc90a |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## [1.417.2](https://github.com/windmill-labs/windmill/compare/v1.417.1...v1.417.2) (2024-11-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** improve pulling instance with folderPerInstance ([00748f4](https://github.com/windmill-labs/windmill/commit/00748f43feab4f28f0dd2682e3dc8ccc15a5f49f))
|
||||
|
||||
## [1.417.1](https://github.com/windmill-labs/windmill/compare/v1.417.0...v1.417.1) (2024-11-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* missing opts for pull and push instance configs ([#4630](https://github.com/windmill-labs/windmill/issues/4630)) ([e92a338](https://github.com/windmill-labs/windmill/commit/e92a338432d2732e6be74c3604b9fa95239e1ca3))
|
||||
|
||||
## 1.417.0 (2024-11-03)
|
||||
|
||||
* feat(cli): instance yaml files inside the instance prefix folders (#4627)
|
||||
|
||||
## [1.416.2](https://github.com/windmill-labs/windmill/compare/v1.416.1...v1.416.2) (2024-11-02)
|
||||
|
||||
|
||||
|
||||
430
backend/Cargo.lock
generated
430
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.416.2"
|
||||
version = "1.417.2"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -29,7 +29,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.416.2"
|
||||
version = "1.417.2"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# Api integration tests
|
||||
|
||||
You'll need deno to be installed and a windmill api endpoint.
|
||||
|
||||
By default the tests use the local environment endpoint <http://localhost:8000>. You can override it using `BASE_URL` environment variable.
|
||||
|
||||
By default the api authentication uses default local env user credentials. You can override api token using `WM_TOKEN` environment variable.
|
||||
|
||||
## Running the api tests
|
||||
|
||||
`deno test --allow-env --allow-net`
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"tasks": {
|
||||
"dev": "deno run --watch main.ts",
|
||||
"test": "deno test --allow-env --allow-net"
|
||||
},
|
||||
"imports": {
|
||||
"@std/assert": "jsr:@std/assert@1"
|
||||
}
|
||||
}
|
||||
40
backend/tests/api/deno.lock
generated
40
backend/tests/api/deno.lock
generated
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"version": "3",
|
||||
"packages": {
|
||||
"specifiers": {
|
||||
"jsr:@std/assert": "jsr:@std/assert@1.0.6",
|
||||
"jsr:@std/assert@1": "jsr:@std/assert@1.0.6",
|
||||
"jsr:@std/internal@^1.0.4": "jsr:@std/internal@1.0.4"
|
||||
},
|
||||
"jsr": {
|
||||
"@std/assert@1.0.6": {
|
||||
"integrity": "1904c05806a25d94fe791d6d883b685c9e2dcd60e4f9fc30f4fc5cf010c72207",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal@^1.0.4"
|
||||
]
|
||||
},
|
||||
"@std/internal@1.0.4": {
|
||||
"integrity": "62e8e4911527e5e4f307741a795c0b0a9e6958d0b3790716ae71ce085f755422"
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": {
|
||||
"https://cdn.skypack.dev/human-id@3.0.0": "https://cdn.skypack.dev/new/human-id@v3.0.0/dist=es2019",
|
||||
"https://cdn.skypack.dev/new/human-id@v3.0.0/dist=es2019": "https://cdn.skypack.dev/error/build:human-id@v3.0.0-ktOXHm1YV4tQ5io95RTp",
|
||||
"https://deno.land/x/nanoid/mod.ts": "https://deno.land/x/nanoid@v3.0.0/mod.ts"
|
||||
},
|
||||
"remote": {
|
||||
"https://cdn.skypack.dev/error/build:human-id@v3.0.0-ktOXHm1YV4tQ5io95RTp": "54c50c8a33ab04f2a14c966809df583d6c59f0f8b549c270d1127afc8d4c652b",
|
||||
"https://deno.land/x/nanoid@v3.0.0/customAlphabet.ts": "1cfd7cfd2f07ca8d78a7e7855fcc9f59abf01ef2a127484ef94328fadf940ead",
|
||||
"https://deno.land/x/nanoid@v3.0.0/customRandom.ts": "af56e19038c891a4b4ef2be931554c27579bd407ee5bbea5cb64f6ee1347cbe3",
|
||||
"https://deno.land/x/nanoid@v3.0.0/mod.ts": "3ead610e40c58d8fdca21d5da9ec661445a2b82526e19c34d05de5f90be8a1be",
|
||||
"https://deno.land/x/nanoid@v3.0.0/nanoid.ts": "8d119bc89a0f34e7bbe0c2dbdc280d01753e431af553d189663492310a31085d",
|
||||
"https://deno.land/x/nanoid@v3.0.0/random.ts": "4da71d5f72f2bfcc6a4ee79b5d4e72f48dcf4fe4c3835fd5ebab08b9f33cd598",
|
||||
"https://deno.land/x/nanoid@v3.0.0/urlAlphabet.ts": "8b1511deb1ecb23c66202b6000dc10fb68f9a96b5550c6c8cef5009324793431"
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@std/assert@1"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
|
||||
import { assertEquals } from "jsr:@std/assert";
|
||||
import type { FlowPreview } from "../../../cli/gen/index.ts";
|
||||
import * as api from "../../../cli/gen/index.ts";
|
||||
import { awaitJobCompletion, setup } from "./utils.ts";
|
||||
|
||||
const flowPreview: FlowPreview = {
|
||||
"args": {
|
||||
"a": 4,
|
||||
"b": 9
|
||||
},
|
||||
"value": {
|
||||
"modules": [
|
||||
{
|
||||
"id": "a",
|
||||
"value": {
|
||||
"type": "rawscript",
|
||||
"content": "// import * as wmill from \"windmill-client\"\n\nexport async function main(a: number, b : number) {\n return a + b\n}\n",
|
||||
"language": "bun",
|
||||
"input_transforms": {
|
||||
"a": {
|
||||
"type": "javascript",
|
||||
"expr": "flow_input.a"
|
||||
},
|
||||
"b": {
|
||||
"type": "javascript",
|
||||
"expr": "flow_input.b"
|
||||
}
|
||||
},
|
||||
"tag": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"value": {
|
||||
"type": "rawscript",
|
||||
"content": "// import * as wmill from \"windmill-client\"\n\nexport async function main(n: number) {\n return n / 2.0\n}\n",
|
||||
"language": "bun",
|
||||
"input_transforms": {
|
||||
"n": {
|
||||
"type": "javascript",
|
||||
"expr": "results.a"
|
||||
}
|
||||
},
|
||||
"tag": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": "u/admin/beauteous_flow"
|
||||
};
|
||||
|
||||
Deno.test("Run a flow preview and check its completion", async () => {
|
||||
const { workspace } = await setup()
|
||||
|
||||
const id = await api.runFlowPreview({
|
||||
workspace,
|
||||
requestBody: flowPreview
|
||||
});
|
||||
|
||||
const result = await awaitJobCompletion({ id, workspace, timeoutMs: 2000 });
|
||||
assertEquals(result.result, 6.5);
|
||||
assertEquals(result.canceled, false);
|
||||
assertEquals(result.success, true);
|
||||
|
||||
});
|
||||
|
||||
Deno.test("Run a flow preview - Immediately cancel and check cancellation status", async () => {
|
||||
const { workspace } = await setup()
|
||||
|
||||
const id = await api.runFlowPreview({
|
||||
workspace,
|
||||
requestBody: flowPreview
|
||||
});
|
||||
|
||||
await api.cancelQueuedJob({ id, workspace, requestBody: { reason: "test cancellation"}});
|
||||
const result = await awaitJobCompletion({ id, workspace, timeoutMs: 200});
|
||||
assertEquals(result.canceled, true);
|
||||
assertEquals(result.success, false);
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
import { OpenAPI, createWorkspace, getJob, login } from "../../../cli/gen/index.ts";
|
||||
|
||||
// Setup method for each api test
|
||||
export async function setup() {
|
||||
await generateApiToken()
|
||||
const workspace = await genTestWorkspace();
|
||||
|
||||
return { workspace }
|
||||
}
|
||||
|
||||
async function generateApiToken() {
|
||||
// if WM_TOKEN env variable not set
|
||||
if (!OpenAPI.TOKEN) {
|
||||
const email = Deno.env.get("LOGIN_WM_EMAIL") || "admin@windmill.dev";
|
||||
const password = Deno.env.get("LOGIN_WM_PASSWORD") || "changeme";
|
||||
const token = await login({ requestBody: { email, password } });
|
||||
OpenAPI.TOKEN = token;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a workspace named "api-tests" is created
|
||||
*/
|
||||
async function genTestWorkspace() {
|
||||
const id = "api-tests"
|
||||
|
||||
await createWorkspace({ requestBody: { id, name: id}}).catch(()=> null)
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns The job result
|
||||
*/
|
||||
export async function awaitJobCompletion(data: { workspace: string, id: string, timeoutMs: number }) {
|
||||
const start = Date.now();
|
||||
while (true) {
|
||||
const result = await getJob(data).catch(()=> null);
|
||||
|
||||
|
||||
if (!!result && result.type === "CompletedJob") {
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((Date.now() - start) > data.timeoutMs) {
|
||||
throw new Error("Job did not finish before the specified timeout: " + data.timeoutMs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.416.2
|
||||
version: 1.417.2
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
|
||||
@@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts";
|
||||
import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts";
|
||||
import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts";
|
||||
|
||||
export const VERSION = "v1.416.2";
|
||||
export const VERSION = "v1.417.2";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
@@ -184,6 +184,7 @@ export type InstanceSyncOptions = {
|
||||
folderPerInstance?: boolean;
|
||||
yes?: boolean;
|
||||
prefix?: string;
|
||||
prefixSettings?: boolean;
|
||||
};
|
||||
|
||||
export async function pickInstance(
|
||||
@@ -260,30 +261,33 @@ export async function pickInstance(
|
||||
|
||||
return instance;
|
||||
}
|
||||
async function instancePull(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
async function instancePull(opts: InstanceSyncOptions) {
|
||||
const instance = await pickInstance(opts, true);
|
||||
log.info("Pulling instance-level changes");
|
||||
log.info(`remote (${instance.name}) -> local`);
|
||||
|
||||
opts.prefix = opts.prefix ?? instance.prefix;
|
||||
let uChanges = 0;
|
||||
if (!opts.skipUsers) {
|
||||
uChanges = (await pullInstanceUsers(true)) as number;
|
||||
uChanges = (await pullInstanceUsers(opts, true)) as number;
|
||||
}
|
||||
let sChanges = 0;
|
||||
if (!opts.skipSettings) {
|
||||
sChanges = (await pullInstanceSettings(true)) as number;
|
||||
sChanges = (await pullInstanceSettings(opts, true)) as number;
|
||||
}
|
||||
let cChanges = 0;
|
||||
if (!opts.skipConfigs) {
|
||||
cChanges = (await pullInstanceConfigs(true)) as number;
|
||||
cChanges = (await pullInstanceConfigs(opts, true)) as number;
|
||||
}
|
||||
let gChanges = 0;
|
||||
if (!opts.skipGroups) {
|
||||
gChanges = (await pullInstanceGroups(true)) as number;
|
||||
gChanges = (await pullInstanceGroups(opts, true)) as number;
|
||||
}
|
||||
|
||||
const totalChanges = uChanges + sChanges + cChanges + gChanges;
|
||||
|
||||
const rootDir = Deno.cwd();
|
||||
|
||||
if (totalChanges > 0) {
|
||||
let confirm = true;
|
||||
if (opts.yes !== true) {
|
||||
@@ -294,17 +298,24 @@ async function instancePull(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
}
|
||||
|
||||
if (confirm) {
|
||||
if (uChanges > 0) {
|
||||
if (opts.folderPerInstance && opts.prefixSettings) {
|
||||
await Deno.mkdir(path.join(rootDir, opts.prefix), {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!opts.skipUsers && uChanges > 0) {
|
||||
await pullInstanceUsers();
|
||||
await pullInstanceUsers(opts);
|
||||
}
|
||||
if (!opts.skipSettings && sChanges > 0) {
|
||||
await pullInstanceSettings();
|
||||
await pullInstanceSettings(opts);
|
||||
}
|
||||
if (!opts.skipConfigs && cChanges > 0) {
|
||||
await pullInstanceConfigs();
|
||||
await pullInstanceConfigs(opts);
|
||||
}
|
||||
if (!opts.skipGroups && gChanges > 0) {
|
||||
await pullInstanceGroups();
|
||||
await pullInstanceGroups(opts);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -313,7 +324,6 @@ async function instancePull(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
|
||||
if (opts.includeWorkspaces) {
|
||||
log.info("\nPulling all workspaces");
|
||||
const rootDir = Deno.cwd();
|
||||
const localWorkspaces = await getLocalWorkspaces(
|
||||
rootDir,
|
||||
instance.prefix,
|
||||
@@ -391,7 +401,7 @@ async function instancePull(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
async function instancePush(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
async function instancePush(opts: InstanceSyncOptions) {
|
||||
let instances = await allInstances();
|
||||
const instance = await pickInstance(opts, true);
|
||||
|
||||
@@ -400,19 +410,19 @@ async function instancePush(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
|
||||
let uChanges = 0;
|
||||
if (!opts.skipUsers) {
|
||||
uChanges = (await pushInstanceUsers(true)) as number;
|
||||
uChanges = (await pushInstanceUsers(opts, true)) as number;
|
||||
}
|
||||
let sChanges = 0;
|
||||
if (!opts.skipSettings) {
|
||||
sChanges = (await pushInstanceSettings(true, opts.baseUrl)) as number;
|
||||
sChanges = (await pushInstanceSettings(opts, true)) as number;
|
||||
}
|
||||
let cChanges = 0;
|
||||
if (!opts.skipConfigs) {
|
||||
cChanges = (await pushInstanceConfigs(true)) as number;
|
||||
cChanges = (await pushInstanceConfigs(opts, true)) as number;
|
||||
}
|
||||
let gChanges = 0;
|
||||
if (!opts.skipGroups) {
|
||||
gChanges = (await pushInstanceGroups(true)) as number;
|
||||
gChanges = (await pushInstanceGroups(opts, true)) as number;
|
||||
}
|
||||
|
||||
const totalChanges = uChanges + sChanges + cChanges + gChanges;
|
||||
@@ -428,16 +438,16 @@ async function instancePush(opts: GlobalOptions & InstanceSyncOptions) {
|
||||
|
||||
if (confirm) {
|
||||
if (!opts.skipUsers && uChanges > 0) {
|
||||
await pushInstanceUsers();
|
||||
await pushInstanceUsers(opts);
|
||||
}
|
||||
if (!opts.skipSettings && sChanges > 0) {
|
||||
await pushInstanceSettings(false, opts.baseUrl);
|
||||
await pushInstanceSettings(opts);
|
||||
}
|
||||
if (!opts.skipConfigs && cChanges > 0) {
|
||||
await pushInstanceConfigs();
|
||||
await pushInstanceConfigs(opts);
|
||||
}
|
||||
if (!opts.skipGroups && gChanges > 0) {
|
||||
await pushInstanceGroups();
|
||||
await pushInstanceGroups(opts);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -709,7 +719,10 @@ const command = new Command()
|
||||
"--prefix <prefix:string>",
|
||||
"Prefix of the local workspaces to pull, used to create the folders when using --include-workspaces"
|
||||
)
|
||||
|
||||
.option(
|
||||
"--prefix-settings",
|
||||
"Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance"
|
||||
)
|
||||
.action(instancePull as any)
|
||||
.command("push")
|
||||
.description(
|
||||
@@ -730,6 +743,10 @@ const command = new Command()
|
||||
"--prefix <prefix:string>",
|
||||
"Prefix of the local workspaces folders to push"
|
||||
)
|
||||
.option(
|
||||
"--prefix-settings",
|
||||
"Store instance yamls inside prefixed folders when using --prefix and --folder-per-instance"
|
||||
)
|
||||
.action(instancePush as any)
|
||||
.command("whoami")
|
||||
.description("Display information about the currently logged-in user")
|
||||
|
||||
@@ -60,7 +60,7 @@ export {
|
||||
// }
|
||||
// });
|
||||
|
||||
export const VERSION = "1.416.2";
|
||||
export const VERSION = "1.417.2";
|
||||
|
||||
const command = new Command()
|
||||
.name("wmill")
|
||||
|
||||
141
cli/settings.ts
141
cli/settings.ts
@@ -3,8 +3,8 @@ import { Confirm } from "./deps.ts";
|
||||
import { colors } from "./deps.ts";
|
||||
import { yamlParseFile } from "./deps.ts";
|
||||
import { log } from "./deps.ts";
|
||||
import { compareInstanceObjects } from "./instance.ts";
|
||||
import { isSuperset } from "./types.ts";
|
||||
import { compareInstanceObjects, InstanceSyncOptions } from "./instance.ts";
|
||||
import { isSuperset, GlobalOptions } from "./types.ts";
|
||||
import { deepEqual } from "./utils.ts";
|
||||
import * as wmill from "./gen/services.gen.ts";
|
||||
import { Config, GlobalSetting } from "./gen/types.gen.ts";
|
||||
@@ -33,6 +33,22 @@ export interface SimplifiedSettings {
|
||||
name: string;
|
||||
}
|
||||
|
||||
const INSTANCE_SETTINGS_PATH = "instance_settings.yaml";
|
||||
let instanceSettingsPath = INSTANCE_SETTINGS_PATH;
|
||||
async function checkInstanceSettingsPath(opts: InstanceSyncOptions) {
|
||||
if (opts.prefix && opts.folderPerInstance && opts.prefixSettings) {
|
||||
instanceSettingsPath = `${opts.prefix}/${INSTANCE_SETTINGS_PATH}`;
|
||||
}
|
||||
}
|
||||
|
||||
const INSTANCE_CONFIGS_PATH = "instance_configs.yaml";
|
||||
let instanceConfigsPath = INSTANCE_CONFIGS_PATH;
|
||||
async function checkInstanceConfigPath(opts: InstanceSyncOptions) {
|
||||
if (opts.prefix && opts.folderPerInstance && opts.prefixSettings) {
|
||||
instanceConfigsPath = `${opts.prefix}/${INSTANCE_CONFIGS_PATH}`;
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushWorkspaceSettings(
|
||||
workspace: string,
|
||||
_path: string,
|
||||
@@ -113,10 +129,10 @@ export async function pushWorkspaceSettings(
|
||||
workspace,
|
||||
requestBody: localSettings.auto_invite_enabled
|
||||
? {
|
||||
operator: localSettings.auto_invite_as === "operator",
|
||||
invite_all: true,
|
||||
auto_add: localSettings.auto_invite_mode === "add",
|
||||
}
|
||||
operator: localSettings.auto_invite_as === "operator",
|
||||
invite_all: true,
|
||||
auto_add: localSettings.auto_invite_mode === "add",
|
||||
}
|
||||
: {},
|
||||
});
|
||||
} catch (_) {
|
||||
@@ -128,10 +144,10 @@ export async function pushWorkspaceSettings(
|
||||
workspace,
|
||||
requestBody: localSettings.auto_invite_enabled
|
||||
? {
|
||||
operator: localSettings.auto_invite_as === "operator",
|
||||
invite_all: false,
|
||||
auto_add: localSettings.auto_invite_mode === "add",
|
||||
}
|
||||
operator: localSettings.auto_invite_as === "operator",
|
||||
invite_all: false,
|
||||
auto_add: localSettings.auto_invite_mode === "add",
|
||||
}
|
||||
: {},
|
||||
});
|
||||
}
|
||||
@@ -156,7 +172,7 @@ export async function pushWorkspaceSettings(
|
||||
settings.error_handler_extra_args
|
||||
) ||
|
||||
localSettings.error_handler_muted_on_cancel !==
|
||||
settings.error_handler_muted_on_cancel
|
||||
settings.error_handler_muted_on_cancel
|
||||
) {
|
||||
log.debug(`Updating error handler...`);
|
||||
await wmill.editErrorHandler({
|
||||
@@ -260,32 +276,36 @@ export async function pushWorkspaceKey(
|
||||
}
|
||||
}
|
||||
|
||||
const INSTANCE_SETTINGS_PATH = "instance_settings.yaml";
|
||||
|
||||
export async function readInstanceSettings() {
|
||||
export async function readInstanceSettings(opts: InstanceSyncOptions) {
|
||||
let localSettings: GlobalSetting[] = [];
|
||||
|
||||
await checkInstanceSettingsPath(opts);
|
||||
|
||||
try {
|
||||
localSettings = (await yamlParseFile(INSTANCE_SETTINGS_PATH)) as GlobalSetting[];
|
||||
localSettings = (await yamlParseFile(instanceSettingsPath)) as GlobalSetting[];
|
||||
} catch {
|
||||
log.warn(`No ${INSTANCE_SETTINGS_PATH} found`);
|
||||
log.warn(`No ${instanceSettingsPath} found`);
|
||||
}
|
||||
return localSettings;
|
||||
}
|
||||
|
||||
|
||||
import { decrypt, encrypt } from "./local_encryption.ts";
|
||||
|
||||
const SENSITIVE_FIELD: string[] = ["license_key", "jwt_secret"]
|
||||
const SENSITIVE_FIELD: string[] = ["license_key", "jwt_secret"];
|
||||
|
||||
async function processInstanceSettings(settings: GlobalSetting[], mode: "encode" | "decode"): Promise<GlobalSetting[]> {
|
||||
async function processInstanceSettings(
|
||||
settings: GlobalSetting[],
|
||||
mode: "encode" | "decode"
|
||||
): Promise<GlobalSetting[]> {
|
||||
const encKey = process.env.WMILL_INSTANCE_LOCAL_ENCRYPTION_KEY;
|
||||
if (encKey) {
|
||||
const res: GlobalSetting[] = []
|
||||
const res: GlobalSetting[] = [];
|
||||
|
||||
for (const s of settings) {
|
||||
if (SENSITIVE_FIELD.includes(s.name) && typeof s.value === "string") {
|
||||
res.push(await processField(s, "value", encKey, mode) as GlobalSetting);
|
||||
res.push(
|
||||
(await processField(s, "value", encKey, mode)) as GlobalSetting
|
||||
);
|
||||
} else if (s.name == "oauths") {
|
||||
if (typeof s.value === "object") {
|
||||
const oauths = s.value as { [key: string]: any };
|
||||
@@ -303,24 +323,42 @@ async function processInstanceSettings(settings: GlobalSetting[], mode: "encode"
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
log.warn("No encryption key found, skipping encryption. Recommend setting WMILL_INSTANCE_LOCAL_ENCRYPTION_KEY");
|
||||
log.warn(
|
||||
"No encryption key found, skipping encryption. Recommend setting WMILL_INSTANCE_LOCAL_ENCRYPTION_KEY"
|
||||
);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
async function processField(obj: { [key: string]: any }, field: string, encKey: string, mode: "encode" | "decode"): Promise<{ [key: string]: any }> {
|
||||
async function processField(
|
||||
obj: { [key: string]: any },
|
||||
field: string,
|
||||
encKey: string,
|
||||
mode: "encode" | "decode"
|
||||
): Promise<{ [key: string]: any }> {
|
||||
return {
|
||||
...obj,
|
||||
[field]: mode === "encode" ? await encrypt(obj[field], encKey) : await decrypt(obj[field], encKey) as any,
|
||||
}
|
||||
[field]:
|
||||
mode === "encode"
|
||||
? await encrypt(obj[field], encKey)
|
||||
: ((await decrypt(obj[field], encKey)) as any),
|
||||
};
|
||||
}
|
||||
|
||||
export async function pullInstanceSettings(preview = false) {
|
||||
export async function pullInstanceSettings(
|
||||
opts: InstanceSyncOptions,
|
||||
preview = false
|
||||
) {
|
||||
const remoteSettings = await wmill.listGlobalSettings();
|
||||
|
||||
await checkInstanceSettingsPath(opts);
|
||||
|
||||
if (preview) {
|
||||
const localSettings: GlobalSetting[] = await readInstanceSettings();
|
||||
const processedSettings = await processInstanceSettings(remoteSettings, "encode");
|
||||
const localSettings: GlobalSetting[] = await readInstanceSettings(opts);
|
||||
const processedSettings = await processInstanceSettings(
|
||||
remoteSettings,
|
||||
"encode"
|
||||
);
|
||||
return compareInstanceObjects(
|
||||
processedSettings,
|
||||
localSettings,
|
||||
@@ -330,30 +368,33 @@ export async function pullInstanceSettings(preview = false) {
|
||||
} else {
|
||||
log.info("Pulling settings from instance");
|
||||
|
||||
const processedSettings = await processInstanceSettings(remoteSettings, "encode");
|
||||
const processedSettings = await processInstanceSettings(
|
||||
remoteSettings,
|
||||
"encode"
|
||||
);
|
||||
await Deno.writeTextFile(
|
||||
INSTANCE_SETTINGS_PATH,
|
||||
instanceSettingsPath,
|
||||
yamlStringify(processedSettings)
|
||||
);
|
||||
|
||||
log.info(colors.green(`Settings written to ${INSTANCE_SETTINGS_PATH}`));
|
||||
log.info(colors.green(`Settings written to ${instanceSettingsPath}`));
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushInstanceSettings(
|
||||
preview: boolean = false,
|
||||
baseUrl?: string
|
||||
opts: InstanceSyncOptions,
|
||||
preview: boolean = false
|
||||
) {
|
||||
const remoteSettings = await wmill.listGlobalSettings();
|
||||
let localSettings: GlobalSetting[] = await readInstanceSettings();
|
||||
let localSettings: GlobalSetting[] = await readInstanceSettings(opts);
|
||||
localSettings = await processInstanceSettings(localSettings, "decode");
|
||||
|
||||
if (baseUrl) {
|
||||
if (opts.baseUrl) {
|
||||
localSettings = localSettings.filter((s) => s.name !== "base_url");
|
||||
localSettings.push({
|
||||
name: "base_url",
|
||||
//@ts-ignore
|
||||
value: baseUrl,
|
||||
value: opts.baseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -404,18 +445,25 @@ export async function pushInstanceSettings(
|
||||
}
|
||||
}
|
||||
|
||||
export async function readLocalConfigs() {
|
||||
export async function readLocalConfigs(
|
||||
opts: InstanceSyncOptions
|
||||
) {
|
||||
let localConfigs: Config[] = [];
|
||||
|
||||
await checkInstanceConfigPath(opts);
|
||||
|
||||
try {
|
||||
localConfigs = (await yamlParseFile("instance_configs.yaml")) as Config[];
|
||||
localConfigs = (await yamlParseFile(instanceConfigsPath)) as Config[];
|
||||
} catch {
|
||||
log.warn("No instance_configs.yaml found");
|
||||
log.warn(`No ${instanceConfigsPath} found`);
|
||||
}
|
||||
return localConfigs;
|
||||
}
|
||||
|
||||
export async function pullInstanceConfigs(preview = false) {
|
||||
export async function pullInstanceConfigs(
|
||||
opts: InstanceSyncOptions,
|
||||
preview = false
|
||||
) {
|
||||
const remoteConfigs = (await wmill.listConfigs()).map((x) => {
|
||||
return {
|
||||
...x,
|
||||
@@ -424,7 +472,7 @@ export async function pullInstanceConfigs(preview = false) {
|
||||
});
|
||||
|
||||
if (preview) {
|
||||
const localConfigs: Config[] = await readLocalConfigs();
|
||||
const localConfigs: Config[] = await readLocalConfigs(opts);
|
||||
|
||||
return compareInstanceObjects(
|
||||
remoteConfigs,
|
||||
@@ -436,22 +484,25 @@ export async function pullInstanceConfigs(preview = false) {
|
||||
log.info("Pulling configs from instance");
|
||||
|
||||
await Deno.writeTextFile(
|
||||
"instance_configs.yaml",
|
||||
instanceConfigsPath,
|
||||
yamlStringify(remoteConfigs as any)
|
||||
);
|
||||
|
||||
log.info(colors.green("Configs written to instance_configs.yaml"));
|
||||
log.info(colors.green(`Configs written to ${instanceConfigsPath}`));
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushInstanceConfigs(preview: boolean = false) {
|
||||
export async function pushInstanceConfigs(
|
||||
opts: InstanceSyncOptions,
|
||||
preview: boolean = false
|
||||
) {
|
||||
const remoteConfigs = (await wmill.listConfigs()).map((x) => {
|
||||
return {
|
||||
...x,
|
||||
name: removeWorkerPrefix(x.name),
|
||||
};
|
||||
});
|
||||
const localConfigs = await readLocalConfigs();
|
||||
const localConfigs = await readLocalConfigs(opts);
|
||||
|
||||
if (preview) {
|
||||
return compareInstanceObjects(
|
||||
|
||||
76
cli/user.ts
76
cli/user.ts
@@ -6,7 +6,7 @@ import {
|
||||
removeType,
|
||||
removePathPrefix,
|
||||
} from "./types.ts";
|
||||
import { compareInstanceObjects } from "./instance.ts";
|
||||
import { compareInstanceObjects, InstanceSyncOptions } from "./instance.ts";
|
||||
import {
|
||||
colors,
|
||||
Command,
|
||||
@@ -23,6 +23,22 @@ import {
|
||||
InstanceGroup,
|
||||
} from "./gen/types.gen.ts";
|
||||
|
||||
const INSTANCE_USERS_PATH = "instance_users.yaml";
|
||||
let instanceUsersPath = INSTANCE_USERS_PATH;
|
||||
function checkInstanceUsersPath(opts: InstanceSyncOptions) {
|
||||
if (opts.prefix && opts.folderPerInstance && opts.prefixSettings) {
|
||||
instanceUsersPath = `${opts.prefix}/${INSTANCE_USERS_PATH}`;
|
||||
}
|
||||
}
|
||||
|
||||
const INSTANCE_GROUPS_PATH = "instance_groups.yaml";
|
||||
let instanceGroupsPath = INSTANCE_GROUPS_PATH;
|
||||
function checkInstanceGroupsPath(opts: InstanceSyncOptions) {
|
||||
if (opts.prefix && opts.folderPerInstance && opts.prefixSettings) {
|
||||
instanceGroupsPath = `${opts.prefix}/${INSTANCE_GROUPS_PATH}`;
|
||||
}
|
||||
}
|
||||
|
||||
async function list(opts: GlobalOptions) {
|
||||
await requireLogin(opts);
|
||||
|
||||
@@ -386,47 +402,61 @@ export async function pushGroup(
|
||||
}
|
||||
}
|
||||
|
||||
export async function pullInstanceUsers(preview: boolean = false) {
|
||||
export async function pullInstanceUsers(
|
||||
opts: InstanceSyncOptions,
|
||||
preview: boolean = false
|
||||
) {
|
||||
const remoteUsers = await wmill.globalUsersExport();
|
||||
|
||||
checkInstanceUsersPath(opts);
|
||||
|
||||
if (preview) {
|
||||
const localUsers: ExportedUser[] = await readInstanceUsers();
|
||||
const localUsers: ExportedUser[] = await readInstanceUsers(opts);
|
||||
return compareInstanceObjects(remoteUsers, localUsers, "email", "user");
|
||||
} else {
|
||||
log.info("Pulling users from instance...");
|
||||
await Deno.writeTextFile(
|
||||
"instance_users.yaml",
|
||||
instanceUsersPath,
|
||||
yamlStringify(remoteUsers as any)
|
||||
);
|
||||
log.info(colors.green("Users written to instance_users.yaml"));
|
||||
log.info(colors.green(`Users written to ${instanceUsersPath}`));
|
||||
}
|
||||
}
|
||||
|
||||
export async function readInstanceUsers() {
|
||||
export async function readInstanceUsers(opts: InstanceSyncOptions) {
|
||||
let localUsers: ExportedUser[] = [];
|
||||
|
||||
await checkInstanceUsersPath(opts);
|
||||
|
||||
try {
|
||||
localUsers = (await yamlParseFile("instance_users.yaml")) as ExportedUser[];
|
||||
localUsers = (await yamlParseFile(instanceUsersPath)) as ExportedUser[];
|
||||
} catch {
|
||||
log.warn("No instance_users.yaml file found");
|
||||
log.warn(`No ${instanceUsersPath} file found`);
|
||||
}
|
||||
return localUsers;
|
||||
}
|
||||
|
||||
export async function readInstanceGroups() {
|
||||
export async function readInstanceGroups(opts: InstanceSyncOptions) {
|
||||
let localGroups: InstanceGroup[] = [];
|
||||
|
||||
checkInstanceGroupsPath(opts);
|
||||
|
||||
try {
|
||||
localGroups = (await yamlParseFile(
|
||||
"instance_groups.yaml"
|
||||
instanceGroupsPath
|
||||
)) as ExportedInstanceGroup[];
|
||||
} catch {
|
||||
log.warn("No instance_groups.yaml file found");
|
||||
log.warn(`No ${instanceGroupsPath} file found`);
|
||||
}
|
||||
return localGroups;
|
||||
}
|
||||
|
||||
export async function pushInstanceUsers(preview: boolean = false) {
|
||||
export async function pushInstanceUsers(
|
||||
opts: InstanceSyncOptions,
|
||||
preview: boolean = false
|
||||
) {
|
||||
const remoteUsers = await wmill.globalUsersExport();
|
||||
const localUsers: ExportedUser[] = await readInstanceUsers();
|
||||
const localUsers: ExportedUser[] = await readInstanceUsers(opts);
|
||||
|
||||
if (preview) {
|
||||
return compareInstanceObjects(localUsers, remoteUsers, "email", "user");
|
||||
@@ -440,27 +470,35 @@ export async function pushInstanceUsers(preview: boolean = false) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function pullInstanceGroups(preview = false) {
|
||||
export async function pullInstanceGroups(
|
||||
opts: InstanceSyncOptions,
|
||||
preview = false
|
||||
) {
|
||||
const remoteGroups = await wmill.exportInstanceGroups();
|
||||
|
||||
checkInstanceGroupsPath(opts);
|
||||
|
||||
if (preview) {
|
||||
const localGroups = await readInstanceGroups();
|
||||
const localGroups = await readInstanceGroups(opts);
|
||||
return compareInstanceObjects(remoteGroups, localGroups, "name", "group");
|
||||
} else {
|
||||
log.info("Pulling groups from instance...");
|
||||
|
||||
await Deno.writeTextFile(
|
||||
"instance_groups.yaml",
|
||||
instanceGroupsPath,
|
||||
yamlStringify(remoteGroups as any)
|
||||
);
|
||||
|
||||
log.info(colors.green("Groups written to instance_groups.yaml"));
|
||||
log.info(colors.green(`Groups written to ${instanceGroupsPath}`));
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushInstanceGroups(preview: boolean = false) {
|
||||
export async function pushInstanceGroups(
|
||||
opts: InstanceSyncOptions,
|
||||
preview: boolean = false
|
||||
) {
|
||||
const remoteGroups = await wmill.exportInstanceGroups();
|
||||
const localGroups = await readInstanceGroups();
|
||||
const localGroups = await readInstanceGroups(opts);
|
||||
|
||||
if (preview) {
|
||||
return compareInstanceObjects(localGroups, remoteGroups, "name", "group");
|
||||
|
||||
@@ -56,7 +56,7 @@ export async function displayWorkerGroups(opts: void) {
|
||||
async function pullWorkerGroups(opts: InstanceSyncOptions) {
|
||||
await pickInstance(opts, true);
|
||||
|
||||
const totalChanges = await pullInstanceConfigs(true) ?? 0;
|
||||
const totalChanges = await pullInstanceConfigs(opts, true) ?? 0;
|
||||
|
||||
if (totalChanges === 0) {
|
||||
log.info("No changes to apply");
|
||||
@@ -72,14 +72,14 @@ async function pullWorkerGroups(opts: InstanceSyncOptions) {
|
||||
}
|
||||
|
||||
if (confirm) {
|
||||
await pullInstanceConfigs(false);
|
||||
await pullInstanceConfigs(opts, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function pushWorkerGroups(opts: InstanceSyncOptions) {
|
||||
await pickInstance(opts, true);
|
||||
|
||||
const totalChanges = await pushInstanceConfigs(true) ?? 0;
|
||||
const totalChanges = await pushInstanceConfigs(opts, true) ?? 0;
|
||||
|
||||
if (totalChanges === 0) {
|
||||
log.info("No changes to apply");
|
||||
@@ -95,7 +95,7 @@ async function pushWorkerGroups(opts: InstanceSyncOptions) {
|
||||
}
|
||||
|
||||
if (confirm) {
|
||||
await pushInstanceConfigs(false);
|
||||
await pushInstanceConfigs(opts, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.416.2",
|
||||
"version": "1.417.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.416.2",
|
||||
"version": "1.417.2",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^4.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.416.2",
|
||||
"version": "1.417.2",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -80,9 +80,8 @@
|
||||
let connectionString = ''
|
||||
let validConnectionString = true
|
||||
function parseConnectionString(close: (_: any) => void) {
|
||||
// parse postgres connection string
|
||||
const regex =
|
||||
/postgres:\/\/(?<user>[^:@]+)(?::(?<password>[^@]+))?@(?<host>[^:\/?]+)(?::(?<port>\d+))?\/(?<dbname>[^\?]+)?(?:\?.*sslmode=(?<sslmode>[^&]+))?/
|
||||
/postgres(?:ql)?:\/\/(?<user>[^:@]+)(?::(?<password>[^@]+))?@(?<host>[^:\/?]+)(?::(?<port>\d+))?\/(?<dbname>[^\?]+)?(?:\?.*sslmode=(?<sslmode>[^&]+))?/
|
||||
const match = connectionString.match(regex)
|
||||
if (match) {
|
||||
validConnectionString = true
|
||||
|
||||
@@ -533,7 +533,7 @@
|
||||
>
|
||||
{:else if notSet == true}
|
||||
<Alert type="error" title="Staging/Prod deploy not set up"
|
||||
>As an admin, go to "Workspace {'->'} Dev/Staging/Prod"</Alert
|
||||
>As an admin, go to Settings {'->'} Workspace {'->'} Deployment UI</Alert
|
||||
>
|
||||
{:else}
|
||||
<Alert type="info" title="Shareable page"
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
Eye,
|
||||
File,
|
||||
FileJson,
|
||||
FileUp,
|
||||
FolderOpen,
|
||||
GitFork,
|
||||
Globe,
|
||||
ChevronUpSquare,
|
||||
History,
|
||||
Pen,
|
||||
Share,
|
||||
@@ -162,7 +162,7 @@
|
||||
},
|
||||
{
|
||||
displayName: 'Move/Rename',
|
||||
icon: FileUp,
|
||||
icon: FolderOpen,
|
||||
action: () => {
|
||||
moveDrawer.openDrawer(path, summary, 'app')
|
||||
},
|
||||
@@ -173,7 +173,7 @@
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to staging/prod',
|
||||
icon: Globe,
|
||||
icon: ChevronUpSquare,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'app')
|
||||
},
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
GitFork,
|
||||
Trash,
|
||||
List,
|
||||
FileUp,
|
||||
Globe,
|
||||
FolderOpen,
|
||||
ChevronUpSquare,
|
||||
Calendar,
|
||||
Share,
|
||||
Archive,
|
||||
@@ -179,7 +179,7 @@
|
||||
},
|
||||
{
|
||||
displayName: 'Move/Rename',
|
||||
icon: FileUp,
|
||||
icon: FolderOpen,
|
||||
action: () => {
|
||||
moveDrawer.openDrawer(path, flow.summary, 'flow')
|
||||
},
|
||||
@@ -197,7 +197,7 @@
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to staging/prod',
|
||||
icon: Globe,
|
||||
icon: ChevronUpSquare,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(path, 'flow')
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import FileInput from '../fileInput/FileInput.svelte'
|
||||
import { goto } from '$lib/navigation'
|
||||
import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte'
|
||||
import { FileUp, Globe, Pen, Share, Trash } from 'lucide-svelte'
|
||||
import { FolderOpen, Globe, Pen, Share, Trash } from 'lucide-svelte'
|
||||
import { isDeployable } from '$lib/utils_deployable'
|
||||
import { getDeployUiSettings } from '$lib/components/home/deploy_ui'
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
return [
|
||||
{
|
||||
displayName: 'Move/Rename',
|
||||
icon: FileUp,
|
||||
icon: FolderOpen,
|
||||
action: () => {
|
||||
moveDrawer.openDrawer(path, summary, 'raw_app')
|
||||
},
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
Code,
|
||||
Copy,
|
||||
Eye,
|
||||
FileUp,
|
||||
FolderOpen,
|
||||
ChevronUpSquare,
|
||||
GitFork,
|
||||
List,
|
||||
Pen,
|
||||
@@ -207,7 +208,7 @@
|
||||
},
|
||||
{
|
||||
displayName: 'Move/Rename',
|
||||
icon: FileUp,
|
||||
icon: FolderOpen,
|
||||
action: () => {
|
||||
moveDrawer.openDrawer(script.path, script.summary, 'script')
|
||||
},
|
||||
@@ -218,7 +219,7 @@
|
||||
? [
|
||||
{
|
||||
displayName: 'Deploy to staging/prod',
|
||||
icon: FileUp,
|
||||
icon: ChevronUpSquare,
|
||||
action: () => {
|
||||
deploymentDrawer.openDrawer(script.path, 'script')
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
FolderOpen,
|
||||
Archive,
|
||||
Trash,
|
||||
Server,
|
||||
ChevronUpSquare,
|
||||
Share,
|
||||
Badge,
|
||||
Loader2,
|
||||
@@ -294,7 +294,7 @@
|
||||
menuItems.push({
|
||||
label: 'Deploy to staging/prod',
|
||||
onclick: () => deploymentDrawer.openDrawer(flow?.path ?? '', 'flow'),
|
||||
Icon: Server
|
||||
Icon: ChevronUpSquare
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
History,
|
||||
Loader2,
|
||||
Pen,
|
||||
Server,
|
||||
ChevronUpSquare,
|
||||
Share,
|
||||
Table2,
|
||||
Trash,
|
||||
@@ -407,7 +407,7 @@
|
||||
if (isDeployable('script', script?.path ?? '', deployUiSettings)) {
|
||||
menuItems.push({
|
||||
label: 'Deploy to staging/prod',
|
||||
Icon: Server,
|
||||
Icon: ChevronUpSquare,
|
||||
onclick: () => {
|
||||
deploymentDrawer.openDrawer(script?.path ?? '', 'script')
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.416.2"
|
||||
wmill_pg = ">=1.416.2"
|
||||
wmill = ">=1.417.2"
|
||||
wmill_pg = ">=1.417.2"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.416.2
|
||||
version: 1.417.2
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
RootModule = 'WindmillClient.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '1.416.2'
|
||||
ModuleVersion = '1.417.2'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.416.2"
|
||||
version = "1.417.2"
|
||||
description = "A client library for accessing Windmill server wrapping the Windmill client API"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill-pg"
|
||||
version = "1.416.2"
|
||||
version = "1.417.2"
|
||||
description = "An extension client for the wmill client library focused on pg"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@windmill/windmill",
|
||||
"version": "1.416.2",
|
||||
"version": "1.417.2",
|
||||
"exports": "./src/index.ts",
|
||||
"publish": {
|
||||
"exclude": ["!src", "./s3Types.ts", "./client.ts"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-client",
|
||||
"description": "Windmill SDK client for browsers and Node.js",
|
||||
"version": "1.416.2",
|
||||
"version": "1.417.2",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.416.2
|
||||
1.417.2
|
||||
|
||||
Reference in New Issue
Block a user