windmill-cli 1.737.0 → 1.739.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/main.js +92 -43
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -4242,9 +4242,11 @@ var init_bun_runtime = __esm(() => {
|
|
|
4242
4242
|
// src/core/log.ts
|
|
4243
4243
|
var exports_log = {};
|
|
4244
4244
|
__export(exports_log, {
|
|
4245
|
+
warnStderr: () => warnStderr,
|
|
4245
4246
|
warn: () => warn,
|
|
4246
4247
|
setup: () => setup,
|
|
4247
4248
|
setSilent: () => setSilent,
|
|
4249
|
+
infoStderr: () => infoStderr,
|
|
4248
4250
|
info: () => info,
|
|
4249
4251
|
error: () => error,
|
|
4250
4252
|
debug: () => debug
|
|
@@ -4264,11 +4266,21 @@ function info(msg) {
|
|
|
4264
4266
|
return;
|
|
4265
4267
|
console.log(`\x1B[34m${String(msg)}\x1B[39m`);
|
|
4266
4268
|
}
|
|
4269
|
+
function infoStderr(msg) {
|
|
4270
|
+
if (silentMode)
|
|
4271
|
+
return;
|
|
4272
|
+
console.error(`\x1B[34m${String(msg)}\x1B[39m`);
|
|
4273
|
+
}
|
|
4267
4274
|
function warn(msg) {
|
|
4268
4275
|
if (silentMode)
|
|
4269
4276
|
return;
|
|
4270
4277
|
console.log(`\x1B[33m${String(msg)}\x1B[39m`);
|
|
4271
4278
|
}
|
|
4279
|
+
function warnStderr(msg) {
|
|
4280
|
+
if (silentMode)
|
|
4281
|
+
return;
|
|
4282
|
+
console.error(`\x1B[33m${String(msg)}\x1B[39m`);
|
|
4283
|
+
}
|
|
4272
4284
|
function error(msg) {
|
|
4273
4285
|
console.error(`\x1B[31m${String(msg)}\x1B[39m`);
|
|
4274
4286
|
}
|
|
@@ -16388,7 +16400,7 @@ import * as http from "node:http";
|
|
|
16388
16400
|
async function loginInteractive(remote) {
|
|
16389
16401
|
let token;
|
|
16390
16402
|
if (!process.stdin.isTTY) {
|
|
16391
|
-
|
|
16403
|
+
infoStderr("Not a TTY, can't login interactively.");
|
|
16392
16404
|
return;
|
|
16393
16405
|
}
|
|
16394
16406
|
if (await Select.prompt({
|
|
@@ -16420,7 +16432,7 @@ async function browserLogin(baseUrl) {
|
|
|
16420
16432
|
const env = process.env["TOKEN_PORT"] != null ? parseInt(process.env["TOKEN_PORT"]) : undefined;
|
|
16421
16433
|
const port = await getPorts({ port: env });
|
|
16422
16434
|
if (port == undefined) {
|
|
16423
|
-
|
|
16435
|
+
infoStderr(colors.red.underline("failed to aquire port"));
|
|
16424
16436
|
return;
|
|
16425
16437
|
}
|
|
16426
16438
|
return new Promise((resolve4) => {
|
|
@@ -16435,12 +16447,12 @@ async function browserLogin(baseUrl) {
|
|
|
16435
16447
|
resolve4(token ?? undefined);
|
|
16436
16448
|
});
|
|
16437
16449
|
const url = `${baseUrl}user/cli?port=${port}`;
|
|
16438
|
-
|
|
16450
|
+
infoStderr(`Login by going to ${url}`);
|
|
16439
16451
|
try {
|
|
16440
16452
|
open_default(url).catch((error2) => {
|
|
16441
16453
|
console.error(`Failed to open browser, please navigate to ${url}, error: ${error2}`);
|
|
16442
16454
|
});
|
|
16443
|
-
|
|
16455
|
+
infoStderr("Opened browser for you");
|
|
16444
16456
|
} catch (error2) {
|
|
16445
16457
|
console.error(`Failed to open browser, please navigate to ${url}, error: ${error2}`);
|
|
16446
16458
|
}
|
|
@@ -16772,7 +16784,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16772
16784
|
PASSWORD: undefined,
|
|
16773
16785
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16774
16786
|
USERNAME: undefined,
|
|
16775
|
-
VERSION: "1.
|
|
16787
|
+
VERSION: "1.739.0",
|
|
16776
16788
|
WITH_CREDENTIALS: true,
|
|
16777
16789
|
interceptors: {
|
|
16778
16790
|
request: new Interceptors,
|
|
@@ -17416,6 +17428,7 @@ __export(exports_services_gen, {
|
|
|
17416
17428
|
getSharedUiVersion: () => getSharedUiVersion,
|
|
17417
17429
|
getSharedUi: () => getSharedUi,
|
|
17418
17430
|
getSettings: () => getSettings,
|
|
17431
|
+
getSessionWorkspaceStatus: () => getSessionWorkspaceStatus,
|
|
17419
17432
|
getSecondaryStorageNames: () => getSecondaryStorageNames,
|
|
17420
17433
|
getScriptLatestVersion: () => getScriptLatestVersion,
|
|
17421
17434
|
getScriptHistoryByPath: () => getScriptHistoryByPath,
|
|
@@ -18108,6 +18121,13 @@ var backendVersion = () => {
|
|
|
18108
18121
|
method: "GET",
|
|
18109
18122
|
url: "/workspaces/users"
|
|
18110
18123
|
});
|
|
18124
|
+
}, getSessionWorkspaceStatus = (data3) => {
|
|
18125
|
+
return request(OpenAPI, {
|
|
18126
|
+
method: "POST",
|
|
18127
|
+
url: "/workspaces/session_workspace_status",
|
|
18128
|
+
body: data3.requestBody,
|
|
18129
|
+
mediaType: "application/json"
|
|
18130
|
+
});
|
|
18111
18131
|
}, getWorkspaceAsSuperAdmin = (data3) => {
|
|
18112
18132
|
return request(OpenAPI, {
|
|
18113
18133
|
method: "GET",
|
|
@@ -25454,20 +25474,20 @@ async function requireLogin(opts) {
|
|
|
25454
25474
|
bodyStr = bodyStr.replace(/\s*[@(]\w+\.rs:\d+[:\d]*\)?/g, "");
|
|
25455
25475
|
bodyStr = bodyStr.replace(/^(Permission denied|Not authorized): /, "");
|
|
25456
25476
|
if (status === 403) {
|
|
25457
|
-
|
|
25477
|
+
infoStderr(colors.red(`Permission denied: the token is valid but lacks the required scope.${bodyStr ? `
|
|
25458
25478
|
${bodyStr}` : ""}`));
|
|
25459
25479
|
} else if (status === 401) {
|
|
25460
|
-
|
|
25480
|
+
infoStderr(colors.red(`Could not authenticate with the provided credentials. Please check your --token and --base-url and try again.${bodyStr ? `
|
|
25461
25481
|
${bodyStr}` : ""}`));
|
|
25462
25482
|
} else {
|
|
25463
|
-
|
|
25483
|
+
infoStderr(colors.red(`Request failed (${status ?? "unknown"}): ${bodyStr}`));
|
|
25464
25484
|
}
|
|
25465
25485
|
return process.exit(1);
|
|
25466
25486
|
}
|
|
25467
|
-
|
|
25487
|
+
infoStderr(colors.red("Could not authenticate with the provided credentials. Please check your --token and --base-url and try again."));
|
|
25468
25488
|
return process.exit(1);
|
|
25469
25489
|
}
|
|
25470
|
-
|
|
25490
|
+
infoStderr("! Could not reach API given existing credentials. Attempting to reauth...");
|
|
25471
25491
|
const newToken = await loginInteractive(workspace.remote);
|
|
25472
25492
|
if (!newToken) {
|
|
25473
25493
|
throw new Error("Unauthorized: Could not authenticate with the provided credentials");
|
|
@@ -25489,7 +25509,7 @@ var init_auth = __esm(async () => {
|
|
|
25489
25509
|
});
|
|
25490
25510
|
|
|
25491
25511
|
// src/core/constants.ts
|
|
25492
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
25512
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.739.0";
|
|
25493
25513
|
|
|
25494
25514
|
// src/utils/git.ts
|
|
25495
25515
|
var exports_git = {};
|
|
@@ -28594,17 +28614,17 @@ async function selectFromMultipleProfiles(profiles, baseUrl2, workspaceId, conte
|
|
|
28594
28614
|
if (lastUsedProfileName) {
|
|
28595
28615
|
const lastUsedProfile = profiles.find((p) => p.name === lastUsedProfileName);
|
|
28596
28616
|
if (lastUsedProfile) {
|
|
28597
|
-
|
|
28617
|
+
infoStderr(colors.green(`Using last used profile '${lastUsedProfile.name}' for ${context}`));
|
|
28598
28618
|
return lastUsedProfile;
|
|
28599
28619
|
}
|
|
28600
28620
|
}
|
|
28601
28621
|
if (!!!process.stdin.isTTY || !!!process.stdout.isTTY) {
|
|
28602
28622
|
const selectedProfile2 = profiles[0];
|
|
28603
|
-
|
|
28623
|
+
infoStderr(colors.yellow(`Multiple profiles found for ${context}. Using first available profile: '${selectedProfile2.name}'`));
|
|
28604
28624
|
await setLastUsedProfile("", baseUrl2, workspaceId, selectedProfile2.name, configDir);
|
|
28605
28625
|
return selectedProfile2;
|
|
28606
28626
|
}
|
|
28607
|
-
|
|
28627
|
+
infoStderr(colors.yellow(`
|
|
28608
28628
|
Multiple workspace profiles found for ${context}:`));
|
|
28609
28629
|
const selectedName = await Select.prompt({
|
|
28610
28630
|
message: "Select profile",
|
|
@@ -28619,16 +28639,16 @@ Multiple workspace profiles found for ${context}:`));
|
|
|
28619
28639
|
}
|
|
28620
28640
|
async function createWorkspaceProfileInteractively(normalizedBaseUrl, workspaceId, currentBranch, opts, context) {
|
|
28621
28641
|
if (!context.isForked) {
|
|
28622
|
-
|
|
28642
|
+
infoStderr(colors.yellow(`
|
|
28623
28643
|
No workspace profile found for branch '${context.rawBranch}'
|
|
28624
28644
|
` + `(${normalizedBaseUrl}, ${workspaceId})`));
|
|
28625
28645
|
} else {
|
|
28626
|
-
|
|
28646
|
+
infoStderr(colors.yellow(`
|
|
28627
28647
|
No workspace profile was found for this forked workspace
|
|
28628
28648
|
` + `(${normalizedBaseUrl}, ${workspaceId})`));
|
|
28629
28649
|
}
|
|
28630
28650
|
if (!!!process.stdin.isTTY || !!!process.stdout.isTTY) {
|
|
28631
|
-
|
|
28651
|
+
infoStderr("Not a TTY, cannot create profile interactively. Use 'wmill workspace add' first.");
|
|
28632
28652
|
return;
|
|
28633
28653
|
}
|
|
28634
28654
|
const shouldCreate = await Confirm.prompt({
|
|
@@ -28655,8 +28675,8 @@ No workspace profile was found for this forked workspace
|
|
|
28655
28675
|
};
|
|
28656
28676
|
await addWorkspace(newWorkspace, opts);
|
|
28657
28677
|
await setLastUsedProfile(currentBranch, normalizedBaseUrl, workspaceId, profileName, opts.configDir);
|
|
28658
|
-
|
|
28659
|
-
|
|
28678
|
+
infoStderr(colors.green(`✓ Created profile '${profileName}' for ${workspaceId} on ${normalizedBaseUrl}`));
|
|
28679
|
+
infoStderr(colors.green(`✓ Profile '${profileName}' is now active`));
|
|
28660
28680
|
return newWorkspace;
|
|
28661
28681
|
}
|
|
28662
28682
|
async function tryResolveWorkspace(opts) {
|
|
@@ -28681,11 +28701,11 @@ async function tryResolveWorkspace(opts) {
|
|
|
28681
28701
|
const matching = allProfs.filter((w) => w.remote === normalizedBaseUrl && w.workspaceId === workspaceId);
|
|
28682
28702
|
if (matching.length >= 1) {
|
|
28683
28703
|
const selected = matching.length === 1 ? matching[0] : await selectFromMultipleProfiles(matching, normalizedBaseUrl, workspaceId, `workspace '${opts.workspace}'`, opts.configDir);
|
|
28684
|
-
|
|
28704
|
+
infoStderr(colors.green(`Using workspace profile '${selected.name}' for workspace '${opts.workspace}' (${workspaceId} on ${normalizedBaseUrl})`));
|
|
28685
28705
|
opts.__secret_workspace = selected;
|
|
28686
28706
|
return { isError: false, value: selected };
|
|
28687
28707
|
}
|
|
28688
|
-
|
|
28708
|
+
infoStderr(`No profile found for workspace '${opts.workspace}' (${workspaceId} on ${normalizedBaseUrl})`);
|
|
28689
28709
|
const ws = await createWorkspaceProfileInteractively(normalizedBaseUrl, workspaceId, opts.workspace, opts, { rawBranch: opts.workspace, isForked: false });
|
|
28690
28710
|
if (ws) {
|
|
28691
28711
|
opts.__secret_workspace = ws;
|
|
@@ -28718,7 +28738,7 @@ async function tryResolveBranchWorkspace(opts, workspaceNameOverride) {
|
|
|
28718
28738
|
wsEntry = config.workspaces?.[workspaceNameOverride];
|
|
28719
28739
|
if (wsEntry) {
|
|
28720
28740
|
wsName = workspaceNameOverride;
|
|
28721
|
-
|
|
28741
|
+
infoStderr(`Using workspace override: ${workspaceNameOverride}`);
|
|
28722
28742
|
}
|
|
28723
28743
|
} else {
|
|
28724
28744
|
if (!isGitRepository()) {
|
|
@@ -28732,7 +28752,7 @@ async function tryResolveBranchWorkspace(opts, workspaceNameOverride) {
|
|
|
28732
28752
|
workspaceIdIfForked = getWorkspaceIdForWorkspaceForkFromBranchName(rawBranch);
|
|
28733
28753
|
const branchToLookup = originalBranchIfForked ?? rawBranch;
|
|
28734
28754
|
if (originalBranchIfForked) {
|
|
28735
|
-
|
|
28755
|
+
infoStderr(`Using original branch \`${originalBranchIfForked}\` for finding workspace from workspaces section in wmill.yaml`);
|
|
28736
28756
|
}
|
|
28737
28757
|
const match = findWorkspaceByGitBranch(config.workspaces, branchToLookup);
|
|
28738
28758
|
if (match) {
|
|
@@ -28744,7 +28764,7 @@ async function tryResolveBranchWorkspace(opts, workspaceNameOverride) {
|
|
|
28744
28764
|
}
|
|
28745
28765
|
if (!wsEntry.baseUrl) {
|
|
28746
28766
|
if (workspaceNameOverride) {
|
|
28747
|
-
|
|
28767
|
+
warnStderr(`⚠️ Workspace '${wsName}' has no baseUrl configured. Cannot resolve a profile.
|
|
28748
28768
|
` + ` Add baseUrl to workspace '${wsName}' in wmill.yaml, or use --base-url flag.`);
|
|
28749
28769
|
}
|
|
28750
28770
|
return;
|
|
@@ -28762,7 +28782,7 @@ async function tryResolveBranchWorkspace(opts, workspaceNameOverride) {
|
|
|
28762
28782
|
} else {
|
|
28763
28783
|
reason = `matched current git branch '${rawBranch}'`;
|
|
28764
28784
|
}
|
|
28765
|
-
|
|
28785
|
+
infoStderr(`Using workspace '${wsName}' (${reason}) → ${workspaceId} on ${baseUrl2}`);
|
|
28766
28786
|
let normalizedBaseUrl;
|
|
28767
28787
|
try {
|
|
28768
28788
|
normalizedBaseUrl = new URL(baseUrl2).toString();
|
|
@@ -28778,24 +28798,24 @@ async function tryResolveBranchWorkspace(opts, workspaceNameOverride) {
|
|
|
28778
28798
|
let selectedProfile;
|
|
28779
28799
|
if (matchingProfiles.length === 1) {
|
|
28780
28800
|
selectedProfile = matchingProfiles[0];
|
|
28781
|
-
|
|
28801
|
+
infoStderr(colors.green(`Using workspace profile '${selectedProfile.name}' for workspace '${wsName}' with workspace id \`${workspaceId}\``));
|
|
28782
28802
|
} else {
|
|
28783
28803
|
const lastUsedName = await getLastUsedProfile(wsName, normalizedBaseUrl, workspaceId, opts.configDir);
|
|
28784
28804
|
if (lastUsedName) {
|
|
28785
28805
|
const lastUsedProfile = matchingProfiles.find((p) => p.name === lastUsedName);
|
|
28786
28806
|
if (lastUsedProfile) {
|
|
28787
|
-
|
|
28807
|
+
infoStderr(colors.green(`Using workspace profile '${lastUsedProfile.name}' for workspace '${wsName}' (last used)`));
|
|
28788
28808
|
return lastUsedProfile;
|
|
28789
28809
|
}
|
|
28790
28810
|
}
|
|
28791
28811
|
selectedProfile = await selectFromMultipleProfiles(matchingProfiles, normalizedBaseUrl, workspaceId, `workspace '${wsName}'`, opts.configDir);
|
|
28792
28812
|
await setLastUsedProfile(wsName, normalizedBaseUrl, workspaceId, selectedProfile.name, opts.configDir);
|
|
28793
|
-
|
|
28813
|
+
infoStderr(colors.green(`Using workspace profile '${selectedProfile.name}' for workspace '${wsName}'`));
|
|
28794
28814
|
}
|
|
28795
28815
|
if (workspaceIdIfForked) {
|
|
28796
28816
|
selectedProfile.name = `${selectedProfile.name}/${workspaceIdIfForked}`;
|
|
28797
28817
|
selectedProfile.workspaceId = workspaceIdIfForked;
|
|
28798
|
-
|
|
28818
|
+
infoStderr(`Using fork workspace \`${workspaceIdIfForked}\` (parent: \`${workspaceId}\`) from branch \`${rawBranch}\``);
|
|
28799
28819
|
}
|
|
28800
28820
|
return selectedProfile;
|
|
28801
28821
|
}
|
|
@@ -28809,7 +28829,7 @@ async function resolveWorkspace(opts, workspaceNameOverride) {
|
|
|
28809
28829
|
try {
|
|
28810
28830
|
normalizedBaseUrl = new URL(opts.baseUrl).toString();
|
|
28811
28831
|
} catch (error2) {
|
|
28812
|
-
|
|
28832
|
+
infoStderr(colors.red(`Invalid base URL: ${opts.baseUrl}`));
|
|
28813
28833
|
return process.exit(-1);
|
|
28814
28834
|
}
|
|
28815
28835
|
if (opts.workspace) {
|
|
@@ -28824,7 +28844,7 @@ async function resolveWorkspace(opts, workspaceNameOverride) {
|
|
|
28824
28844
|
}
|
|
28825
28845
|
if (existingWorkspace) {
|
|
28826
28846
|
if (existingWorkspace.remote !== normalizedBaseUrl) {
|
|
28827
|
-
|
|
28847
|
+
infoStderr(colors.red(`Base URL mismatch: --base-url is ${normalizedBaseUrl} but workspace profile "${opts.workspace}" uses ${existingWorkspace.remote}`));
|
|
28828
28848
|
return process.exit(-1);
|
|
28829
28849
|
}
|
|
28830
28850
|
return {
|
|
@@ -28840,7 +28860,7 @@ async function resolveWorkspace(opts, workspaceNameOverride) {
|
|
|
28840
28860
|
token: opts.token
|
|
28841
28861
|
};
|
|
28842
28862
|
} else {
|
|
28843
|
-
|
|
28863
|
+
infoStderr(colors.red("If you specify a base URL with --base-url, you must also specify a workspace (--workspace) and token (--token)."));
|
|
28844
28864
|
return process.exit(-1);
|
|
28845
28865
|
}
|
|
28846
28866
|
}
|
|
@@ -28851,7 +28871,7 @@ async function resolveWorkspace(opts, workspaceNameOverride) {
|
|
|
28851
28871
|
if (workspaceNameOverride || opts.workspace || !branch || !branch.startsWith(WM_FORK_PREFIX)) {
|
|
28852
28872
|
return workspace;
|
|
28853
28873
|
} else {
|
|
28854
|
-
|
|
28874
|
+
infoStderr(`Found an active workspace \`${workspace.name}\` but the branch name indicates this is a forked workspace. Ignoring active workspace and trying to resolve the correct workspace from the branch name \`${branch}\`. Use --workspace to override.`);
|
|
28855
28875
|
}
|
|
28856
28876
|
} else if (opts.workspace) {
|
|
28857
28877
|
const profiles = await allWorkspaces(opts.configDir);
|
|
@@ -28861,9 +28881,9 @@ async function resolveWorkspace(opts, workspaceNameOverride) {
|
|
|
28861
28881
|
if (suggestions.length > 0) {
|
|
28862
28882
|
msg += ` Did you mean: ${suggestions.map((s) => `"${s.name}"`).join(", ")}?`;
|
|
28863
28883
|
}
|
|
28864
|
-
|
|
28884
|
+
infoStderr(colors.red.bold(msg));
|
|
28865
28885
|
if (profiles.length > 0) {
|
|
28866
|
-
|
|
28886
|
+
infoStderr(`
|
|
28867
28887
|
Available workspaces:`);
|
|
28868
28888
|
new Table2().header(["name", "remote", "workspace id"]).padding(2).border(true).body(profiles.map((w) => [w.name, w.remote, w.workspaceId])).render();
|
|
28869
28889
|
}
|
|
@@ -28894,10 +28914,10 @@ Available workspaces:`);
|
|
|
28894
28914
|
`);
|
|
28895
28915
|
if (wsNames.length === 1) {
|
|
28896
28916
|
pickedWsName = wsNames[0];
|
|
28897
|
-
|
|
28917
|
+
infoStderr(`Auto-selected workspace '${pickedWsName}' (only workspace in config).
|
|
28898
28918
|
Use --workspace to override or 'wmill workspace bind' to add more workspaces.`);
|
|
28899
28919
|
} else if (process.stdin.isTTY) {
|
|
28900
|
-
|
|
28920
|
+
infoStderr(`Multiple workspaces configured but none matched the current context.
|
|
28901
28921
|
Configured workspaces:
|
|
28902
28922
|
${wsListStr}
|
|
28903
28923
|
Use --workspace to skip this prompt.`);
|
|
@@ -28935,7 +28955,7 @@ Use --workspace to select one.`));
|
|
|
28935
28955
|
try {
|
|
28936
28956
|
normalizedBaseUrl = new URL(envBaseUrl).toString();
|
|
28937
28957
|
} catch {
|
|
28938
|
-
|
|
28958
|
+
infoStderr(colors.red(`Invalid BASE_INTERNAL_URL: ${envBaseUrl}`));
|
|
28939
28959
|
return process.exit(-1);
|
|
28940
28960
|
}
|
|
28941
28961
|
debug(`Using workspace from environment variables: ${envWorkspace} on ${normalizedBaseUrl}`);
|
|
@@ -28948,7 +28968,7 @@ Use --workspace to select one.`));
|
|
|
28948
28968
|
opts.__secret_workspace = ws;
|
|
28949
28969
|
return ws;
|
|
28950
28970
|
}
|
|
28951
|
-
|
|
28971
|
+
infoStderr(colors.red.bold("No workspace given and no default set. Run 'wmill workspace add' to configure one."));
|
|
28952
28972
|
return process.exit(-1);
|
|
28953
28973
|
}
|
|
28954
28974
|
async function fetchVersion(baseUrl2) {
|
|
@@ -28988,7 +29008,7 @@ async function tryResolveVersion(opts) {
|
|
|
28988
29008
|
}
|
|
28989
29009
|
function validatePath(path4) {
|
|
28990
29010
|
if (!(path4.startsWith("g") || path4.startsWith("u") || path4.startsWith("f"))) {
|
|
28991
|
-
|
|
29011
|
+
infoStderr(colors.red("Given remote path looks invalid. Remote paths are typically of the form <u|g|f>/<username|group|folder>/..."));
|
|
28992
29012
|
return false;
|
|
28993
29013
|
}
|
|
28994
29014
|
return true;
|
|
@@ -74091,7 +74111,18 @@ async function get6(opts, path19) {
|
|
|
74091
74111
|
console.log(colors.bold("Account:") + " " + (v.account ?? "-"));
|
|
74092
74112
|
}
|
|
74093
74113
|
}
|
|
74094
|
-
|
|
74114
|
+
function looksLikeWorkspaceCiphertext(value) {
|
|
74115
|
+
if (value.startsWith("$vault:") || value.startsWith("$aws_sm:") || value.startsWith("$azure_kv:")) {
|
|
74116
|
+
return true;
|
|
74117
|
+
}
|
|
74118
|
+
if (value.length === 0 || value.length % 4 !== 0)
|
|
74119
|
+
return false;
|
|
74120
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(value))
|
|
74121
|
+
return false;
|
|
74122
|
+
const decodedLen = Buffer.from(value, "base64").length;
|
|
74123
|
+
return decodedLen > 0 && decodedLen % 16 === 0;
|
|
74124
|
+
}
|
|
74125
|
+
async function pushVariable(workspace, remotePath, variable, localVariable, plainSecrets, wsSpecific, allowSecretDowngrade = false) {
|
|
74095
74126
|
remotePath = removeType(remotePath, "variable");
|
|
74096
74127
|
debug(`Processing local variable ${remotePath}`);
|
|
74097
74128
|
try {
|
|
@@ -74111,13 +74142,21 @@ async function pushVariable(workspace, remotePath, variable, localVariable, plai
|
|
|
74111
74142
|
return;
|
|
74112
74143
|
}
|
|
74113
74144
|
debug(`Variable ${remotePath} is not up-to-date, updating`);
|
|
74145
|
+
let nextIsSecret = undefined;
|
|
74146
|
+
if (localVariable.is_secret !== variable.is_secret) {
|
|
74147
|
+
if (localVariable.is_secret) {
|
|
74148
|
+
nextIsSecret = true;
|
|
74149
|
+
} else if (allowSecretDowngrade) {
|
|
74150
|
+
nextIsSecret = false;
|
|
74151
|
+
}
|
|
74152
|
+
}
|
|
74114
74153
|
await updateVariable({
|
|
74115
74154
|
workspace,
|
|
74116
74155
|
path: remotePath.replaceAll(SEP16, "/"),
|
|
74117
74156
|
alreadyEncrypted: !plainSecrets,
|
|
74118
74157
|
requestBody: {
|
|
74119
74158
|
...localVariable,
|
|
74120
|
-
is_secret:
|
|
74159
|
+
is_secret: nextIsSecret,
|
|
74121
74160
|
...wsSpecific !== undefined ? { ws_specific: wsSpecific } : {}
|
|
74122
74161
|
}
|
|
74123
74162
|
});
|
|
@@ -74145,7 +74184,17 @@ async function push7(opts, filePath, remotePath) {
|
|
|
74145
74184
|
throw new Error("file path must refer to a file.");
|
|
74146
74185
|
}
|
|
74147
74186
|
info(colors.bold.yellow("Pushing variable..."));
|
|
74148
|
-
|
|
74187
|
+
const local = parseFromFile(filePath);
|
|
74188
|
+
let plainSecrets = opts.plainSecrets ?? false;
|
|
74189
|
+
if (opts.plainSecrets === undefined && local.is_secret) {
|
|
74190
|
+
if (!looksLikeWorkspaceCiphertext(local.value)) {
|
|
74191
|
+
info(colors.yellow("Secret value is not in encrypted form; pushing as plaintext to be encrypted server-side (pass --plain-secrets to silence)."));
|
|
74192
|
+
plainSecrets = true;
|
|
74193
|
+
} else {
|
|
74194
|
+
warn("Secret value looks already-encrypted; pushing it as-is. If it is a plaintext secret, re-run with --plain-secrets so it gets encrypted.");
|
|
74195
|
+
}
|
|
74196
|
+
}
|
|
74197
|
+
await pushVariable(workspace.workspaceId, remotePath, undefined, local, plainSecrets, undefined, true);
|
|
74149
74198
|
info(colors.bold.underline.green(`Variable ${remotePath} pushed`));
|
|
74150
74199
|
}
|
|
74151
74200
|
async function add2(opts, value, remotePath) {
|