diff --git a/cli/conf.ts b/cli/conf.ts index 25009ffb67..ad4b267755 100644 --- a/cli/conf.ts +++ b/cli/conf.ts @@ -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 { + +export async function readConfigFile(): Promise { 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(opts: T): Promise { + const configFile = await readConfigFile(); + return Object.assign(configFile, opts); +} diff --git a/cli/context.ts b/cli/context.ts index 7925cd26c7..6d6e6c3508 100644 --- a/cli/context.ts +++ b/cli/context.ts @@ -101,6 +101,7 @@ export async function fetchVersion(baseUrl: string): Promise { const extraHeaders = getHeaders(); if (extraHeaders) { for (const [key, value] of Object.entries(extraHeaders)) { + // @ts-ignore requestHeaders.set(key, value); } } diff --git a/cli/deps.ts b/cli/deps.ts index 3ae4406a57..b58f7d32a3 100644 --- a/cli/deps.ts +++ b/cli/deps.ts @@ -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"; diff --git a/cli/dev.ts b/cli/dev.ts index 8afb623289..7244828cc2 100644 --- a/cli/dev.ts +++ b/cli/dev.ts @@ -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 ", + "--includes ", "Filter paths givena glob pattern or path" ) // deno-lint-ignore no-explicit-any diff --git a/cli/sync.ts b/cli/sync.ts index c041284ebc..71c29bb65f 100644 --- a/cli/sync.ts +++ b/cli/sync.ts @@ -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 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 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 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 to specify which file to NOT take into account." + ) .option( "--message ", "Include a message that will be added to all scripts/flows/apps updated during this push"