@rudderhq/cli 0.3.6-canary.6 → 0.3.6-canary.8
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/dist/index.js +123 -31
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13788,6 +13788,7 @@ function createByteProgress(label, options = {}) {
|
|
|
13788
13788
|
init_version();
|
|
13789
13789
|
var DEFAULT_DESKTOP_RELEASE_REPO = "Undertone0809/rudder";
|
|
13790
13790
|
var DESKTOP_UPDATE_QUIT_ARG = "--rudder-update-quit";
|
|
13791
|
+
var DESKTOP_UPDATE_FORCE_ARG = "--rudder-update-force";
|
|
13791
13792
|
var STABLE_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
|
|
13792
13793
|
var CANARY_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9]+$/;
|
|
13793
13794
|
var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest";
|
|
@@ -13871,7 +13872,7 @@ function createDesktopProgressFactory() {
|
|
|
13871
13872
|
async function waitForDesktopApplySignal() {
|
|
13872
13873
|
process.stdin.setEncoding("utf8");
|
|
13873
13874
|
process.stdin.resume();
|
|
13874
|
-
await new Promise((resolve, reject) => {
|
|
13875
|
+
return await new Promise((resolve, reject) => {
|
|
13875
13876
|
let buffer = "";
|
|
13876
13877
|
const cleanup = () => {
|
|
13877
13878
|
process.stdin.off("data", onData);
|
|
@@ -13882,9 +13883,15 @@ async function waitForDesktopApplySignal() {
|
|
|
13882
13883
|
buffer += chunk;
|
|
13883
13884
|
const lines = buffer.split(/\r?\n/);
|
|
13884
13885
|
buffer = lines.pop() ?? "";
|
|
13885
|
-
|
|
13886
|
+
const commands = lines.map((line) => line.trim());
|
|
13887
|
+
if (commands.includes("force-apply")) {
|
|
13886
13888
|
cleanup();
|
|
13887
|
-
resolve();
|
|
13889
|
+
resolve({ force: true });
|
|
13890
|
+
return;
|
|
13891
|
+
}
|
|
13892
|
+
if (commands.includes("apply")) {
|
|
13893
|
+
cleanup();
|
|
13894
|
+
resolve({ force: false });
|
|
13888
13895
|
}
|
|
13889
13896
|
};
|
|
13890
13897
|
const onEnd = () => {
|
|
@@ -14597,14 +14604,6 @@ function isInstalledDesktopCurrent(metadata, releaseTag, assetName, assetChecksu
|
|
|
14597
14604
|
metadata && metadata.releaseTag === releaseTag && metadata.assetName === assetName && metadata.assetChecksum === assetChecksum
|
|
14598
14605
|
);
|
|
14599
14606
|
}
|
|
14600
|
-
function buildForceQuitCommand(target) {
|
|
14601
|
-
if (target.platform === "windows") return { command: "taskkill.exe", args: ["/IM", `${DESKTOP_APP_NAME}.exe`, "/T", "/F"] };
|
|
14602
|
-
return { command: "pkill", args: ["-x", DESKTOP_APP_NAME] };
|
|
14603
|
-
}
|
|
14604
|
-
function forceQuitDesktopProcesses(target) {
|
|
14605
|
-
const command = buildForceQuitCommand(target);
|
|
14606
|
-
spawnSync3(command.command, command.args, { stdio: "ignore" });
|
|
14607
|
-
}
|
|
14608
14607
|
function forceQuitDesktopProcess(pid, target) {
|
|
14609
14608
|
if (target.platform === "windows") {
|
|
14610
14609
|
spawnSync3("taskkill.exe", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
@@ -14615,6 +14614,36 @@ function forceQuitDesktopProcess(pid, target) {
|
|
|
14615
14614
|
} catch {
|
|
14616
14615
|
}
|
|
14617
14616
|
}
|
|
14617
|
+
function quotePowerShellString(value) {
|
|
14618
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
14619
|
+
}
|
|
14620
|
+
function findDesktopExecutablePids(executablePath, target) {
|
|
14621
|
+
if (target.platform === "windows") {
|
|
14622
|
+
const result2 = spawnSync3("powershell.exe", [
|
|
14623
|
+
"-NoProfile",
|
|
14624
|
+
"-Command",
|
|
14625
|
+
`Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq ${quotePowerShellString(executablePath)} } | Select-Object -ExpandProperty ProcessId`
|
|
14626
|
+
], {
|
|
14627
|
+
encoding: "utf8",
|
|
14628
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
14629
|
+
});
|
|
14630
|
+
if (result2.status !== 0) return [];
|
|
14631
|
+
return result2.stdout.split(/\r?\n/).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid);
|
|
14632
|
+
}
|
|
14633
|
+
const result = spawnSync3("ps", ["-eo", "pid=,args="], {
|
|
14634
|
+
encoding: "utf8",
|
|
14635
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
14636
|
+
});
|
|
14637
|
+
if (result.status !== 0) return [];
|
|
14638
|
+
return result.stdout.split(/\r?\n/).flatMap((line) => {
|
|
14639
|
+
const match = line.match(/^\s*(\d+)\s+(.+)$/);
|
|
14640
|
+
if (!match) return [];
|
|
14641
|
+
const pid = Number.parseInt(match[1], 10);
|
|
14642
|
+
const commandLine = match[2];
|
|
14643
|
+
const matchesExecutable = commandLine === executablePath || commandLine.startsWith(`${executablePath} `);
|
|
14644
|
+
return matchesExecutable && pid !== process.pid ? [pid] : [];
|
|
14645
|
+
});
|
|
14646
|
+
}
|
|
14618
14647
|
function isRunningInsideDesktopExecutable() {
|
|
14619
14648
|
return path21.basename(process.execPath).toLowerCase().startsWith(DESKTOP_APP_NAME.toLowerCase());
|
|
14620
14649
|
}
|
|
@@ -14628,10 +14657,13 @@ async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
|
|
|
14628
14657
|
}
|
|
14629
14658
|
return null;
|
|
14630
14659
|
}
|
|
14631
|
-
async function requestDesktopQuit(executablePath, target) {
|
|
14660
|
+
async function requestDesktopQuit(executablePath, target, options = {}) {
|
|
14632
14661
|
if (!await pathExists2(executablePath)) return { ok: true, status: "not_running" };
|
|
14633
14662
|
const responsePath = path21.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
|
|
14634
|
-
const result = spawnSync3(executablePath, [
|
|
14663
|
+
const result = spawnSync3(executablePath, [
|
|
14664
|
+
`${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`,
|
|
14665
|
+
...options.forceUpdate ? [DESKTOP_UPDATE_FORCE_ARG] : []
|
|
14666
|
+
], {
|
|
14635
14667
|
stdio: "ignore",
|
|
14636
14668
|
timeout: 5e3
|
|
14637
14669
|
});
|
|
@@ -14639,7 +14671,7 @@ async function requestDesktopQuit(executablePath, target) {
|
|
|
14639
14671
|
return null;
|
|
14640
14672
|
}
|
|
14641
14673
|
try {
|
|
14642
|
-
return await waitForUpdateQuitResponse(responsePath);
|
|
14674
|
+
return await waitForUpdateQuitResponse(responsePath, options.responseTimeoutMs);
|
|
14643
14675
|
} finally {
|
|
14644
14676
|
await rm2(responsePath, { force: true });
|
|
14645
14677
|
}
|
|
@@ -14668,6 +14700,12 @@ async function waitForProcessExit(pid, timeoutMs = 2e4, intervalMs = 250) {
|
|
|
14668
14700
|
}
|
|
14669
14701
|
return !processExists(pid);
|
|
14670
14702
|
}
|
|
14703
|
+
async function waitForProcessesExit(pids, waitForExit) {
|
|
14704
|
+
const uniquePids = [...new Set(pids)];
|
|
14705
|
+
if (uniquePids.length === 0) return true;
|
|
14706
|
+
const results = await Promise.all(uniquePids.map((pid) => waitForExit(pid)));
|
|
14707
|
+
return results.every(Boolean);
|
|
14708
|
+
}
|
|
14671
14709
|
async function removePathWithRetry(targetPath, attempts = 5) {
|
|
14672
14710
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
14673
14711
|
try {
|
|
@@ -14680,50 +14718,100 @@ async function removePathWithRetry(targetPath, attempts = 5) {
|
|
|
14680
14718
|
return false;
|
|
14681
14719
|
}
|
|
14682
14720
|
async function prepareForDesktopReplace(paths, target, options = {}) {
|
|
14683
|
-
const forceQuit = options.forceQuitDesktopProcesses ?? forceQuitDesktopProcesses;
|
|
14684
14721
|
const forceQuitPid = options.forceQuitDesktopProcess ?? forceQuitDesktopProcess;
|
|
14685
14722
|
const waitForExit = options.waitForDesktopProcessExit ?? waitForProcessExit;
|
|
14723
|
+
const findPids = options.findDesktopExecutablePids ?? findDesktopExecutablePids;
|
|
14724
|
+
async function forceQuitPidAndConfirm(pid) {
|
|
14725
|
+
forceQuitPid(pid, target);
|
|
14726
|
+
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14727
|
+
if (!await waitForExit(pid)) {
|
|
14728
|
+
throw new Error(`Rudder Desktop process ${pid} did not exit after force-quit fallback. Close Rudder and rerun start.`);
|
|
14729
|
+
}
|
|
14730
|
+
}
|
|
14731
|
+
async function forceQuitPidsAndConfirm(pids) {
|
|
14732
|
+
const uniquePids = [...new Set(pids)];
|
|
14733
|
+
for (const pid of uniquePids) {
|
|
14734
|
+
forceQuitPid(pid, target);
|
|
14735
|
+
}
|
|
14736
|
+
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14737
|
+
if (!await waitForProcessesExit(uniquePids, waitForExit)) {
|
|
14738
|
+
throw new Error(`Rudder Desktop process${uniquePids.length === 1 ? "" : "es"} ${uniquePids.join(", ")} did not exit after force-quit fallback. Close Rudder and rerun start.`);
|
|
14739
|
+
}
|
|
14740
|
+
}
|
|
14741
|
+
let quitPid = null;
|
|
14742
|
+
let managedExecutablePids = [];
|
|
14686
14743
|
const hasManagedExecutable = await pathExists2(paths.executablePath);
|
|
14687
14744
|
if (hasManagedExecutable) {
|
|
14688
|
-
|
|
14689
|
-
|
|
14745
|
+
managedExecutablePids = findPids(paths.executablePath, target);
|
|
14746
|
+
const requestQuit = () => requestDesktopQuit(paths.executablePath, target, {
|
|
14747
|
+
forceUpdate: options.forceUpdate,
|
|
14748
|
+
responseTimeoutMs: options.updateQuitResponseTimeoutMs
|
|
14749
|
+
});
|
|
14750
|
+
let quitResponse = await requestQuit();
|
|
14751
|
+
while (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs" && options.waitForActiveRuns && !options.forceUpdate) {
|
|
14690
14752
|
p15.log.warn(
|
|
14691
14753
|
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}; waiting before replacing Desktop.`
|
|
14692
14754
|
);
|
|
14693
14755
|
await delay2(options.activeRunPollIntervalMs ?? 15e3);
|
|
14694
|
-
quitResponse = await
|
|
14756
|
+
quitResponse = await requestQuit();
|
|
14695
14757
|
}
|
|
14696
14758
|
if (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs") {
|
|
14759
|
+
if (!options.forceUpdate) {
|
|
14760
|
+
throw new Error(
|
|
14761
|
+
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}. Stop active work, then rerun start.`
|
|
14762
|
+
);
|
|
14763
|
+
}
|
|
14697
14764
|
throw new Error(
|
|
14698
|
-
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}. Stop active work, then rerun start.`
|
|
14765
|
+
`Rudder Desktop still has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"} after the force-update request. Stop active work, then rerun start.`
|
|
14699
14766
|
);
|
|
14700
14767
|
}
|
|
14701
|
-
|
|
14768
|
+
if (quitResponse && !quitResponse.ok && quitResponse.status === "failed") {
|
|
14769
|
+
throw new Error(quitResponse.message);
|
|
14770
|
+
}
|
|
14771
|
+
quitPid = readUpdateQuitPid(quitResponse);
|
|
14702
14772
|
if (quitPid) {
|
|
14703
14773
|
p15.log.info(`Waiting for existing Rudder Desktop process ${quitPid} to exit before replacing it.`);
|
|
14704
14774
|
if (!await waitForExit(quitPid)) {
|
|
14705
14775
|
p15.log.warn(`Rudder Desktop process ${quitPid} did not exit in time; attempting force-quit fallback.`);
|
|
14706
|
-
|
|
14707
|
-
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14776
|
+
await forceQuitPidAndConfirm(quitPid);
|
|
14708
14777
|
}
|
|
14709
14778
|
} else if (isLegacyUnconfirmedUpdateQuit(quitResponse)) {
|
|
14710
14779
|
const graceMs = options.legacyUpdateQuitGraceMs ?? LEGACY_UPDATE_QUIT_GRACE_MS;
|
|
14711
14780
|
p15.log.warn(
|
|
14712
|
-
`Existing Rudder Desktop acknowledged update quit without a process id; waiting ${Math.ceil(graceMs / 1e3)}s before
|
|
14781
|
+
`Existing Rudder Desktop acknowledged update quit without a process id; waiting ${Math.ceil(graceMs / 1e3)}s before replacement.`
|
|
14713
14782
|
);
|
|
14714
14783
|
await delay2(graceMs);
|
|
14715
|
-
|
|
14716
|
-
|
|
14784
|
+
if (managedExecutablePids.length > 0 && !await waitForProcessesExit(managedExecutablePids, waitForExit)) {
|
|
14785
|
+
p15.log.warn(
|
|
14786
|
+
`Existing Rudder Desktop did not exit after acknowledging update quit; attempting path-scoped force-quit for process${managedExecutablePids.length === 1 ? "" : "es"} ${managedExecutablePids.join(", ")}.`
|
|
14787
|
+
);
|
|
14788
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14789
|
+
}
|
|
14790
|
+
} else if (!quitResponse) {
|
|
14791
|
+
if (options.forceUpdate && managedExecutablePids.length > 0) {
|
|
14792
|
+
p15.log.warn(
|
|
14793
|
+
`Existing Rudder Desktop did not respond to the update quit request; attempting path-scoped force-quit for process${managedExecutablePids.length === 1 ? "" : "es"} ${managedExecutablePids.join(", ")}.`
|
|
14794
|
+
);
|
|
14795
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14796
|
+
} else {
|
|
14797
|
+
throw new Error("Existing Rudder Desktop did not respond to the update quit request. Close Rudder and rerun start.");
|
|
14798
|
+
}
|
|
14717
14799
|
} else {
|
|
14718
14800
|
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14719
14801
|
}
|
|
14720
14802
|
} else if (!isRunningInsideDesktopExecutable()) {
|
|
14721
|
-
|
|
14803
|
+
throw new Error("Cannot find the managed Rudder Desktop executable to request a safe update quit. Close Rudder and rerun start.");
|
|
14722
14804
|
}
|
|
14723
14805
|
const replacePath = target.platform === "windows" ? paths.installRoot : paths.appPath;
|
|
14724
14806
|
if (await removePathWithRetry(replacePath)) return;
|
|
14725
|
-
|
|
14726
|
-
|
|
14807
|
+
if (!quitPid) {
|
|
14808
|
+
if (managedExecutablePids.length > 0) {
|
|
14809
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14810
|
+
if (await removePathWithRetry(replacePath, 6)) return;
|
|
14811
|
+
}
|
|
14812
|
+
throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
|
|
14813
|
+
}
|
|
14814
|
+
await forceQuitPidAndConfirm(quitPid);
|
|
14727
14815
|
if (await removePathWithRetry(replacePath, 6)) return;
|
|
14728
14816
|
throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
|
|
14729
14817
|
}
|
|
@@ -15056,22 +15144,26 @@ async function startCommand(opts) {
|
|
|
15056
15144
|
() => assertChecksumMatch(cachedAsset.path, expectedChecksum),
|
|
15057
15145
|
desktopProgressJson ? "verifying_checksum" : null
|
|
15058
15146
|
);
|
|
15147
|
+
let applySignal = null;
|
|
15059
15148
|
if (desktopProgressJson && opts.desktopWaitForApply === true) {
|
|
15060
15149
|
writeDesktopProgress({
|
|
15061
15150
|
phase: "ready_to_install",
|
|
15062
15151
|
message: "Desktop update is downloaded and verified.",
|
|
15063
15152
|
percent: 100
|
|
15064
15153
|
});
|
|
15065
|
-
await waitForDesktopApplySignal();
|
|
15154
|
+
applySignal = await waitForDesktopApplySignal();
|
|
15066
15155
|
writeDesktopProgress({
|
|
15067
15156
|
phase: "preparing_restart",
|
|
15068
|
-
message: "Applying Desktop update..."
|
|
15157
|
+
message: applySignal.force ? "Applying Desktop update and quitting active runs..." : "Applying Desktop update..."
|
|
15069
15158
|
});
|
|
15070
15159
|
}
|
|
15071
15160
|
await runStartPhase(
|
|
15072
15161
|
"Replacing existing Rudder Desktop if needed...",
|
|
15073
15162
|
"Existing Desktop install is ready for replacement.",
|
|
15074
|
-
() => prepareForDesktopReplace(installPaths, target, {
|
|
15163
|
+
() => prepareForDesktopReplace(installPaths, target, {
|
|
15164
|
+
waitForActiveRuns: opts.waitForActiveRuns === true,
|
|
15165
|
+
forceUpdate: applySignal?.force === true
|
|
15166
|
+
}),
|
|
15075
15167
|
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
15076
15168
|
);
|
|
15077
15169
|
await runStartPhase(
|