Skip to content
8 changes: 4 additions & 4 deletions packages/compass/src/main/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,13 @@ class CompassApplication {

await this.setupCORSBypass();
void this.setupCompassAuthService();
if (!process.env.CI || process.env.HADRON_AUTO_UPDATE_ENDPOINT_OVERRIDE) {
this.setupAutoUpdate();
}
await setupCSFLELibrary();
setupTheme(this);
this.setupJavaScriptArguments();
this.setupLifecycleListeners();
this.setupApplicationMenu();
this.setupWindowManager();
this.setupAutoUpdate();
this.trackApplicationLaunched(globalPreferences);
}

Expand Down Expand Up @@ -213,7 +211,9 @@ class CompassApplication {
}

private static setupAutoUpdate(): void {
CompassAutoUpdateManager.init(this);
if (!process.env.CI || process.env.HADRON_AUTO_UPDATE_ENDPOINT_OVERRIDE) {
void CompassAutoUpdateManager.init(this);
}
}

private static setupApplicationMenu(): void {
Expand Down
10 changes: 9 additions & 1 deletion packages/compass/src/main/auto-update-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
CompassAutoUpdateManager,
} from './auto-update-manager';
import type { DownloadItem } from 'electron';
import { dialog, autoUpdater } from 'electron';
import { dialog, autoUpdater, BrowserWindow } from 'electron';
import os from 'os';
import dl from 'electron-dl';
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
Expand Down Expand Up @@ -344,6 +344,10 @@ describe('CompassAutoUpdateManager', function () {
return Promise.resolve({ response: 0, checkboxChecked: false });
});

sandbox.stub(BrowserWindow, 'getAllWindows').callsFake(() => {
return [{} as BrowserWindow];
});

const stub = sandbox.stub(dl, 'download').callsFake(() => {
return Promise.resolve({} as DownloadItem);
});
Expand All @@ -356,6 +360,10 @@ describe('CompassAutoUpdateManager', function () {
)
).to.eq(true);

// Any small timeout will do, we're allowing for the async tasks to
// clear
await wait(300);

expect(stub).to.be.calledOnce;
});

Expand Down
98 changes: 88 additions & 10 deletions packages/compass/src/main/auto-update-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { PreferencesAccess } from 'compass-preferences-model';
import { getOsInfo } from '@mongodb-js/get-os-info';
import { createIpcTrack } from '@mongodb-js/compass-telemetry';
import type { Response } from '@mongodb-js/devtools-proxy-support';
import { pathToFileURL } from 'url';

const { log, mongoLogId, debug } = createLogger('COMPASS-AUTO-UPDATES');
const track = createIpcTrack();
Expand Down Expand Up @@ -60,6 +61,37 @@ function isMismatchedArchDarwin(): boolean {
return process.platform === 'darwin' && getSystemArch() !== process.arch;
}

async function waitForWindow(timeout = 5_000) {
const start = Date.now();
while (start + timeout > Date.now()) {
await new Promise((resolve) => setTimeout(resolve, 100));
const window = BrowserWindow.getAllWindows()[0];
if (window) {
return window;
}
}
return null;
}

async function download(url: string): Promise<void> {
const maybeWindow = await waitForWindow();
if (maybeWindow) {
await dl.download(maybeWindow, url, {
onCompleted(file) {
const fileURL = pathToFileURL(file.path).toString();
void shell.openExternal(fileURL);
},
});
} else {
await shell.openExternal(url);
}
}

function getMacOSDownloadUrl(channel: string, version: string): string {
version = channel === 'dev' ? 'latest' : version;
return `https://compass.mongodb.com/api/v2/download/${version}/compass/${channel}/darwin-${getSystemArch()}`;
}

type PromptForUpdateResult = 'download' | 'update' | 'cancel';
async function promptForUpdate(
from: string,
Expand Down Expand Up @@ -445,7 +477,7 @@ const STATE_UPDATE: Record<
},
[AutoUpdateManagerState.ManualDownload]: {
nextStates: [AutoUpdateManagerState.UserPromptedManualCheck],
enter: function (_updateManager, _fromState, updateInfo: UpdateInfo) {
enter: function (updateManager, _fromState, updateInfo: UpdateInfo) {
log.info(
mongoLogId(1_001_000_167),
'AutoUpdateManager',
Expand All @@ -467,10 +499,11 @@ const STATE_UPDATE: Record<
);
}

const url = `https://downloads.mongodb.com/compass/${
process.env.HADRON_PRODUCT
}-${updateInfo.to}-${process.platform}-${getSystemArch()}.dmg`;
void dl.download(BrowserWindow.getAllWindows()[0], url);
const url = getMacOSDownloadUrl(
updateManager.autoUpdateOptions.channel,
updateInfo.to
);
void download(url);
},
},
[AutoUpdateManagerState.UpdateDismissed]: {
Expand Down Expand Up @@ -827,11 +860,54 @@ class CompassAutoUpdateManager {
this.setState(AutoUpdateManagerState.RestartDismissed);
}

private static _init(
private static checkForMismatchedMacOSArch() {
const mismatchedOnArm =
isMismatchedArchDarwin() && getSystemArch() === 'arm64';

if (!mismatchedOnArm) {
return;
}

void dialog
.showMessageBox({
Comment on lines +871 to +872
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the performance issue is bad enough that it deserves a system prompt and not a toast or something similar, but I'm open to the feedback here

icon: COMPASS_ICON,
message: 'Mismatched architecture detected',
detail:
'You are currently using a build of Compass that is not optimized for Apple Silicon processors. This version might have significant performance issues when used. ' +
'Would you like to download the version of Compass optimized for Apple Silicon processors now?',
buttons: [
'Download Compass for Apple Silicon (Recommended)',
'Not now',
],
cancelId: 1,
})
.then(({ response }) => {
if (response === 0) {
const url = getMacOSDownloadUrl(
this.autoUpdateOptions.channel,
this.autoUpdateOptions.version
);
return download(url);
}
})
.catch((err) => {
log.warn(
mongoLogId(1_001_000_362),
'AutoUpdateManager',
'Failed to download Compass for a mismatched macos arch',
{ error: err.message }
);
});
}

private static async _init(
compassApp: typeof CompassApplication,
options: Partial<AutoUpdateManagerOptions> = {}
): void {
): Promise<void> {
await app.whenReady();

this.fetch = (url: string) => compassApp.httpClient.fetch(url);

compassApp.addExitHandler(() => {
this.stop();
return Promise.resolve();
Expand Down Expand Up @@ -867,6 +943,8 @@ class CompassAutoUpdateManager {
...options,
};

this.checkForMismatchedMacOSArch();

// TODO(COMPASS-7232): If auto-updates are not supported, then there is
// still a menu item to check for updates and then if it finds an update but
// auto-updates aren't supported it will still display a popup with an
Expand Down Expand Up @@ -961,13 +1039,13 @@ class CompassAutoUpdateManager {
);
}

static init(
static async init(
compassApp: typeof CompassApplication,
options: Partial<AutoUpdateManagerOptions> = {}
): void {
): Promise<void> {
if (!this.initCalled) {
this.initCalled = true;
this._init(compassApp, options);
await this._init(compassApp, options);
}
}

Expand Down
Loading