windmill-cli 1.532.0 → 1.533.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/gen/core/OpenAPI.js +1 -1
- package/esm/src/commands/gitsync-settings/pull.js +17 -20
- package/esm/src/commands/gitsync-settings/push.js +3 -5
- package/esm/src/commands/gitsync-settings/utils.js +9 -9
- package/esm/src/commands/init/init.js +9 -9
- package/esm/src/commands/sync/sync.js +139 -28
- package/esm/src/commands/workspace/workspace.js +10 -10
- package/esm/src/core/conf.js +160 -31
- package/esm/src/core/context.js +1 -1
- package/esm/src/core/specific_items.js +141 -0
- package/esm/src/main.js +1 -1
- package/package.json +1 -1
- package/types/_dnt.polyfills.d.ts +6 -0
- package/types/_dnt.polyfills.d.ts.map +1 -1
- package/types/src/commands/gitsync-settings/pull.d.ts.map +1 -1
- package/types/src/commands/gitsync-settings/push.d.ts.map +1 -1
- package/types/src/commands/sync/sync.d.ts +2 -1
- package/types/src/commands/sync/sync.d.ts.map +1 -1
- package/types/src/core/conf.d.ts +27 -0
- package/types/src/core/conf.d.ts.map +1 -1
- package/types/src/core/specific_items.d.ts +36 -0
- package/types/src/core/specific_items.d.ts.map +1 -0
- package/types/src/main.d.ts +1 -1
package/esm/gen/core/OpenAPI.js
CHANGED
|
@@ -3,7 +3,7 @@ import { colors, log, yamlStringify } from "../../../deps.js";
|
|
|
3
3
|
import { requireLogin } from "../../core/auth.js";
|
|
4
4
|
import { resolveWorkspace } from "../../core/context.js";
|
|
5
5
|
import * as wmill from "../../../gen/services.gen.js";
|
|
6
|
-
import { readConfigFile, getEffectiveSettings, DEFAULT_SYNC_OPTIONS } from "../../core/conf.js";
|
|
6
|
+
import { readConfigFile, getEffectiveSettings, DEFAULT_SYNC_OPTIONS, getWmillYamlPath } from "../../core/conf.js";
|
|
7
7
|
import { deepEqual } from "../../utils/utils.js";
|
|
8
8
|
import { getCurrentGitBranch, isGitRepository } from "../../utils/git.js";
|
|
9
9
|
import { GitSyncSettingsConverter } from "./converter.js";
|
|
@@ -83,12 +83,9 @@ export async function pullGitSyncSettings(opts) {
|
|
|
83
83
|
// Convert backend settings to SyncOptions format
|
|
84
84
|
const backendSyncOptions = GitSyncSettingsConverter.fromBackendFormat(selectedRepo.settings);
|
|
85
85
|
// Check if wmill.yaml exists - create a default one if it doesn't exist
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
wmillYamlExists = false;
|
|
86
|
+
const wmillYamlPath = getWmillYamlPath();
|
|
87
|
+
const wmillYamlExists = wmillYamlPath !== null;
|
|
88
|
+
if (!wmillYamlExists) {
|
|
92
89
|
if (!opts.jsonOutput) {
|
|
93
90
|
log.info(colors.yellow("No wmill.yaml file found. Will create one with backend git-sync settings."));
|
|
94
91
|
}
|
|
@@ -110,11 +107,11 @@ export async function pullGitSyncSettings(opts) {
|
|
|
110
107
|
if (isGitRepository()) {
|
|
111
108
|
const currentBranch = getCurrentGitBranch();
|
|
112
109
|
if (currentBranch) {
|
|
113
|
-
if (!updatedConfig.
|
|
114
|
-
updatedConfig.
|
|
110
|
+
if (!updatedConfig.gitBranches) {
|
|
111
|
+
updatedConfig.gitBranches = {};
|
|
115
112
|
}
|
|
116
|
-
if (!updatedConfig.
|
|
117
|
-
updatedConfig.
|
|
113
|
+
if (!updatedConfig.gitBranches[currentBranch]) {
|
|
114
|
+
updatedConfig.gitBranches[currentBranch] = { overrides: {} };
|
|
118
115
|
}
|
|
119
116
|
}
|
|
120
117
|
}
|
|
@@ -268,15 +265,15 @@ export async function pullGitSyncSettings(opts) {
|
|
|
268
265
|
let needsBranchStructure = false;
|
|
269
266
|
if (isGitRepository()) {
|
|
270
267
|
const currentBranch = getCurrentGitBranch();
|
|
271
|
-
if (currentBranch && (!localConfig.
|
|
268
|
+
if (currentBranch && (!localConfig.gitBranches || !localConfig.gitBranches[currentBranch])) {
|
|
272
269
|
needsBranchStructure = true;
|
|
273
270
|
// Create empty branch structure
|
|
274
271
|
const updatedConfig = { ...localConfig };
|
|
275
|
-
if (!updatedConfig.
|
|
276
|
-
updatedConfig.
|
|
272
|
+
if (!updatedConfig.gitBranches) {
|
|
273
|
+
updatedConfig.gitBranches = {};
|
|
277
274
|
}
|
|
278
|
-
if (!updatedConfig.
|
|
279
|
-
updatedConfig.
|
|
275
|
+
if (!updatedConfig.gitBranches[currentBranch]) {
|
|
276
|
+
updatedConfig.gitBranches[currentBranch] = { overrides: {} };
|
|
280
277
|
}
|
|
281
278
|
// Write updated configuration
|
|
282
279
|
await dntShim.Deno.writeTextFile("wmill.yaml", yamlStringify(updatedConfig));
|
|
@@ -322,11 +319,11 @@ export async function pullGitSyncSettings(opts) {
|
|
|
322
319
|
const currentBranch = getCurrentGitBranch();
|
|
323
320
|
if (currentBranch) {
|
|
324
321
|
log.info(`Detected Git repository, adding empty branch structure for: ${currentBranch}`);
|
|
325
|
-
if (!updatedConfig.
|
|
326
|
-
updatedConfig.
|
|
322
|
+
if (!updatedConfig.gitBranches) {
|
|
323
|
+
updatedConfig.gitBranches = {};
|
|
327
324
|
}
|
|
328
|
-
if (!updatedConfig.
|
|
329
|
-
updatedConfig.
|
|
325
|
+
if (!updatedConfig.gitBranches[currentBranch]) {
|
|
326
|
+
updatedConfig.gitBranches[currentBranch] = { overrides: {} };
|
|
330
327
|
}
|
|
331
328
|
}
|
|
332
329
|
}
|
|
@@ -3,7 +3,7 @@ import { colors, log, Confirm } from "../../../deps.js";
|
|
|
3
3
|
import { requireLogin } from "../../core/auth.js";
|
|
4
4
|
import { resolveWorkspace } from "../../core/context.js";
|
|
5
5
|
import * as wmill from "../../../gen/services.gen.js";
|
|
6
|
-
import { readConfigFile, validateBranchConfiguration, getEffectiveSettings } from "../../core/conf.js";
|
|
6
|
+
import { readConfigFile, validateBranchConfiguration, getEffectiveSettings, getWmillYamlPath } from "../../core/conf.js";
|
|
7
7
|
import { deepEqual } from "../../utils/utils.js";
|
|
8
8
|
import { GitSyncSettingsConverter } from "./converter.js";
|
|
9
9
|
import { handleLegacyRepositoryMigration } from "./legacySettings.js";
|
|
@@ -24,10 +24,8 @@ export async function pushGitSyncSettings(opts) {
|
|
|
24
24
|
await requireLogin(opts);
|
|
25
25
|
try {
|
|
26
26
|
// Check if wmill.yaml exists - require it for git-sync settings commands
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
27
|
+
const wmillYamlPath = getWmillYamlPath();
|
|
28
|
+
if (!wmillYamlPath) {
|
|
31
29
|
log.error(colors.red("No wmill.yaml file found. Please run 'wmill init' first to create the configuration file."));
|
|
32
30
|
dntShim.Deno.exit(1);
|
|
33
31
|
}
|
|
@@ -21,11 +21,11 @@ export function normalizeRepoPath(path) {
|
|
|
21
21
|
}
|
|
22
22
|
// Helper to get or create branch configuration
|
|
23
23
|
export function getOrCreateBranchConfig(config, branchName) {
|
|
24
|
-
if (!config.
|
|
25
|
-
config.
|
|
24
|
+
if (!config.gitBranches) {
|
|
25
|
+
config.gitBranches = {};
|
|
26
26
|
}
|
|
27
|
-
if (!config.
|
|
28
|
-
config.
|
|
27
|
+
if (!config.gitBranches[branchName]) {
|
|
28
|
+
config.gitBranches[branchName] = {};
|
|
29
29
|
}
|
|
30
30
|
return {
|
|
31
31
|
config,
|
|
@@ -36,20 +36,20 @@ export function getOrCreateBranchConfig(config, branchName) {
|
|
|
36
36
|
export function applyBackendSettingsToBranch(config, branchName, backendSettings) {
|
|
37
37
|
const { config: updatedConfig } = getOrCreateBranchConfig(config, branchName);
|
|
38
38
|
// Get the base settings (top-level + defaults) to compare against
|
|
39
|
-
const {
|
|
39
|
+
const { gitBranches, ...topLevelSettings } = config;
|
|
40
40
|
const baseSettings = { ...DEFAULT_SYNC_OPTIONS, ...topLevelSettings };
|
|
41
41
|
// Only store fields that differ from the base settings
|
|
42
42
|
Object.keys(backendSettings).forEach(key => {
|
|
43
|
-
if (key !== '
|
|
43
|
+
if (key !== 'gitBranches' && backendSettings[key] !== undefined) {
|
|
44
44
|
const backendValue = backendSettings[key];
|
|
45
45
|
const baseValue = baseSettings[key];
|
|
46
46
|
// Only store if different from base
|
|
47
47
|
const isDifferent = GitSyncSettingsConverter.isDifferent(backendValue, baseValue);
|
|
48
48
|
if (isDifferent) {
|
|
49
|
-
if (!updatedConfig.
|
|
50
|
-
updatedConfig.
|
|
49
|
+
if (!updatedConfig.gitBranches[branchName].overrides) {
|
|
50
|
+
updatedConfig.gitBranches[branchName].overrides = {};
|
|
51
51
|
}
|
|
52
|
-
updatedConfig.
|
|
52
|
+
updatedConfig.gitBranches[branchName].overrides[key] = backendValue;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
});
|
|
@@ -20,16 +20,16 @@ async function initAction(opts) {
|
|
|
20
20
|
if (isGitRepository()) {
|
|
21
21
|
const currentBranch = getCurrentGitBranch();
|
|
22
22
|
if (currentBranch) {
|
|
23
|
-
initialConfig.
|
|
23
|
+
initialConfig.gitBranches = {
|
|
24
24
|
[currentBranch]: { overrides: {} },
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
|
-
initialConfig.
|
|
28
|
+
initialConfig.gitBranches = {};
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
initialConfig.
|
|
32
|
+
initialConfig.gitBranches = {};
|
|
33
33
|
}
|
|
34
34
|
await dntShim.Deno.writeTextFile("wmill.yaml", yamlStringify(initialConfig));
|
|
35
35
|
log.info(colors.green("wmill.yaml created with default settings"));
|
|
@@ -66,15 +66,15 @@ async function initAction(opts) {
|
|
|
66
66
|
})))) {
|
|
67
67
|
// Update the config with workspace binding
|
|
68
68
|
const currentConfig = await import("../../core/conf.js").then((m) => m.readConfigFile());
|
|
69
|
-
if (!currentConfig.
|
|
70
|
-
currentConfig.
|
|
69
|
+
if (!currentConfig.gitBranches) {
|
|
70
|
+
currentConfig.gitBranches = {};
|
|
71
71
|
}
|
|
72
|
-
if (!currentConfig.
|
|
73
|
-
currentConfig.
|
|
72
|
+
if (!currentConfig.gitBranches[currentBranch]) {
|
|
73
|
+
currentConfig.gitBranches[currentBranch] = { overrides: {} };
|
|
74
74
|
}
|
|
75
|
-
currentConfig.
|
|
75
|
+
currentConfig.gitBranches[currentBranch].baseUrl =
|
|
76
76
|
activeWorkspace.remote;
|
|
77
|
-
currentConfig.
|
|
77
|
+
currentConfig.gitBranches[currentBranch].workspaceId =
|
|
78
78
|
activeWorkspace.workspaceId;
|
|
79
79
|
await dntShim.Deno.writeTextFile("wmill.yaml", yamlStringify(currentConfig));
|
|
80
80
|
log.info(colors.green(`✓ Bound branch '${currentBranch}' to workspace '${activeWorkspace.name}'`));
|
|
@@ -8,7 +8,9 @@ import { downloadZip } from "./pull.js";
|
|
|
8
8
|
import { exts, findContentFile, findGlobalDeps, findResourceFile, handleScriptMetadata, removeExtensionToPath, } from "../script/script.js";
|
|
9
9
|
import { handleFile } from "../script/script.js";
|
|
10
10
|
import { deepEqual, isFileResource } from "../../utils/utils.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getEffectiveSettings, validateBranchConfiguration, mergeConfigWithConfigFile, } from "../../core/conf.js";
|
|
12
|
+
import { getSpecificItemsForCurrentBranch, isSpecificItem, getBranchSpecificPath, fromBranchSpecificPath, isCurrentBranchFile, isBranchSpecificFile, } from "../../core/specific_items.js";
|
|
13
|
+
import { getCurrentGitBranch } from "../../utils/git.js";
|
|
12
14
|
import { removePathPrefix } from "../../types.js";
|
|
13
15
|
import { listSyncCodebases } from "../../utils/codebase.js";
|
|
14
16
|
import { generateFlowLockInternal, generateScriptMetadataInternal, readLockfile, } from "../../utils/metadata.js";
|
|
@@ -21,8 +23,7 @@ function mergeCliWithEffectiveOptions(cliOpts, effectiveOpts) {
|
|
|
21
23
|
return Object.assign({}, effectiveOpts, cliOpts);
|
|
22
24
|
}
|
|
23
25
|
// Resolve effective sync options using branch-based configuration
|
|
24
|
-
async function resolveEffectiveSyncOptions(workspace, promotion) {
|
|
25
|
-
const localConfig = await readConfigFile();
|
|
26
|
+
async function resolveEffectiveSyncOptions(workspace, localConfig, promotion) {
|
|
26
27
|
return await getEffectiveSettings(localConfig, promotion);
|
|
27
28
|
}
|
|
28
29
|
export function findCodebase(path, codebases) {
|
|
@@ -505,8 +506,30 @@ export async function* readDirRecursiveWithIgnore(ignore, root) {
|
|
|
505
506
|
}
|
|
506
507
|
}
|
|
507
508
|
}
|
|
508
|
-
export async function elementsToMap(els, ignore, json, skips) {
|
|
509
|
+
export async function elementsToMap(els, ignore, json, skips, specificItems) {
|
|
509
510
|
const map = {};
|
|
511
|
+
const processedBasePaths = new Set();
|
|
512
|
+
// First pass: collect all file paths to identify branch-specific files
|
|
513
|
+
const allPaths = [];
|
|
514
|
+
for await (const entry of readDirRecursiveWithIgnore(ignore, els)) {
|
|
515
|
+
if (!entry.isDirectory && !entry.ignored) {
|
|
516
|
+
allPaths.push(entry.path);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
const branchSpecificExists = new Set();
|
|
520
|
+
if (specificItems) {
|
|
521
|
+
const currentBranch = getCurrentGitBranch();
|
|
522
|
+
if (currentBranch) {
|
|
523
|
+
for (const path of allPaths) {
|
|
524
|
+
if (isCurrentBranchFile(path)) {
|
|
525
|
+
const basePath = fromBranchSpecificPath(path, currentBranch);
|
|
526
|
+
if (isSpecificItem(basePath, specificItems)) {
|
|
527
|
+
branchSpecificExists.add(basePath);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
510
533
|
for await (const entry of readDirRecursiveWithIgnore(ignore, els)) {
|
|
511
534
|
if (entry.isDirectory || entry.ignored)
|
|
512
535
|
continue;
|
|
@@ -578,10 +601,18 @@ export async function elementsToMap(els, ignore, json, skips) {
|
|
|
578
601
|
"nu",
|
|
579
602
|
"java",
|
|
580
603
|
"rb",
|
|
581
|
-
// for related places search: ADD_NEW_LANG
|
|
604
|
+
// for related places search: ADD_NEW_LANG
|
|
582
605
|
].includes(path.split(".").pop() ?? "") &&
|
|
583
606
|
!isFileResource(path))
|
|
584
607
|
continue;
|
|
608
|
+
// Handle branch-specific files - skip files for other branches
|
|
609
|
+
if (specificItems && isBranchSpecificFile(path)) {
|
|
610
|
+
const currentBranch = getCurrentGitBranch();
|
|
611
|
+
if (!currentBranch || !isCurrentBranchFile(path)) {
|
|
612
|
+
// Skip branch-specific files for other branches
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
585
616
|
const content = await entry.getContentText();
|
|
586
617
|
if (skips.skipSecrets && path.endsWith(".variable" + ext)) {
|
|
587
618
|
try {
|
|
@@ -612,17 +643,45 @@ export async function elementsToMap(els, ignore, json, skips) {
|
|
|
612
643
|
log.warn(`Error reading variable ${path} to check for secrets`);
|
|
613
644
|
}
|
|
614
645
|
}
|
|
615
|
-
|
|
646
|
+
// Handle branch-specific path mapping after all filtering
|
|
647
|
+
if (specificItems) {
|
|
648
|
+
const currentBranch = getCurrentGitBranch();
|
|
649
|
+
if (currentBranch && isCurrentBranchFile(path)) {
|
|
650
|
+
// This is a branch-specific file for current branch
|
|
651
|
+
const basePath = fromBranchSpecificPath(path, currentBranch);
|
|
652
|
+
if (isSpecificItem(basePath, specificItems)) {
|
|
653
|
+
// Map to base path for push operations
|
|
654
|
+
map[basePath] = content;
|
|
655
|
+
processedBasePaths.add(basePath);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// Branch-specific file doesn't match pattern, skip it
|
|
659
|
+
continue;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
else if (!isBranchSpecificFile(path)) {
|
|
663
|
+
// This is a regular base file, check if we should skip it
|
|
664
|
+
if (processedBasePaths.has(path)) {
|
|
665
|
+
// Skip base file, we already processed branch-specific version
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
map[path] = content;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
// No specific items configuration, use regular path
|
|
673
|
+
map[entry.path] = content;
|
|
674
|
+
}
|
|
616
675
|
}
|
|
617
676
|
return map;
|
|
618
677
|
}
|
|
619
|
-
async function compareDynFSElement(els1, els2, ignore, json, skips, ignoreMetadataDeletion, codebases, ignoreCodebaseChanges) {
|
|
678
|
+
async function compareDynFSElement(els1, els2, ignore, json, skips, ignoreMetadataDeletion, codebases, ignoreCodebaseChanges, specificItems) {
|
|
620
679
|
const [m1, m2] = els2
|
|
621
680
|
? await Promise.all([
|
|
622
|
-
elementsToMap(els1, ignore, json, skips),
|
|
623
|
-
elementsToMap(els2, ignore, json, skips),
|
|
681
|
+
elementsToMap(els1, ignore, json, skips, specificItems),
|
|
682
|
+
elementsToMap(els2, ignore, json, skips, specificItems),
|
|
624
683
|
])
|
|
625
|
-
: [await elementsToMap(els1, ignore, json, skips), {}];
|
|
684
|
+
: [await elementsToMap(els1, ignore, json, skips, specificItems), {}];
|
|
626
685
|
const changes = [];
|
|
627
686
|
function parseYaml(k, v) {
|
|
628
687
|
if (k.endsWith(".script.yaml")) {
|
|
@@ -985,6 +1044,8 @@ async function buildTracker(changes) {
|
|
|
985
1044
|
return tracker;
|
|
986
1045
|
}
|
|
987
1046
|
export async function pull(opts) {
|
|
1047
|
+
const originalCliOpts = { ...opts };
|
|
1048
|
+
opts = await mergeConfigWithConfigFile(opts);
|
|
988
1049
|
// Validate branch configuration early
|
|
989
1050
|
try {
|
|
990
1051
|
await validateBranchConfiguration(false, opts.yes);
|
|
@@ -1002,9 +1063,11 @@ export async function pull(opts) {
|
|
|
1002
1063
|
const workspace = await resolveWorkspace(opts);
|
|
1003
1064
|
await requireLogin(opts);
|
|
1004
1065
|
// Resolve effective sync options with branch awareness
|
|
1005
|
-
const effectiveOpts = await resolveEffectiveSyncOptions(workspace, opts.promotion);
|
|
1066
|
+
const effectiveOpts = await resolveEffectiveSyncOptions(workspace, opts, opts.promotion);
|
|
1067
|
+
// Extract specific items configuration before merging overwrites gitBranches
|
|
1068
|
+
const specificItems = getSpecificItemsForCurrentBranch(opts);
|
|
1006
1069
|
// Merge CLI flags with resolved settings (CLI flags take precedence only for explicit overrides)
|
|
1007
|
-
opts = mergeCliWithEffectiveOptions(
|
|
1070
|
+
opts = mergeCliWithEffectiveOptions(originalCliOpts, effectiveOpts);
|
|
1008
1071
|
const codebases = await listSyncCodebases(opts);
|
|
1009
1072
|
log.info(colors.gray("Computing the files to update locally to match remote (taking wmill.yaml into account)"));
|
|
1010
1073
|
let resourceTypeToFormatExtension = {};
|
|
@@ -1020,7 +1083,7 @@ export async function pull(opts) {
|
|
|
1020
1083
|
const local = !opts.stateful
|
|
1021
1084
|
? await FSFSElement(dntShim.Deno.cwd(), codebases, true)
|
|
1022
1085
|
: await FSFSElement(path.join(dntShim.Deno.cwd(), ".wmill"), [], true);
|
|
1023
|
-
const changes = await compareDynFSElement(remote, local, await ignoreF(opts), opts.json ?? false, opts, false, codebases, true);
|
|
1086
|
+
const changes = await compareDynFSElement(remote, local, await ignoreF(opts), opts.json ?? false, opts, false, codebases, true, specificItems);
|
|
1024
1087
|
log.info(`remote (${workspace.name}) -> local: ${changes.length} changes to apply`);
|
|
1025
1088
|
// Handle JSON output for dry-run
|
|
1026
1089
|
if (opts.dryRun && opts.jsonOutput) {
|
|
@@ -1032,6 +1095,12 @@ export async function pull(opts) {
|
|
|
1032
1095
|
...(change.name === "edited" && change.codebase
|
|
1033
1096
|
? { codebase_changed: true }
|
|
1034
1097
|
: {}),
|
|
1098
|
+
...(specificItems && isSpecificItem(change.path, specificItems)
|
|
1099
|
+
? {
|
|
1100
|
+
branch_specific: true,
|
|
1101
|
+
branch_specific_path: getBranchSpecificPath(change.path, specificItems)
|
|
1102
|
+
}
|
|
1103
|
+
: {}),
|
|
1035
1104
|
})),
|
|
1036
1105
|
total: changes.length,
|
|
1037
1106
|
};
|
|
@@ -1040,7 +1109,7 @@ export async function pull(opts) {
|
|
|
1040
1109
|
}
|
|
1041
1110
|
if (changes.length > 0) {
|
|
1042
1111
|
if (!opts.jsonOutput) {
|
|
1043
|
-
prettyChanges(changes);
|
|
1112
|
+
prettyChanges(changes, specificItems);
|
|
1044
1113
|
}
|
|
1045
1114
|
if (opts.dryRun) {
|
|
1046
1115
|
log.info(colors.gray(`Dry run complete.`));
|
|
@@ -1056,8 +1125,16 @@ export async function pull(opts) {
|
|
|
1056
1125
|
const conflicts = [];
|
|
1057
1126
|
log.info(colors.gray(`Applying changes to files ...`));
|
|
1058
1127
|
for await (const change of changes) {
|
|
1059
|
-
|
|
1060
|
-
|
|
1128
|
+
// Determine if this file should be written to a branch-specific path
|
|
1129
|
+
let targetPath = change.path;
|
|
1130
|
+
if (specificItems && isSpecificItem(change.path, specificItems)) {
|
|
1131
|
+
const branchSpecificPath = getBranchSpecificPath(change.path, specificItems);
|
|
1132
|
+
if (branchSpecificPath) {
|
|
1133
|
+
targetPath = branchSpecificPath;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
const target = path.join(dntShim.Deno.cwd(), targetPath);
|
|
1137
|
+
const stateTarget = path.join(dntShim.Deno.cwd(), ".wmill", targetPath);
|
|
1061
1138
|
if (change.name === "edited") {
|
|
1062
1139
|
if (opts.stateful) {
|
|
1063
1140
|
try {
|
|
@@ -1089,11 +1166,11 @@ export async function pull(opts) {
|
|
|
1089
1166
|
}
|
|
1090
1167
|
}
|
|
1091
1168
|
if (exts.some((e) => change.path.endsWith(e))) {
|
|
1092
|
-
log.info(`Editing script content of ${change.path}`);
|
|
1169
|
+
log.info(`Editing script content of ${targetPath}${targetPath !== change.path ? colors.gray(` (branch-specific override for ${change.path})`) : ""}`);
|
|
1093
1170
|
}
|
|
1094
1171
|
else if (change.path.endsWith(".yaml") ||
|
|
1095
1172
|
change.path.endsWith(".json")) {
|
|
1096
|
-
log.info(`Editing ${getTypeStrFromPath(change.path)} ${change.path}`);
|
|
1173
|
+
log.info(`Editing ${getTypeStrFromPath(change.path)} ${targetPath}${targetPath !== change.path ? colors.gray(` (branch-specific override for ${change.path})`) : ""}`);
|
|
1097
1174
|
}
|
|
1098
1175
|
await dntShim.Deno.writeTextFile(target, change.after);
|
|
1099
1176
|
if (opts.stateful) {
|
|
@@ -1105,10 +1182,10 @@ export async function pull(opts) {
|
|
|
1105
1182
|
await ensureDir(path.dirname(target));
|
|
1106
1183
|
if (opts.stateful) {
|
|
1107
1184
|
await ensureDir(path.dirname(stateTarget));
|
|
1108
|
-
log.info(`Adding ${getTypeStrFromPath(change.path)} ${change.path}`);
|
|
1185
|
+
log.info(`Adding ${getTypeStrFromPath(change.path)} ${targetPath}${targetPath !== change.path ? colors.gray(` (branch-specific override for ${change.path})`) : ""}`);
|
|
1109
1186
|
}
|
|
1110
1187
|
await dntShim.Deno.writeTextFile(target, change.content);
|
|
1111
|
-
log.info(`Writing ${getTypeStrFromPath(change.path)} ${change.path}`);
|
|
1188
|
+
log.info(`Writing ${getTypeStrFromPath(change.path)} ${targetPath}${targetPath !== change.path ? colors.gray(` (branch-specific override for ${change.path})`) : ""}`);
|
|
1112
1189
|
if (opts.stateful) {
|
|
1113
1190
|
await dntShim.Deno.copyFile(target, stateTarget);
|
|
1114
1191
|
}
|
|
@@ -1166,6 +1243,12 @@ export async function pull(opts) {
|
|
|
1166
1243
|
...(change.name === "edited" && change.codebase
|
|
1167
1244
|
? { codebase_changed: true }
|
|
1168
1245
|
: {}),
|
|
1246
|
+
...(specificItems && isSpecificItem(change.path, specificItems)
|
|
1247
|
+
? {
|
|
1248
|
+
branch_specific: true,
|
|
1249
|
+
branch_specific_path: getBranchSpecificPath(change.path, specificItems)
|
|
1250
|
+
}
|
|
1251
|
+
: {}),
|
|
1169
1252
|
})),
|
|
1170
1253
|
total: changes.length,
|
|
1171
1254
|
};
|
|
@@ -1179,17 +1262,27 @@ export async function pull(opts) {
|
|
|
1179
1262
|
console.log(JSON.stringify({ success: true, message: "No changes to apply", total: 0 }, null, 2));
|
|
1180
1263
|
}
|
|
1181
1264
|
}
|
|
1182
|
-
function prettyChanges(changes) {
|
|
1265
|
+
function prettyChanges(changes, specificItems) {
|
|
1183
1266
|
for (const change of changes) {
|
|
1267
|
+
let displayPath = change.path;
|
|
1268
|
+
let branchNote = "";
|
|
1269
|
+
// Check if this will be written as a branch-specific file
|
|
1270
|
+
if (specificItems && isSpecificItem(change.path, specificItems)) {
|
|
1271
|
+
const branchSpecificPath = getBranchSpecificPath(change.path, specificItems);
|
|
1272
|
+
if (branchSpecificPath) {
|
|
1273
|
+
displayPath = branchSpecificPath;
|
|
1274
|
+
branchNote = " (branch-specific)";
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1184
1277
|
if (change.name === "added") {
|
|
1185
|
-
log.info(colors.green(`+ ${getTypeStrFromPath(change.path)} ` +
|
|
1278
|
+
log.info(colors.green(`+ ${getTypeStrFromPath(change.path)} ` + displayPath + colors.gray(branchNote)));
|
|
1186
1279
|
}
|
|
1187
1280
|
else if (change.name === "deleted") {
|
|
1188
|
-
log.info(colors.red(`- ${getTypeStrFromPath(change.path)} ` +
|
|
1281
|
+
log.info(colors.red(`- ${getTypeStrFromPath(change.path)} ` + displayPath + colors.gray(branchNote)));
|
|
1189
1282
|
}
|
|
1190
1283
|
else if (change.name === "edited") {
|
|
1191
1284
|
log.info(colors.yellow(`~ ${getTypeStrFromPath(change.path)} ` +
|
|
1192
|
-
|
|
1285
|
+
displayPath + colors.gray(branchNote) +
|
|
1193
1286
|
(change.codebase ? ` (codebase changed)` : "")));
|
|
1194
1287
|
if (change.before != change.after) {
|
|
1195
1288
|
showDiff(change.before, change.after);
|
|
@@ -1222,6 +1315,10 @@ function removeSuffix(str, suffix) {
|
|
|
1222
1315
|
return str.slice(0, str.length - suffix.length);
|
|
1223
1316
|
}
|
|
1224
1317
|
export async function push(opts) {
|
|
1318
|
+
// Save original CLI options before merging with config file
|
|
1319
|
+
const originalCliOpts = { ...opts };
|
|
1320
|
+
// Load configuration from wmill.yaml and merge with CLI options
|
|
1321
|
+
opts = await mergeConfigWithConfigFile(opts);
|
|
1225
1322
|
// Validate branch configuration early
|
|
1226
1323
|
try {
|
|
1227
1324
|
await validateBranchConfiguration(false, opts.yes);
|
|
@@ -1236,9 +1333,11 @@ export async function push(opts) {
|
|
|
1236
1333
|
const workspace = await resolveWorkspace(opts);
|
|
1237
1334
|
await requireLogin(opts);
|
|
1238
1335
|
// Resolve effective sync options with branch awareness
|
|
1239
|
-
const effectiveOpts = await resolveEffectiveSyncOptions(workspace, opts.promotion);
|
|
1336
|
+
const effectiveOpts = await resolveEffectiveSyncOptions(workspace, opts, opts.promotion);
|
|
1337
|
+
// Extract specific items configuration BEFORE merging overwrites gitBranches
|
|
1338
|
+
const specificItems = getSpecificItemsForCurrentBranch(opts);
|
|
1240
1339
|
// Merge CLI flags with resolved settings (CLI flags take precedence only for explicit overrides)
|
|
1241
|
-
opts = mergeCliWithEffectiveOptions(
|
|
1340
|
+
opts = mergeCliWithEffectiveOptions(originalCliOpts, effectiveOpts);
|
|
1242
1341
|
const codebases = await listSyncCodebases(opts);
|
|
1243
1342
|
if (opts.raw) {
|
|
1244
1343
|
log.info("--raw is now the default, you can remove it as a flag");
|
|
@@ -1263,7 +1362,7 @@ export async function push(opts) {
|
|
|
1263
1362
|
}
|
|
1264
1363
|
const remote = ZipFSElement((await downloadZip(workspace, opts.plainSecrets, opts.skipVariables, opts.skipResources, opts.skipResourceTypes, opts.skipSecrets, opts.includeSchedules, opts.includeTriggers, opts.includeUsers, opts.includeGroups, opts.includeSettings, opts.includeKey, opts.defaultTs)), !opts.json, opts.defaultTs ?? "bun", resourceTypeToFormatExtension, false);
|
|
1265
1364
|
const local = await FSFSElement(path.join(dntShim.Deno.cwd(), ""), codebases, false);
|
|
1266
|
-
const changes = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false);
|
|
1365
|
+
const changes = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false, specificItems);
|
|
1267
1366
|
const globalDeps = await findGlobalDeps();
|
|
1268
1367
|
const tracker = await buildTracker(changes);
|
|
1269
1368
|
const staleScripts = [];
|
|
@@ -1308,6 +1407,12 @@ export async function push(opts) {
|
|
|
1308
1407
|
...(change.name === "edited" && change.codebase
|
|
1309
1408
|
? { codebase_changed: true }
|
|
1310
1409
|
: {}),
|
|
1410
|
+
...(specificItems && isSpecificItem(change.path, specificItems)
|
|
1411
|
+
? {
|
|
1412
|
+
branch_specific: true,
|
|
1413
|
+
branch_specific_path: getBranchSpecificPath(change.path, specificItems)
|
|
1414
|
+
}
|
|
1415
|
+
: {}),
|
|
1311
1416
|
})),
|
|
1312
1417
|
total: changes.length,
|
|
1313
1418
|
};
|
|
@@ -1316,7 +1421,7 @@ export async function push(opts) {
|
|
|
1316
1421
|
}
|
|
1317
1422
|
if (changes.length > 0) {
|
|
1318
1423
|
if (!opts.jsonOutput) {
|
|
1319
|
-
prettyChanges(changes);
|
|
1424
|
+
prettyChanges(changes, specificItems);
|
|
1320
1425
|
}
|
|
1321
1426
|
if (opts.dryRun) {
|
|
1322
1427
|
log.info(colors.gray(`Dry run complete.`));
|
|
@@ -1603,6 +1708,12 @@ export async function push(opts) {
|
|
|
1603
1708
|
...(change.name === "edited" && change.codebase
|
|
1604
1709
|
? { codebase_changed: true }
|
|
1605
1710
|
: {}),
|
|
1711
|
+
...(specificItems && isSpecificItem(change.path, specificItems)
|
|
1712
|
+
? {
|
|
1713
|
+
branch_specific: true,
|
|
1714
|
+
branch_specific_path: getBranchSpecificPath(change.path, specificItems)
|
|
1715
|
+
}
|
|
1716
|
+
: {}),
|
|
1606
1717
|
})),
|
|
1607
1718
|
total: changes.length,
|
|
1608
1719
|
duration_ms: Math.round(performance.now() - start),
|
|
@@ -279,27 +279,27 @@ async function bind(opts, bindWorkspace) {
|
|
|
279
279
|
return;
|
|
280
280
|
}
|
|
281
281
|
// For unbind, check if branch exists
|
|
282
|
-
if (!bindWorkspace && (!config.
|
|
283
|
-
log.error(colors.red(`Branch '${branch}' not found in wmill.yaml
|
|
282
|
+
if (!bindWorkspace && (!config.gitBranches || !config.gitBranches[branch])) {
|
|
283
|
+
log.error(colors.red(`Branch '${branch}' not found in wmill.yaml gitBranches`));
|
|
284
284
|
return;
|
|
285
285
|
}
|
|
286
286
|
// Update the branch configuration with workspace binding
|
|
287
|
-
if (!config.
|
|
288
|
-
config.
|
|
287
|
+
if (!config.gitBranches) {
|
|
288
|
+
config.gitBranches = {};
|
|
289
289
|
}
|
|
290
|
-
if (!config.
|
|
291
|
-
config.
|
|
290
|
+
if (!config.gitBranches[branch]) {
|
|
291
|
+
config.gitBranches[branch] = { overrides: {} };
|
|
292
292
|
}
|
|
293
293
|
if (bindWorkspace && activeWorkspace) {
|
|
294
|
-
config.
|
|
295
|
-
config.
|
|
294
|
+
config.gitBranches[branch].baseUrl = activeWorkspace.remote;
|
|
295
|
+
config.gitBranches[branch].workspaceId = activeWorkspace.workspaceId;
|
|
296
296
|
log.info(colors.green(`✓ Bound branch '${branch}' to workspace '${activeWorkspace.name}'\n` +
|
|
297
297
|
` ${activeWorkspace.workspaceId} on ${activeWorkspace.remote}`));
|
|
298
298
|
}
|
|
299
299
|
else {
|
|
300
300
|
// Unbind
|
|
301
|
-
delete config.
|
|
302
|
-
delete config.
|
|
301
|
+
delete config.gitBranches[branch].baseUrl;
|
|
302
|
+
delete config.gitBranches[branch].workspaceId;
|
|
303
303
|
log.info(colors.green(`✓ Removed workspace binding from branch '${branch}'`));
|
|
304
304
|
}
|
|
305
305
|
// Write back the updated config
|
package/esm/src/core/conf.js
CHANGED
|
@@ -1,13 +1,80 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
2
|
import { log, yamlParseFile, Confirm, yamlStringify } from "../../deps.js";
|
|
3
3
|
import { getCurrentGitBranch, isGitRepository } from "../utils/git.js";
|
|
4
|
+
import { join, dirname, resolve, relative } from "node:path";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
4
7
|
export let showDiffs = false;
|
|
5
8
|
export function setShowDiffs(value) {
|
|
6
9
|
showDiffs = value;
|
|
7
10
|
}
|
|
11
|
+
function getGitRepoRoot() {
|
|
12
|
+
try {
|
|
13
|
+
const result = execSync("git rev-parse --show-toplevel", {
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
stdio: "pipe"
|
|
16
|
+
});
|
|
17
|
+
return result.trim();
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function findWmillYaml() {
|
|
24
|
+
const startDir = resolve(dntShim.Deno.cwd());
|
|
25
|
+
const isInGitRepo = isGitRepository();
|
|
26
|
+
// If not in git repo, only check current directory
|
|
27
|
+
if (!isInGitRepo) {
|
|
28
|
+
const wmillYamlPath = join(startDir, "wmill.yaml");
|
|
29
|
+
return existsSync(wmillYamlPath) ? wmillYamlPath : null;
|
|
30
|
+
}
|
|
31
|
+
// If in git repo, search up to git repository root
|
|
32
|
+
const gitRoot = getGitRepoRoot();
|
|
33
|
+
let currentDir = startDir;
|
|
34
|
+
let foundPath = null;
|
|
35
|
+
while (true) {
|
|
36
|
+
const wmillYamlPath = join(currentDir, "wmill.yaml");
|
|
37
|
+
if (existsSync(wmillYamlPath)) {
|
|
38
|
+
foundPath = wmillYamlPath;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
// Check if we've reached the git repository root
|
|
42
|
+
if (gitRoot && resolve(currentDir) === resolve(gitRoot)) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
// Check if we've reached the filesystem root
|
|
46
|
+
const parentDir = dirname(currentDir);
|
|
47
|
+
if (parentDir === currentDir) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
currentDir = parentDir;
|
|
51
|
+
}
|
|
52
|
+
// If wmill.yaml was found in a parent directory, warn the user and change working directory
|
|
53
|
+
if (foundPath && resolve(dirname(foundPath)) !== resolve(startDir)) {
|
|
54
|
+
const configDir = dirname(foundPath);
|
|
55
|
+
const relativePath = relative(startDir, foundPath);
|
|
56
|
+
log.warn(`⚠️ wmill.yaml found in parent directory: ${relativePath}`);
|
|
57
|
+
// Change working directory to where wmill.yaml was found
|
|
58
|
+
dntShim.Deno.chdir(configDir);
|
|
59
|
+
log.info(`📁 Changed working directory to: ${configDir}`);
|
|
60
|
+
}
|
|
61
|
+
return foundPath;
|
|
62
|
+
}
|
|
63
|
+
export function getWmillYamlPath() {
|
|
64
|
+
return findWmillYaml();
|
|
65
|
+
}
|
|
8
66
|
export async function readConfigFile() {
|
|
9
67
|
try {
|
|
10
|
-
|
|
68
|
+
// First, try to find wmill.yaml recursively
|
|
69
|
+
const wmillYamlPath = findWmillYaml();
|
|
70
|
+
if (!wmillYamlPath) {
|
|
71
|
+
log.warn("No wmill.yaml found. Use 'wmill init' to bootstrap it. Using 'bun' as default typescript runtime.");
|
|
72
|
+
return {};
|
|
73
|
+
}
|
|
74
|
+
const conf = (await yamlParseFile(wmillYamlPath));
|
|
75
|
+
// Handle legacy format migrations (combine overrides and git_branches)
|
|
76
|
+
let needsConfigWrite = false;
|
|
77
|
+
const migrationMessages = [];
|
|
11
78
|
// Handle obsolete overrides format
|
|
12
79
|
if (conf && 'overrides' in conf) {
|
|
13
80
|
const overrides = conf.overrides;
|
|
@@ -18,17 +85,55 @@ export async function readConfigFile() {
|
|
|
18
85
|
" Please delete your wmill.yaml and run 'wmill init' to recreate it with the new format.");
|
|
19
86
|
}
|
|
20
87
|
else {
|
|
21
|
-
// Remove empty overrides
|
|
22
|
-
log.info("ℹ️ Removing empty 'overrides: {}' from wmill.yaml (migrated to git_branches format)");
|
|
88
|
+
// Remove empty overrides
|
|
23
89
|
delete conf.overrides;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
90
|
+
needsConfigWrite = true;
|
|
91
|
+
migrationMessages.push("ℹ️ Removing empty 'overrides: {}' from wmill.yaml (migrated to gitBranches format)");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Handle git_branches to gitBranches migration
|
|
95
|
+
if (conf && 'git_branches' in conf) {
|
|
96
|
+
if (!conf.gitBranches) {
|
|
97
|
+
// Deep copy git_branches to gitBranches (even if empty)
|
|
98
|
+
conf.gitBranches = JSON.parse(JSON.stringify(conf.git_branches));
|
|
99
|
+
needsConfigWrite = true;
|
|
100
|
+
migrationMessages.push("⚠️ Migrating 'git_branches' to 'gitBranches' (camelCase). The snake_case format is deprecated.");
|
|
101
|
+
migrationMessages.push("✅ Successfully migrated 'git_branches' to 'gitBranches' in wmill.yaml");
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
migrationMessages.push("⚠️ Both 'git_branches' and 'gitBranches' found in wmill.yaml. Using 'gitBranches' and ignoring 'git_branches'.");
|
|
105
|
+
}
|
|
106
|
+
// Always remove the old field from config object (both file and memory)
|
|
107
|
+
delete conf.git_branches;
|
|
108
|
+
}
|
|
109
|
+
// Perform single atomic write if any migrations are needed
|
|
110
|
+
if (needsConfigWrite) {
|
|
111
|
+
try {
|
|
112
|
+
await dntShim.Deno.writeTextFile(wmillYamlPath, yamlStringify(conf));
|
|
113
|
+
// Log all migration messages after successful write
|
|
114
|
+
migrationMessages.forEach(msg => {
|
|
115
|
+
if (msg.startsWith('⚠️')) {
|
|
116
|
+
log.warn(msg);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
log.info(msg);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
log.warn(`Could not update wmill.yaml to apply migrations: ${error instanceof Error ? error.message : error}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (migrationMessages.length > 0) {
|
|
128
|
+
// Log messages for non-write cases (like "both found")
|
|
129
|
+
migrationMessages.forEach(msg => {
|
|
130
|
+
if (msg.startsWith('⚠️')) {
|
|
131
|
+
log.warn(msg);
|
|
27
132
|
}
|
|
28
|
-
|
|
29
|
-
log.
|
|
133
|
+
else {
|
|
134
|
+
log.info(msg);
|
|
30
135
|
}
|
|
31
|
-
}
|
|
136
|
+
});
|
|
32
137
|
}
|
|
33
138
|
if (conf?.defaultTs == undefined) {
|
|
34
139
|
log.warn("No defaultTs defined in your wmill.yaml. Using 'bun' as default.");
|
|
@@ -39,8 +144,19 @@ export async function readConfigFile() {
|
|
|
39
144
|
if (e instanceof Error && (e.message.includes("overrides") || e.message.includes("Obsolete configuration format"))) {
|
|
40
145
|
throw e; // Re-throw the specific obsolete format error
|
|
41
146
|
}
|
|
42
|
-
|
|
43
|
-
|
|
147
|
+
// Since we already found the file path, this is likely a parsing or access error
|
|
148
|
+
if (e instanceof Error && e.message.includes("Error parsing yaml")) {
|
|
149
|
+
const yamlError = e.cause instanceof Error ? e.cause.message : String(e.cause);
|
|
150
|
+
throw new Error("❌ YAML syntax error in wmill.yaml:\n" +
|
|
151
|
+
" " + yamlError + "\n" +
|
|
152
|
+
" Please fix the YAML syntax in wmill.yaml or delete the file to start fresh.");
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// File exists but has other issues (permissions, etc.)
|
|
156
|
+
throw new Error("❌ Failed to read wmill.yaml:\n" +
|
|
157
|
+
" " + (e instanceof Error ? e.message : String(e)) + "\n" +
|
|
158
|
+
" Please check file permissions or fix the syntax.");
|
|
159
|
+
}
|
|
44
160
|
}
|
|
45
161
|
}
|
|
46
162
|
// Default sync options - shared across the codebase to prevent duplication
|
|
@@ -74,33 +190,40 @@ export async function validateBranchConfiguration(skipValidation, autoAccept) {
|
|
|
74
190
|
return;
|
|
75
191
|
}
|
|
76
192
|
const config = await readConfigFile();
|
|
77
|
-
const {
|
|
193
|
+
const { gitBranches } = config;
|
|
78
194
|
const currentBranch = getCurrentGitBranch();
|
|
79
|
-
// In a git repository,
|
|
80
|
-
if (!
|
|
81
|
-
log.warn("⚠️ WARNING: In a Git repository, the '
|
|
82
|
-
" Consider adding a
|
|
195
|
+
// In a git repository, gitBranches section is recommended
|
|
196
|
+
if (!gitBranches || Object.keys(gitBranches).length === 0) {
|
|
197
|
+
log.warn("⚠️ WARNING: In a Git repository, the 'gitBranches' section is recommended in wmill.yaml.\n" +
|
|
198
|
+
" Consider adding a gitBranches section with configuration for your Git branches.\n" +
|
|
83
199
|
" Run 'wmill init' to recreate the configuration file with proper branch setup.");
|
|
84
200
|
return;
|
|
85
201
|
}
|
|
86
|
-
// Current branch must be defined in
|
|
87
|
-
if (currentBranch && !
|
|
202
|
+
// Current branch must be defined in gitBranches config
|
|
203
|
+
if (currentBranch && !gitBranches[currentBranch]) {
|
|
88
204
|
// In interactive mode, offer to create the branch
|
|
89
205
|
if (dntShim.Deno.stdin.isTerminal()) {
|
|
90
|
-
const availableBranches = Object.keys(
|
|
91
|
-
log.info(`Current Git branch '${currentBranch}' is not defined in the
|
|
206
|
+
const availableBranches = Object.keys(gitBranches).join(', ');
|
|
207
|
+
log.info(`Current Git branch '${currentBranch}' is not defined in the gitBranches configuration.\n` +
|
|
92
208
|
`Available branches: ${availableBranches}`);
|
|
93
209
|
const shouldCreate = autoAccept || await Confirm.prompt({
|
|
94
210
|
message: `Create empty branch configuration for '${currentBranch}'?`,
|
|
95
211
|
default: true,
|
|
96
212
|
});
|
|
97
213
|
if (shouldCreate) {
|
|
214
|
+
// Warn if branch name contains filesystem-unsafe characters
|
|
215
|
+
if (/[\/\\:*?"<>|.]/.test(currentBranch)) {
|
|
216
|
+
const sanitizedBranchName = currentBranch.replace(/[\/\\:*?"<>|.]/g, '_');
|
|
217
|
+
log.warn(`⚠️ WARNING: Branch name "${currentBranch}" contains filesystem-unsafe characters (/ \\ : * ? " < > | .).`);
|
|
218
|
+
log.warn(` Branch-specific files will be saved with sanitized name: "${sanitizedBranchName}"`);
|
|
219
|
+
log.warn(` Example: "file.variable.yaml" → "file.${sanitizedBranchName}.variable.yaml"`);
|
|
220
|
+
}
|
|
98
221
|
// Read current config, add branch, and write it back
|
|
99
222
|
const currentConfig = await readConfigFile();
|
|
100
|
-
if (!currentConfig.
|
|
101
|
-
currentConfig.
|
|
223
|
+
if (!currentConfig.gitBranches) {
|
|
224
|
+
currentConfig.gitBranches = {};
|
|
102
225
|
}
|
|
103
|
-
currentConfig.
|
|
226
|
+
currentConfig.gitBranches[currentBranch] = { overrides: {} };
|
|
104
227
|
await dntShim.Deno.writeTextFile("wmill.yaml", yamlStringify(currentConfig));
|
|
105
228
|
log.info(`✅ Created empty branch configuration for '${currentBranch}'`);
|
|
106
229
|
}
|
|
@@ -110,9 +233,15 @@ export async function validateBranchConfiguration(skipValidation, autoAccept) {
|
|
|
110
233
|
}
|
|
111
234
|
}
|
|
112
235
|
else {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
236
|
+
// Warn about filesystem-unsafe characters in branch name
|
|
237
|
+
if (/[\/\\:*?"<>|.]/.test(currentBranch)) {
|
|
238
|
+
const sanitizedBranchName = currentBranch.replace(/[\/\\:*?"<>|.]/g, '_');
|
|
239
|
+
log.warn(`⚠️ WARNING: Branch name "${currentBranch}" contains filesystem-unsafe characters (/ \\ : * ? " < > | .).`);
|
|
240
|
+
log.warn(` Branch-specific files will use sanitized name: "${sanitizedBranchName}"`);
|
|
241
|
+
}
|
|
242
|
+
log.warn(`⚠️ WARNING: Current Git branch '${currentBranch}' is not defined in the gitBranches configuration.\n` +
|
|
243
|
+
` Consider adding configuration for branch '${currentBranch}' in the gitBranches section of wmill.yaml.\n` +
|
|
244
|
+
` Available branches: ${Object.keys(gitBranches).join(', ')}`);
|
|
116
245
|
return;
|
|
117
246
|
}
|
|
118
247
|
}
|
|
@@ -120,13 +249,13 @@ export async function validateBranchConfiguration(skipValidation, autoAccept) {
|
|
|
120
249
|
// Get effective settings by merging top-level settings with branch-specific overrides
|
|
121
250
|
export async function getEffectiveSettings(config, promotion, skipBranchValidation, suppressLogs) {
|
|
122
251
|
// Start with top-level settings from config
|
|
123
|
-
const {
|
|
252
|
+
const { gitBranches, ...topLevelSettings } = config;
|
|
124
253
|
let effective = { ...topLevelSettings };
|
|
125
254
|
if (isGitRepository()) {
|
|
126
255
|
const currentBranch = getCurrentGitBranch();
|
|
127
256
|
// If promotion is specified, use that branch's promotionOverrides or overrides
|
|
128
|
-
if (promotion &&
|
|
129
|
-
const targetBranch =
|
|
257
|
+
if (promotion && gitBranches && gitBranches[promotion]) {
|
|
258
|
+
const targetBranch = gitBranches[promotion];
|
|
130
259
|
// First try promotionOverrides, then fall back to overrides
|
|
131
260
|
if (targetBranch.promotionOverrides) {
|
|
132
261
|
Object.assign(effective, targetBranch.promotionOverrides);
|
|
@@ -145,8 +274,8 @@ export async function getEffectiveSettings(config, promotion, skipBranchValidati
|
|
|
145
274
|
}
|
|
146
275
|
}
|
|
147
276
|
// Otherwise use current branch overrides (existing behavior)
|
|
148
|
-
else if (currentBranch &&
|
|
149
|
-
Object.assign(effective,
|
|
277
|
+
else if (currentBranch && gitBranches && gitBranches[currentBranch] && gitBranches[currentBranch].overrides) {
|
|
278
|
+
Object.assign(effective, gitBranches[currentBranch].overrides);
|
|
150
279
|
if (!suppressLogs) {
|
|
151
280
|
log.info(`Applied settings for Git branch: ${currentBranch}`);
|
|
152
281
|
}
|
package/esm/src/core/context.js
CHANGED
|
@@ -79,7 +79,7 @@ async function tryResolveBranchWorkspace(opts) {
|
|
|
79
79
|
}
|
|
80
80
|
// Read wmill.yaml to check for branch workspace configuration
|
|
81
81
|
const config = await readConfigFile();
|
|
82
|
-
const branchConfig = config.
|
|
82
|
+
const branchConfig = config.gitBranches?.[currentBranch];
|
|
83
83
|
// Check if branch has workspace configuration
|
|
84
84
|
if (!branchConfig?.baseUrl || !branchConfig?.workspaceId) {
|
|
85
85
|
return undefined;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { minimatch } from "../../deps.js";
|
|
2
|
+
import { getCurrentGitBranch, isGitRepository } from "../utils/git.js";
|
|
3
|
+
/**
|
|
4
|
+
* Get the specific items configuration for the current git branch
|
|
5
|
+
* Merges commonSpecificItems with branch-specific specificItems
|
|
6
|
+
*/
|
|
7
|
+
export function getSpecificItemsForCurrentBranch(config) {
|
|
8
|
+
if (!isGitRepository() || !config.gitBranches) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const currentBranch = getCurrentGitBranch();
|
|
12
|
+
if (!currentBranch) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const commonItems = config.gitBranches.commonSpecificItems;
|
|
16
|
+
const branchItems = config.gitBranches[currentBranch]?.specificItems;
|
|
17
|
+
// If neither common nor branch-specific items exist, return undefined
|
|
18
|
+
if (!commonItems && !branchItems) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
// Merge common and branch-specific items
|
|
22
|
+
const merged = {};
|
|
23
|
+
// Add common items
|
|
24
|
+
if (commonItems?.variables) {
|
|
25
|
+
merged.variables = [...commonItems.variables];
|
|
26
|
+
}
|
|
27
|
+
if (commonItems?.resources) {
|
|
28
|
+
merged.resources = [...commonItems.resources];
|
|
29
|
+
}
|
|
30
|
+
// Add branch-specific items (extending common items)
|
|
31
|
+
if (branchItems?.variables) {
|
|
32
|
+
merged.variables = [...(merged.variables || []), ...branchItems.variables];
|
|
33
|
+
}
|
|
34
|
+
if (branchItems?.resources) {
|
|
35
|
+
merged.resources = [...(merged.resources || []), ...branchItems.resources];
|
|
36
|
+
}
|
|
37
|
+
return merged;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a path matches any of the patterns in the given list
|
|
41
|
+
*/
|
|
42
|
+
function matchesPatterns(path, patterns) {
|
|
43
|
+
return patterns.some(pattern => minimatch(path, pattern));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if a file path should be treated as branch-specific
|
|
47
|
+
*/
|
|
48
|
+
export function isSpecificItem(path, specificItems) {
|
|
49
|
+
if (!specificItems) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
// Determine the item type from the file path
|
|
53
|
+
if (path.endsWith('.variable.yaml')) {
|
|
54
|
+
return specificItems.variables ? matchesPatterns(path, specificItems.variables) : false;
|
|
55
|
+
}
|
|
56
|
+
if (path.endsWith('.resource.yaml')) {
|
|
57
|
+
return specificItems.resources ? matchesPatterns(path, specificItems.resources) : false;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Convert a base path to a branch-specific path
|
|
63
|
+
*/
|
|
64
|
+
export function toBranchSpecificPath(basePath, branchName) {
|
|
65
|
+
// Extract the extension (e.g., ".variable.yaml" or ".resource.yaml")
|
|
66
|
+
const extensionMatch = basePath.match(/(\.(variable|resource)\.yaml)$/);
|
|
67
|
+
if (!extensionMatch) {
|
|
68
|
+
return basePath; // Return unchanged if no recognized extension
|
|
69
|
+
}
|
|
70
|
+
const extension = extensionMatch[1];
|
|
71
|
+
const pathWithoutExtension = basePath.substring(0, basePath.length - extension.length);
|
|
72
|
+
// Sanitize branch name to be filesystem-safe
|
|
73
|
+
const sanitizedBranchName = branchName.replace(/[\/\\:*?"<>|.]/g, '_');
|
|
74
|
+
// Warn about potential collisions if sanitization occurred
|
|
75
|
+
if (sanitizedBranchName !== branchName) {
|
|
76
|
+
console.warn(`Warning: Branch name "${branchName}" contains filesystem-unsafe characters (/ \\ : * ? " < > | .) and was sanitized to "${sanitizedBranchName}". This may cause collisions with other similarly named branches.`);
|
|
77
|
+
}
|
|
78
|
+
return `${pathWithoutExtension}.${sanitizedBranchName}${extension}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convert a branch-specific path back to a base path
|
|
82
|
+
*/
|
|
83
|
+
export function fromBranchSpecificPath(branchSpecificPath, branchName) {
|
|
84
|
+
// Sanitize branch name the same way as in toBranchSpecificPath
|
|
85
|
+
const sanitizedBranchName = branchName.replace(/[\/\\:*?"<>|.]/g, '_');
|
|
86
|
+
// Pattern: path.sanitizedBranchName.extension
|
|
87
|
+
const escapedBranchName = sanitizedBranchName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
88
|
+
const pattern = new RegExp(`\\.${escapedBranchName}(\\.(variable|resource)\\.yaml)$`);
|
|
89
|
+
const match = branchSpecificPath.match(pattern);
|
|
90
|
+
if (!match) {
|
|
91
|
+
return branchSpecificPath; // Return unchanged if not a branch-specific path
|
|
92
|
+
}
|
|
93
|
+
const extension = match[1];
|
|
94
|
+
const pathWithoutBranchAndExtension = branchSpecificPath.substring(0, branchSpecificPath.length - `.${sanitizedBranchName}${extension}`.length);
|
|
95
|
+
return `${pathWithoutBranchAndExtension}${extension}`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the branch-specific path for the current branch if the item should be branch-specific
|
|
99
|
+
*/
|
|
100
|
+
export function getBranchSpecificPath(basePath, specificItems) {
|
|
101
|
+
if (!isGitRepository() || !specificItems) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const currentBranch = getCurrentGitBranch();
|
|
105
|
+
if (!currentBranch) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
if (isSpecificItem(basePath, specificItems)) {
|
|
109
|
+
return toBranchSpecificPath(basePath, currentBranch);
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
// Cache for compiled regex patterns to avoid recompilation
|
|
114
|
+
const branchPatternCache = new Map();
|
|
115
|
+
/**
|
|
116
|
+
* Check if a path is a branch-specific file for the current branch
|
|
117
|
+
*/
|
|
118
|
+
export function isCurrentBranchFile(path) {
|
|
119
|
+
if (!isGitRepository()) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
const currentBranch = getCurrentGitBranch();
|
|
123
|
+
if (!currentBranch) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
// Use cached pattern or create and cache new one
|
|
127
|
+
let pattern = branchPatternCache.get(currentBranch);
|
|
128
|
+
if (!pattern) {
|
|
129
|
+
pattern = new RegExp(`\\.${currentBranch}\\.(variable|resource)\\.yaml$`);
|
|
130
|
+
branchPatternCache.set(currentBranch, pattern);
|
|
131
|
+
}
|
|
132
|
+
return pattern.test(path);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if a path is a branch-specific file for ANY branch (not necessarily current)
|
|
136
|
+
* Used to identify and skip files from other branches during sync operations
|
|
137
|
+
*/
|
|
138
|
+
export function isBranchSpecificFile(path) {
|
|
139
|
+
// Pattern: *.branchName.variable.yaml or *.branchName.resource.yaml
|
|
140
|
+
return /\.[^.]+\.(variable|resource)\.yaml$/.test(path);
|
|
141
|
+
}
|
package/esm/src/main.js
CHANGED
|
@@ -38,7 +38,7 @@ export { flow, app, script, workspace, resource, resourceType, user, variable, h
|
|
|
38
38
|
// console.error(JSON.stringify(event.error, null, 4));
|
|
39
39
|
// }
|
|
40
40
|
// });
|
|
41
|
-
export const VERSION = "1.
|
|
41
|
+
export const VERSION = "1.533.0";
|
|
42
42
|
const command = new Command()
|
|
43
43
|
.name("wmill")
|
|
44
44
|
.action(() => log.info(`Welcome to Windmill CLI ${VERSION}. Use -h for help.`))
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;;;;;;;WAQG;QACH,IAAI,EAAE,OAAO,CAAC;QAEd;;;;;;;WAOG;QAEH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;KACpC;CACF;AAED,OAAO,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;;;;;;;WAQG;QACH,IAAI,EAAE,OAAO,CAAC;QAEd;;;;;;;WAOG;QAEH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;KACpC;CACF;AAED,OAAO,EAAE,CAAA;AACT,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC;AAgBV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd;;;;WAIG;QACH,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;KAC5C;CACF;AAED,OAAO,EAAE,CAAC;AAEV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAgB;QACxB,SAAS,CAAC,CAAC,EACP,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAC7F,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAEhB,SAAS,CAAC,CAAC,EAAE,CAAC,EACV,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAClE,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAC/B,OAAO,CAAC,EAAE,GAAG,GACd,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KAC1B;CACF;AAoID,OAAO,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/gitsync-settings/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAqB/C,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/gitsync-settings/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAqB/C,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,iBAucF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/gitsync-settings/push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAmB/C,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/gitsync-settings/push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAmB/C,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,iBA2UF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from "../../../deps.js";
|
|
2
2
|
import { GlobalOptions } from "../../types.js";
|
|
3
3
|
import { SyncOptions } from "../../core/conf.js";
|
|
4
|
+
import { SpecificItemsConfig } from "../../core/specific_items.js";
|
|
4
5
|
import { SyncCodebase } from "../../utils/codebase.js";
|
|
5
6
|
import { PathAssigner } from "../../../windmill-utils-internal/src/path-utils/path-assigner.js";
|
|
6
7
|
type DynFSElement = {
|
|
@@ -28,7 +29,7 @@ export declare function readDirRecursiveWithIgnore(ignore: (path: string, isDire
|
|
|
28
29
|
isDirectory: boolean;
|
|
29
30
|
getContentText(): Promise<string>;
|
|
30
31
|
}>;
|
|
31
|
-
export declare function elementsToMap(els: DynFSElement, ignore: (path: string, isDirectory: boolean) => boolean, json: boolean, skips: Skips): Promise<{
|
|
32
|
+
export declare function elementsToMap(els: DynFSElement, ignore: (path: string, isDirectory: boolean) => boolean, json: boolean, skips: Skips, specificItems?: SpecificItemsConfig): Promise<{
|
|
32
33
|
[key: string]: string;
|
|
33
34
|
}>;
|
|
34
35
|
export interface Skips {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/sync/sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,OAAO,EAWR,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAEL,aAAa,EAKd,MAAM,gBAAgB,CAAC;AAcxB,OAAO,EACL,WAAW,
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/src/commands/sync/sync.ts"],"names":[],"mappings":"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"}
|
package/types/src/core/conf.d.ts
CHANGED
|
@@ -31,12 +31,38 @@ export interface SyncOptions {
|
|
|
31
31
|
codebases?: Codebase[];
|
|
32
32
|
parallel?: number;
|
|
33
33
|
jsonOutput?: boolean;
|
|
34
|
+
gitBranches?: {
|
|
35
|
+
commonSpecificItems?: {
|
|
36
|
+
variables?: string[];
|
|
37
|
+
resources?: string[];
|
|
38
|
+
};
|
|
39
|
+
} & {
|
|
40
|
+
[branchName: string]: SyncOptions & {
|
|
41
|
+
overrides?: Partial<SyncOptions>;
|
|
42
|
+
promotionOverrides?: Partial<SyncOptions>;
|
|
43
|
+
baseUrl?: string;
|
|
44
|
+
workspaceId?: string;
|
|
45
|
+
specificItems?: {
|
|
46
|
+
variables?: string[];
|
|
47
|
+
resources?: string[];
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
34
51
|
git_branches?: {
|
|
52
|
+
commonSpecificItems?: {
|
|
53
|
+
variables?: string[];
|
|
54
|
+
resources?: string[];
|
|
55
|
+
};
|
|
56
|
+
} & {
|
|
35
57
|
[branchName: string]: SyncOptions & {
|
|
36
58
|
overrides?: Partial<SyncOptions>;
|
|
37
59
|
promotionOverrides?: Partial<SyncOptions>;
|
|
38
60
|
baseUrl?: string;
|
|
39
61
|
workspaceId?: string;
|
|
62
|
+
specificItems?: {
|
|
63
|
+
variables?: string[];
|
|
64
|
+
resources?: string[];
|
|
65
|
+
};
|
|
40
66
|
};
|
|
41
67
|
};
|
|
42
68
|
promotion?: string;
|
|
@@ -56,6 +82,7 @@ export interface Codebase {
|
|
|
56
82
|
};
|
|
57
83
|
inject?: string[];
|
|
58
84
|
}
|
|
85
|
+
export declare function getWmillYamlPath(): string | null;
|
|
59
86
|
export declare function readConfigFile(): Promise<SyncOptions>;
|
|
60
87
|
export declare const DEFAULT_SYNC_OPTIONS: Readonly<Required<Pick<SyncOptions, 'defaultTs' | 'includes' | 'excludes' | 'codebases' | 'skipVariables' | 'skipResources' | 'skipResourceTypes' | 'skipSecrets' | 'includeSchedules' | 'includeTriggers' | 'skipScripts' | 'skipFlows' | 'skipApps' | 'skipFolders' | 'includeUsers' | 'includeGroups' | 'includeSettings' | 'includeKey'>>>;
|
|
61
88
|
export declare function mergeConfigWithConfigFile<T>(opts: T): Promise<T & SyncOptions>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conf.d.ts","sourceRoot":"","sources":["../../../src/src/core/conf.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"conf.d.ts","sourceRoot":"","sources":["../../../src/src/core/conf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SyncOptions } from "./conf.js";
|
|
2
|
+
export interface SpecificItemsConfig {
|
|
3
|
+
variables?: string[];
|
|
4
|
+
resources?: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Get the specific items configuration for the current git branch
|
|
8
|
+
* Merges commonSpecificItems with branch-specific specificItems
|
|
9
|
+
*/
|
|
10
|
+
export declare function getSpecificItemsForCurrentBranch(config: SyncOptions): SpecificItemsConfig | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a file path should be treated as branch-specific
|
|
13
|
+
*/
|
|
14
|
+
export declare function isSpecificItem(path: string, specificItems: SpecificItemsConfig | undefined): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Convert a base path to a branch-specific path
|
|
17
|
+
*/
|
|
18
|
+
export declare function toBranchSpecificPath(basePath: string, branchName: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Convert a branch-specific path back to a base path
|
|
21
|
+
*/
|
|
22
|
+
export declare function fromBranchSpecificPath(branchSpecificPath: string, branchName: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get the branch-specific path for the current branch if the item should be branch-specific
|
|
25
|
+
*/
|
|
26
|
+
export declare function getBranchSpecificPath(basePath: string, specificItems: SpecificItemsConfig | undefined): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a path is a branch-specific file for the current branch
|
|
29
|
+
*/
|
|
30
|
+
export declare function isCurrentBranchFile(path: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a path is a branch-specific file for ANY branch (not necessarily current)
|
|
33
|
+
* Used to identify and skip files from other branches during sync operations
|
|
34
|
+
*/
|
|
35
|
+
export declare function isBranchSpecificFile(path: string): boolean;
|
|
36
|
+
//# sourceMappingURL=specific_items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specific_items.d.ts","sourceRoot":"","sources":["../../../src/src/core/specific_items.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,GAAG,SAAS,CAsCrG;AASD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,GAAG,SAAS,GAAG,OAAO,CAepG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAmBjF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAoB7F;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,mBAAmB,GAAG,SAAS,GAC7C,MAAM,GAAG,SAAS,CAepB;AAKD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkBzD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG1D"}
|
package/types/src/main.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { pull as hubPull } from "./commands/hub/hub.js";
|
|
|
22
22
|
import { pull, push } from "./commands/sync/sync.js";
|
|
23
23
|
import { add as workspaceAdd } from "./commands/workspace/workspace.js";
|
|
24
24
|
export { flow, app, script, workspace, resource, resourceType, user, variable, hub, folder, schedule, trigger, sync, gitsyncSettings, instance, dev, hubPull, pull, push, workspaceAdd, };
|
|
25
|
-
export declare const VERSION = "1.
|
|
25
|
+
export declare const VERSION = "1.533.0";
|
|
26
26
|
declare const command: Command<{
|
|
27
27
|
workspace?: (import("../deps/jsr.io/@windmill-labs/cliffy-command/1.0.0-rc.5/mod.js").StringType & string) | undefined;
|
|
28
28
|
} & {
|