windmill-cli 1.696.0 → 1.696.2

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.
Files changed (2) hide show
  1. package/esm/main.js +85 -11
  2. package/package.json +1 -1
package/esm/main.js CHANGED
@@ -16440,6 +16440,48 @@ var init_login = __esm(async () => {
16440
16440
  ]);
16441
16441
  });
16442
16442
 
16443
+ // src/utils/http_guards.ts
16444
+ async function detectAuthGatewayChallenge(response, url) {
16445
+ const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
16446
+ const cfMitigated = response.headers.get("cf-mitigated") ?? undefined;
16447
+ const looksHtml = contentType.includes("text/html");
16448
+ if (!looksHtml && cfMitigated !== "challenge")
16449
+ return;
16450
+ let snippet = "";
16451
+ try {
16452
+ snippet = (await response.clone().text()).slice(0, 256);
16453
+ } catch {}
16454
+ const isChallenge = cfMitigated === "challenge" || ACCESS_TITLE.test(snippet) || looksHtml && HTML_DOCTYPE.test(snippet);
16455
+ if (!isChallenge)
16456
+ return;
16457
+ throw new AuthGatewayChallengeError(url || response.url || "(unknown)", response.headers.get("cf-ray") ?? undefined, cfMitigated, response.status, snippet);
16458
+ }
16459
+ var ACCESS_TITLE, HTML_DOCTYPE, AuthGatewayChallengeError;
16460
+ var init_http_guards = __esm(() => {
16461
+ ACCESS_TITLE = /<title>\s*Sign in[^<]*Cloudflare Access\s*<\/title>/i;
16462
+ HTML_DOCTYPE = /^\s*<(!doctype|html)/i;
16463
+ AuthGatewayChallengeError = class AuthGatewayChallengeError extends Error {
16464
+ url;
16465
+ cfRay;
16466
+ cfMitigated;
16467
+ status;
16468
+ bodySnippet;
16469
+ name = "AuthGatewayChallengeError";
16470
+ constructor(url, cfRay, cfMitigated, status, bodySnippet) {
16471
+ const cfPart = [
16472
+ cfRay ? `cf-ray=${cfRay}` : null,
16473
+ cfMitigated ? `cf-mitigated=${cfMitigated}` : null
16474
+ ].filter(Boolean).join(", ");
16475
+ super(`Got an HTML response from ${url} (status ${status}${cfPart ? `, ${cfPart}` : ""}). ` + `The request was intercepted by an upstream auth gateway (likely Cloudflare Access) ` + `before reaching Windmill. Verify the runner is on the right network or pass service-token headers via the HEADERS env var ` + `(e.g. HEADERS="CF-Access-Client-Id: <id>, CF-Access-Client-Secret: <secret>"). ` + `Body starts with: ${JSON.stringify(bodySnippet.slice(0, 120))}`);
16476
+ this.url = url;
16477
+ this.cfRay = cfRay;
16478
+ this.cfMitigated = cfMitigated;
16479
+ this.status = status;
16480
+ this.bodySnippet = bodySnippet;
16481
+ }
16482
+ };
16483
+ });
16484
+
16443
16485
  // windmill-utils-internal/src/config/config.ts
16444
16486
  import { stat as stat2, mkdir } from "node:fs/promises";
16445
16487
  function getEnv2(key) {
@@ -16710,7 +16752,7 @@ var init_OpenAPI = __esm(() => {
16710
16752
  PASSWORD: undefined,
16711
16753
  TOKEN: getEnv3("WM_TOKEN"),
16712
16754
  USERNAME: undefined,
16713
- VERSION: "1.696.0",
16755
+ VERSION: "1.696.2",
16714
16756
  WITH_CREDENTIALS: true,
16715
16757
  interceptors: {
16716
16758
  request: new Interceptors,
@@ -28116,7 +28158,12 @@ async function fetchVersion(baseUrl2) {
28116
28158
  requestHeaders.set(key, value);
28117
28159
  }
28118
28160
  }
28119
- const response = await fetch(new URL(new URL(baseUrl2).origin + "/api/version"), { headers: requestHeaders, method: "GET" });
28161
+ const versionUrl = new URL(new URL(baseUrl2).origin + "/api/version");
28162
+ const response = await fetch(versionUrl, {
28163
+ headers: requestHeaders,
28164
+ method: "GET"
28165
+ });
28166
+ await detectAuthGatewayChallenge(response, versionUrl.toString());
28120
28167
  if (!response.ok) {
28121
28168
  await response.text();
28122
28169
  throw new Error(`Failed to fetch version: ${response.status} ${response.statusText}`);
@@ -28149,6 +28196,7 @@ var init_context = __esm(async () => {
28149
28196
  init_colors2();
28150
28197
  init_log();
28151
28198
  init_mod6();
28199
+ init_http_guards();
28152
28200
  init_git();
28153
28201
  init_levenshtein_distance();
28154
28202
  await __promiseAll([
@@ -33636,23 +33684,23 @@ async function logQueueStatus(workspace, jobId, label = "Job ") {
33636
33684
  try {
33637
33685
  const job = await getJob({ workspace, id: jobId });
33638
33686
  if (!job)
33639
- return;
33687
+ return false;
33640
33688
  if (job.running === true) {
33641
33689
  info(colors.gray(`${label}${jobId}: running, waiting for completion...`));
33642
- return;
33690
+ return true;
33643
33691
  }
33644
33692
  if (typeof job.running !== "boolean") {
33645
- return;
33693
+ return false;
33646
33694
  }
33647
33695
  const scheduledFor = job.scheduled_for;
33648
33696
  if (!scheduledFor) {
33649
33697
  info(colors.gray(`${label}${jobId}: queued, waiting for executor...`));
33650
- return;
33698
+ return true;
33651
33699
  }
33652
33700
  const scheduledForMs = new Date(scheduledFor).getTime();
33653
33701
  if (!Number.isFinite(scheduledForMs)) {
33654
33702
  info(colors.gray(`${label}${jobId}: queued, waiting for executor...`));
33655
- return;
33703
+ return true;
33656
33704
  }
33657
33705
  try {
33658
33706
  const pos = await getQueuePosition({
@@ -33665,10 +33713,14 @@ async function logQueueStatus(workspace, jobId, label = "Job ") {
33665
33713
  } else {
33666
33714
  info(colors.gray(`${label}${jobId}: queued, waiting for executor...`));
33667
33715
  }
33716
+ return true;
33668
33717
  } catch {
33669
33718
  info(colors.gray(`${label}${jobId}: queued, waiting for executor...`));
33719
+ return true;
33670
33720
  }
33671
- } catch {}
33721
+ } catch {
33722
+ return false;
33723
+ }
33672
33724
  }
33673
33725
  async function pollJobWithQueueLogging(workspace, jobId, options) {
33674
33726
  const fastPollIntervalMs = options?.fastPollIntervalMs ?? DEFAULT_FAST_POLL_INTERVAL_MS;
@@ -33677,6 +33729,7 @@ async function pollJobWithQueueLogging(workspace, jobId, options) {
33677
33729
  const label = options?.label ? `[${options.label}] ` : "Job ";
33678
33730
  const startedAt = Date.now();
33679
33731
  let lastQueueLogAt = Date.now();
33732
+ let lastHeartbeatAt = Date.now();
33680
33733
  let consecutiveErrors = 0;
33681
33734
  while (true) {
33682
33735
  try {
@@ -33692,19 +33745,26 @@ async function pollJobWithQueueLogging(workspace, jobId, options) {
33692
33745
  } catch (err) {
33693
33746
  consecutiveErrors++;
33694
33747
  warn(colors.yellow(`${label}${jobId}: error checking job status (${consecutiveErrors}/${MAX_CONSECUTIVE_POLL_ERRORS}): ${err?.message ?? err}`));
33748
+ lastHeartbeatAt = Date.now();
33695
33749
  if (consecutiveErrors >= MAX_CONSECUTIVE_POLL_ERRORS) {
33696
33750
  throw new Error(`Giving up polling job ${jobId} after ${MAX_CONSECUTIVE_POLL_ERRORS} consecutive errors. Last error: ${err?.message ?? err}`);
33697
33751
  }
33698
33752
  }
33699
33753
  if (Date.now() - lastQueueLogAt >= QUEUE_LOG_INTERVAL_MS) {
33700
33754
  lastQueueLogAt = Date.now();
33701
- await logQueueStatus(workspace, jobId, label);
33755
+ const logged = await logQueueStatus(workspace, jobId, label);
33756
+ if (logged)
33757
+ lastHeartbeatAt = Date.now();
33758
+ }
33759
+ if (Date.now() - lastHeartbeatAt >= HEARTBEAT_INTERVAL_MS) {
33760
+ lastHeartbeatAt = Date.now();
33761
+ info(colors.gray(`${label}${jobId}: still polling, queue status unavailable...`));
33702
33762
  }
33703
33763
  const delayMs = Date.now() - startedAt < fastPollDurationMs ? fastPollIntervalMs : slowPollIntervalMs;
33704
33764
  await new Promise((resolve6) => setTimeout(resolve6, delayMs));
33705
33765
  }
33706
33766
  }
33707
- var DEFAULT_FAST_POLL_INTERVAL_MS = 100, DEFAULT_FAST_POLL_DURATION_MS = 2000, DEFAULT_SLOW_POLL_INTERVAL_MS = 2000, QUEUE_LOG_INTERVAL_MS = 5000, MAX_CONSECUTIVE_POLL_ERRORS = 10;
33767
+ var DEFAULT_FAST_POLL_INTERVAL_MS = 100, DEFAULT_FAST_POLL_DURATION_MS = 2000, DEFAULT_SLOW_POLL_INTERVAL_MS = 2000, QUEUE_LOG_INTERVAL_MS = 5000, HEARTBEAT_INTERVAL_MS = 60000, MAX_CONSECUTIVE_POLL_ERRORS = 10;
33708
33768
  var init_job_polling = __esm(() => {
33709
33769
  init_services_gen();
33710
33770
  init_log();
@@ -46847,6 +46907,7 @@ async function downloadZip(workspace, plainSecrets, skipVariables, skipResources
46847
46907
  const baseUrl2 = workspace.remote + "api/w/" + workspace.workspaceId + "/workspaces/tarball?";
46848
46908
  const zipUrl = baseUrl2 + "archive_type=zip" + baseParams;
46849
46909
  const zipResponse = await fetch(zipUrl, { headers: requestHeaders, method: "GET" });
46910
+ await detectAuthGatewayChallenge(zipResponse, zipUrl);
46850
46911
  if (zipResponse.ok) {
46851
46912
  debug("Downloaded zip archive successfully");
46852
46913
  const blob = await zipResponse.blob();
@@ -46857,6 +46918,7 @@ async function downloadZip(workspace, plainSecrets, skipVariables, skipResources
46857
46918
  debug("Zip archive not supported by backend, falling back to tar");
46858
46919
  const tarUrl = baseUrl2 + "archive_type=tar" + baseParams;
46859
46920
  const tarResponse = await fetch(tarUrl, { headers: requestHeaders, method: "GET" });
46921
+ await detectAuthGatewayChallenge(tarResponse, tarUrl);
46860
46922
  if (tarResponse.ok) {
46861
46923
  debug("Downloaded tar archive successfully");
46862
46924
  return await parseTarResponse(tarResponse);
@@ -46885,6 +46947,7 @@ var init_pull = __esm(async () => {
46885
46947
  init_mod3();
46886
46948
  init_log();
46887
46949
  init_tar_stream();
46950
+ init_http_guards();
46888
46951
  await init_utils();
46889
46952
  import_jszip = __toESM(require_lib3(), 1);
46890
46953
  command3 = new Command().description("Pull all definitions in the current workspace from the API and write them to disk.").arguments("<dir:string>").action(stub);
@@ -64542,6 +64605,7 @@ async function updateFlow2(workspace, flow_value, remotePath, rawWorkspaceDepend
64542
64605
  },
64543
64606
  body: JSON.stringify(body)
64544
64607
  });
64608
+ await detectAuthGatewayChallenge(queueResponse, `${workspace.remote}api/w/${workspace.workspaceId}/jobs/run/flow_dependencies_async`);
64545
64609
  if (!queueResponse.ok) {
64546
64610
  let bodyText = "";
64547
64611
  try {
@@ -64569,6 +64633,7 @@ var init_flow_metadata = __esm(async () => {
64569
64633
  init_log();
64570
64634
  init_extractor();
64571
64635
  init_path_assigner();
64636
+ init_http_guards();
64572
64637
  init_script_common();
64573
64638
  init_job_polling();
64574
64639
  await __promiseAll([
@@ -68151,6 +68216,7 @@ async function fetchScriptLock(workspace, scriptContent, language, remotePath, r
68151
68216
  temp_script_refs: tempScriptRefs && Object.keys(tempScriptRefs).length > 0 ? tempScriptRefs : null
68152
68217
  })
68153
68218
  });
68219
+ await detectAuthGatewayChallenge(queueResponse, `${workspace.remote}api/w/${workspace.workspaceId}/jobs/run/dependencies_async`);
68154
68220
  if (!queueResponse.ok) {
68155
68221
  let bodyText = "";
68156
68222
  try {
@@ -68635,6 +68701,7 @@ var init_metadata = __esm(async () => {
68635
68701
  init_script_bootstrap();
68636
68702
  init_script_common();
68637
68703
  init_script_common();
68704
+ init_http_guards();
68638
68705
  init_parse_schema();
68639
68706
  init_job_polling();
68640
68707
  await __promiseAll([
@@ -69336,6 +69403,7 @@ async function generateInlineScriptLock(workspace, content, language, scriptPath
69336
69403
  ...tempScriptRefs && Object.keys(tempScriptRefs).length > 0 ? { temp_script_refs: tempScriptRefs } : {}
69337
69404
  })
69338
69405
  });
69406
+ await detectAuthGatewayChallenge(queueResponse, `${workspace.remote}api/w/${workspace.workspaceId}/jobs/run/dependencies_async`);
69339
69407
  if (!queueResponse.ok) {
69340
69408
  const text = await queueResponse.text();
69341
69409
  throw new Error(`Dependency generation failed: ${queueResponse.status} ${queueResponse.statusText}
@@ -69516,6 +69584,7 @@ var init_app_metadata = __esm(async () => {
69516
69584
  init_colors2();
69517
69585
  init_log();
69518
69586
  init_script_common();
69587
+ init_http_guards();
69519
69588
  init_path_assigner();
69520
69589
  init_job_polling();
69521
69590
  await __promiseAll([
@@ -78615,6 +78684,7 @@ var dev_default2 = command25;
78615
78684
 
78616
78685
  // src/main.ts
78617
78686
  init_gen();
78687
+ init_http_guards();
78618
78688
  await __promiseAll([
78619
78689
  init_utils(),
78620
78690
  init_conf()
@@ -89017,7 +89087,7 @@ var config_default = command35;
89017
89087
 
89018
89088
  // src/main.ts
89019
89089
  await init_context();
89020
- var VERSION = "1.696.0";
89090
+ var VERSION = "1.696.2";
89021
89091
  async function checkVersionSafe(cmd) {
89022
89092
  const mainCommand = cmd.getMainCommand();
89023
89093
  const upgradeCommand = mainCommand.getCommand("upgrade");
@@ -89099,6 +89169,10 @@ async function main2() {
89099
89169
  if (extraHeaders) {
89100
89170
  OpenAPI.HEADERS = extraHeaders;
89101
89171
  }
89172
+ OpenAPI.interceptors.response.use(async (response) => {
89173
+ await detectAuthGatewayChallenge(response);
89174
+ return response;
89175
+ });
89102
89176
  await command36.parse(args);
89103
89177
  } catch (e) {
89104
89178
  if (e && typeof e === "object" && "name" in e && e.name === "ApiError") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windmill-cli",
3
- "version": "1.696.0",
3
+ "version": "1.696.2",
4
4
  "description": "CLI for Windmill",
5
5
  "license": "Apache 2.0",
6
6
  "type": "module",