feat(cli): allow all sync options to be passable from wmill.yaml directly

This commit is contained in:
Ruben Fiszel
2024-01-27 16:19:10 +01:00
parent 28a196657f
commit 2a80df4a80
5 changed files with 71 additions and 59 deletions
+23 -4
View File
@@ -1,17 +1,36 @@
import { yamlParse } from "./deps.ts";
export interface WmillConfiguration {
export interface SyncOptions {
stateful?: boolean;
raw?: boolean;
yes?: boolean;
skipPull?: boolean;
failConflicts?: boolean;
plainSecrets?: boolean;
json?: boolean;
skipVariables?: boolean;
skipResources?: boolean;
skipSecrets?: boolean;
includeSchedules?: boolean;
message?: string;
includes?: string[];
extraIncludes?: string[];
excludes?: string[];
}
export async function readConfigFile(): Promise<WmillConfiguration> {
export async function readConfigFile(): Promise<SyncOptions> {
try {
const conf = yamlParse(
await Deno.readTextFile("wmill.yaml")
) as WmillConfiguration;
) as SyncOptions;
return typeof conf == "object" ? conf : ({} as WmillConfiguration);
return typeof conf == "object" ? conf : ({} as SyncOptions);
} catch (e) {
return {};
}
}
export async function mergeConfigWithConfigFile<T>(opts: T): Promise<T> {
const configFile = await readConfigFile();
return Object.assign(configFile, opts);
}
+1
View File
@@ -101,6 +101,7 @@ export async function fetchVersion(baseUrl: string): Promise<string> {
const extraHeaders = getHeaders();
if (extraHeaders) {
for (const [key, value] of Object.entries(extraHeaders)) {
// @ts-ignore
requestHeaders.set(key, value);
}
}
+9 -9
View File
@@ -3,18 +3,18 @@ export { setClient } from "https://deno.land/x/windmill@v1.226.1/mod.ts";
export * from "https://deno.land/x/windmill@v1.226.1/windmill-api/index.ts";
export { SEP } from "https://deno.land/std@0.201.0/path/separator.ts";
// cliffy
export { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.2/command/mod.ts";
export { Table } from "https://deno.land/x/cliffy@v1.0.0-rc.2/table/table.ts";
export { colors } from "https://deno.land/x/cliffy@v1.0.0-rc.2/ansi/colors.ts";
export { Secret } from "https://deno.land/x/cliffy@v1.0.0-rc.2/prompt/secret.ts";
export { Select } from "https://deno.land/x/cliffy@v1.0.0-rc.2/prompt/select.ts";
export { Confirm } from "https://deno.land/x/cliffy@v1.0.0-rc.2/prompt/confirm.ts";
export { Input } from "https://deno.land/x/cliffy@v1.0.0-rc.2/prompt/input.ts";
export { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/mod.ts";
export { Table } from "https://deno.land/x/cliffy@v1.0.0-rc.3/table/table.ts";
export { colors } from "https://deno.land/x/cliffy@v1.0.0-rc.3/ansi/colors.ts";
export { Secret } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/secret.ts";
export { Select } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/select.ts";
export { Confirm } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/confirm.ts";
export { Input } from "https://deno.land/x/cliffy@v1.0.0-rc.3/prompt/input.ts";
export {
DenoLandProvider,
UpgradeCommand,
} from "https://deno.land/x/cliffy@v1.0.0-rc.2/command/upgrade/mod.ts";
export { CompletionsCommand } from "https://deno.land/x/cliffy@v1.0.0-rc.2/command/completions/mod.ts";
} from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/upgrade/mod.ts";
export { CompletionsCommand } from "https://deno.land/x/cliffy@v1.0.0-rc.3/command/completions/mod.ts";
// std
export * as path from "https://deno.land/std@0.184.0/path/mod.ts";
export { ensureDir } from "https://deno.land/std@0.184.0/fs/ensure_dir.ts";
+6 -4
View File
@@ -3,18 +3,20 @@ import { Application, Command, Router, log, open, path } from "./deps.ts";
import { GlobalOptions } from "./types.ts";
import { ignoreF } from "./sync.ts";
import { requireLogin, resolveWorkspace } from "./context.ts";
import { SyncOptions, mergeConfigWithConfigFile } from "./conf.ts";
const PORT = 3001;
async function dev(opts: GlobalOptions & { filter?: string }) {
async function dev(opts: GlobalOptions & SyncOptions) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
log.info("Started dev mode");
let currentLastEdit: LastEdit | undefined = undefined;
const watcher = Deno.watchFs(opts.filter ?? ".");
const watcher = Deno.watchFs(".");
const base = await Deno.realPath(".");
const ignore = await ignoreF();
opts = await mergeConfigWithConfigFile(opts);
const ignore = await ignoreF(opts);
async function watchChanges() {
for await (const event of watcher) {
@@ -159,7 +161,7 @@ async function dev(opts: GlobalOptions & { filter?: string }) {
const command = new Command()
.description("Launch a dev server that will spawn a webserver with HMR")
.option(
"--filter <filter:string>",
"--includes <pattern...:string>",
"Filter paths givena glob pattern or path"
)
// deno-lint-ignore no-explicit-any
+32 -42
View File
@@ -37,8 +37,7 @@ import { handleScriptMetadata, removeExtensionToPath } from "./script.ts";
import { handleFile } from "./script.ts";
import { deepEqual } from "./utils.ts";
import { read } from "https://deno.land/x/cbor@v1.4.1/decode.js";
import { readConfigFile } from "./conf.ts";
import { SyncOptions, mergeConfigWithConfigFile } from "./conf.ts";
type DynFSElement = {
isDirectory: boolean;
@@ -442,11 +441,10 @@ export const isWhitelisted = (p: string) => {
return p == "." + SEP || p == "" || p == "u" || p == "f" || p == "g";
};
export async function ignoreF(): Promise<
(p: string, isDirectory: boolean) => boolean
> {
const wmillconf = await readConfigFile();
export async function ignoreF(wmillconf: {
includes?: string[];
excludes?: string[];
}): Promise<(p: string, isDirectory: boolean) => boolean> {
let whitelist: { approve(file: string): boolean } | undefined = undefined;
if (wmillconf?.includes || wmillconf?.excludes) {
@@ -502,19 +500,9 @@ export async function ignoreF(): Promise<
};
}
async function pull(
opts: GlobalOptions & {
stateful: boolean;
yes: boolean;
failConflicts: boolean;
plainSecrets?: boolean;
json?: boolean;
skipVariables?: boolean;
skipResources?: boolean;
skipSecrets?: boolean;
includeSchedules?: boolean;
}
) {
async function pull(opts: GlobalOptions & SyncOptions) {
opts = await mergeConfigWithConfigFile(opts);
if (opts.stateful) {
await ensureDir(path.join(Deno.cwd(), ".wmill"));
}
@@ -544,7 +532,7 @@ async function pull(
const changes = await compareDynFSElement(
remote,
local,
await ignoreF(),
await ignoreF(opts),
opts.json ?? false,
opts,
false
@@ -713,22 +701,8 @@ function removeSuffix(str: string, suffix: string) {
return str.slice(0, str.length - suffix.length);
}
async function push(
opts: GlobalOptions & {
stateful: boolean;
raw: boolean;
yes: boolean;
skipPull: boolean;
failConflicts: boolean;
plainSecrets?: boolean;
json?: boolean;
skipVariables?: boolean;
skipResources?: boolean;
skipSecrets?: boolean;
includeSchedules?: boolean;
message?: string;
}
) {
async function push(opts: GlobalOptions & SyncOptions) {
opts = await mergeConfigWithConfigFile(opts);
if (opts.raw) {
log.info("--raw is now the default, you can remove it as a flag");
}
@@ -767,7 +741,7 @@ async function push(
const changes = await compareDynFSElement(
local,
remote,
await ignoreF(),
await ignoreF(opts),
opts.json ?? false,
opts,
true
@@ -990,12 +964,12 @@ const command = new Command()
)
.option(
"--raw",
"Push without using state, just overwrite. (Will be removed as a flag and made the default behavior in the future)"
"Push without using state, just overwrite. (Default, has no effect)"
)
.option("--yes", "Pull without needing confirmation")
.option(
"--stateful",
"Pull using state tracking (create .wmill folder and needed for --fail-conflicts). Default currently but will change in favor of --raw"
"Pull using state tracking (create .wmill folder and needed for --fail-conflicts)"
)
.option("--plain-secrets", "Pull secrets as plain text")
.option("--json", "Use JSON instead of YAML")
@@ -1003,6 +977,14 @@ const command = new Command()
.option("--skip-secrets", "Skip syncing only secrets variables")
.option("--skip-resources", "Skip syncing resources")
.option("--include-schedules", "Include syncing schedules")
.option(
"-i --includes <patterns...:file>",
"Patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)"
)
.option(
"-e --excludes <patterns...:file>",
"Patterns to specify which file to NOT take into account."
)
// deno-lint-ignore no-explicit-any
.action(pull as any)
.command("push")
@@ -1015,11 +997,11 @@ const command = new Command()
)
.option(
"--raw",
"Push without using state, just overwrite. (Will be removed as a flag and made the default behavior in the future)"
"Push without using state, just overwrite. (Default, has no effect)"
)
.option(
"--stateful",
"Pull using state tracking (use .wmill folder and needed for --fail-conflicts). Default currently but will change in favor of --raw"
"Pull using state tracking (use .wmill folder and needed for --fail-conflicts)w"
)
.option("--skip-pull", "(stateful only) Push without pulling first")
.option("--yes", "Push without needing confirmation")
@@ -1029,6 +1011,14 @@ const command = new Command()
.option("--skip-secrets", "Skip syncing only secrets variables")
.option("--skip-resources", "Skip syncing resources")
.option("--include-schedules", "Include syncing schedules")
.option(
"-i --includes <patterns...:file>",
"Patterns to specify which file to take into account (among files that are compatible with windmill). Patterns can include * (any string until '/') and ** (any string)"
)
.option(
"-e --excludes <patterns...:file>",
"Patterns to specify which file to NOT take into account."
)
.option(
"--message <message:string>",
"Include a message that will be added to all scripts/flows/apps updated during this push"