mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-29 06:28:23 +02:00
MUL-4164: support Intel macOS Desktop packages (#5436)
* feat(desktop): support Intel macOS packages Co-authored-by: multica-agent <github@multica.ai> * fix(desktop): scope Intel macOS rollout Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Eve <eve@multica-ai.local> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -66,6 +66,7 @@ const ARCH_FLAGS = new Map([
|
||||
const SUPPORTED_CLI_ARCHS = new Set(["x64", "arm64"]);
|
||||
const MAC_ALL_PLATFORM_TARGETS = [
|
||||
{ platform: "mac", arch: "arm64" },
|
||||
{ platform: "mac", arch: "x64" },
|
||||
{ platform: "win", arch: "x64" },
|
||||
{ platform: "win", arch: "arm64" },
|
||||
{ platform: "linux", arch: "x64" },
|
||||
@@ -338,18 +339,21 @@ export function builderArgsForTarget(
|
||||
`-c.directories.output=dist/${target.platform}-${target.arch}`,
|
||||
);
|
||||
}
|
||||
// electron-builder's update metadata file is `latest.yml` for Windows
|
||||
// regardless of arch (only Linux gets an arch suffix automatically — see
|
||||
// app-builder-lib's getArchPrefixForUpdateFile). Without an explicit
|
||||
// channel override, building Windows x64 and arm64 in two invocations
|
||||
// makes both publish `latest.yml` to the same GitHub Release, so the
|
||||
// second upload overwrites the first and one of the two architectures
|
||||
// ends up with no auto-update metadata. Route Windows arm64 to its own
|
||||
// channel so x64 keeps `latest.yml` and arm64 ships `latest-arm64.yml`;
|
||||
// the renderer-side updater pins the matching channel per arch.
|
||||
// electron-builder only adds an architecture suffix to Linux update
|
||||
// metadata. Windows x64/arm64 would both publish `latest.yml`, while macOS
|
||||
// arm64/x64 would both publish `latest-mac.yml`. Keep the established x64
|
||||
// Windows and arm64 macOS feeds unchanged for installed clients, and route
|
||||
// the additional architectures to explicit channels. updater.ts pins the
|
||||
// matching channel at runtime.
|
||||
if (target.platform === "win" && target.arch === "arm64") {
|
||||
builderArgs.push("-c.publish.channel=latest-arm64");
|
||||
}
|
||||
if (target.platform === "mac" && target.arch === "x64") {
|
||||
// Scope the Electron 39 platform floor to the new Intel package so this
|
||||
// change does not rewrite established Apple Silicon bundle metadata.
|
||||
builderArgs.push("-c.mac.minimumSystemVersion=12.0.0");
|
||||
builderArgs.push("-c.publish.channel=latest-x64");
|
||||
}
|
||||
return builderArgs;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ describe("resolveBuildMatrix", () => {
|
||||
),
|
||||
).toEqual([
|
||||
{ platform: "mac", arch: "arm64" },
|
||||
{ platform: "mac", arch: "x64" },
|
||||
{ platform: "win", arch: "x64" },
|
||||
{ platform: "win", arch: "arm64" },
|
||||
{ platform: "linux", arch: "x64" },
|
||||
@@ -322,6 +323,58 @@ describe("builderArgsForTarget", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("isolates the macOS x64 feed and platform floor", () => {
|
||||
expect(
|
||||
builderArgsForTarget(
|
||||
{ platform: "mac", arch: "x64" },
|
||||
{
|
||||
allPlatforms: false,
|
||||
sharedArgs: ["--publish", "always"],
|
||||
platformTargets: { mac: ["dmg", "zip"], win: [], linux: [] },
|
||||
requestedPlatforms: ["mac"],
|
||||
requestedArchs: ["x64"],
|
||||
},
|
||||
"1.2.3",
|
||||
{ hostPlatform: "darwin", useScopedOutputDir: true },
|
||||
),
|
||||
).toEqual([
|
||||
"-c.extraMetadata.version=1.2.3",
|
||||
"--mac",
|
||||
"dmg",
|
||||
"zip",
|
||||
"--x64",
|
||||
"--publish",
|
||||
"always",
|
||||
"-c.directories.output=dist/mac-x64",
|
||||
"-c.mac.minimumSystemVersion=12.0.0",
|
||||
"-c.publish.channel=latest-x64",
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps macOS arm64 on the existing latest-mac update channel", () => {
|
||||
expect(
|
||||
builderArgsForTarget(
|
||||
{ platform: "mac", arch: "arm64" },
|
||||
{
|
||||
allPlatforms: false,
|
||||
sharedArgs: ["--publish", "always"],
|
||||
platformTargets: { mac: [], win: [], linux: [] },
|
||||
requestedPlatforms: ["mac"],
|
||||
requestedArchs: ["arm64"],
|
||||
},
|
||||
"1.2.3",
|
||||
{ hostPlatform: "darwin", useScopedOutputDir: true },
|
||||
),
|
||||
).toEqual([
|
||||
"-c.extraMetadata.version=1.2.3",
|
||||
"--mac",
|
||||
"--arm64",
|
||||
"--publish",
|
||||
"always",
|
||||
"-c.directories.output=dist/mac-arm64",
|
||||
]);
|
||||
});
|
||||
|
||||
it("defaults linux cross-builds to AppImage on non-Linux hosts", () => {
|
||||
expect(
|
||||
builderArgsForTarget(
|
||||
|
||||
@@ -26,6 +26,7 @@ vi.mock("electron-updater", () => {
|
||||
autoDownload: false,
|
||||
autoInstallOnAppQuit: false,
|
||||
channel: undefined as string | undefined,
|
||||
allowDowngrade: false,
|
||||
on: vi.fn((event: string, handler: Handler) => {
|
||||
const handlers = ctx.handlers.get(event) ?? [];
|
||||
handlers.push(handler);
|
||||
@@ -50,9 +51,40 @@ vi.mock("electron", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
import { setupAutoUpdater } from "./updater";
|
||||
import {
|
||||
configureMacX64UpdateChannel,
|
||||
setupAutoUpdater,
|
||||
} from "./updater";
|
||||
import { updaterPreferencesPath } from "./updater-preferences";
|
||||
|
||||
describe("macOS x64 update channel", () => {
|
||||
it("does not touch established architecture paths", () => {
|
||||
for (const [platform, arch] of [
|
||||
["darwin", "arm64"],
|
||||
["win32", "x64"],
|
||||
["win32", "arm64"],
|
||||
["linux", "arm64"],
|
||||
] as const) {
|
||||
const updater = { channel: null, allowDowngrade: true };
|
||||
|
||||
configureMacX64UpdateChannel(updater, platform, arch);
|
||||
|
||||
expect(updater).toEqual({ channel: null, allowDowngrade: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("does not enable downgrades when selecting an architecture feed", () => {
|
||||
const updater = { channel: null, allowDowngrade: true };
|
||||
|
||||
configureMacX64UpdateChannel(updater, "darwin", "x64");
|
||||
|
||||
expect(updater).toEqual({
|
||||
channel: "latest-x64",
|
||||
allowDowngrade: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function emitUpdater(event: string, ...args: unknown[]) {
|
||||
for (const handler of ctx.handlers.get(event) ?? []) {
|
||||
handler(...args);
|
||||
|
||||
@@ -27,6 +27,30 @@ if (process.platform === "win32" && process.arch === "arm64") {
|
||||
autoUpdater.channel = "latest-arm64";
|
||||
}
|
||||
|
||||
interface ChannelConfigurableUpdater {
|
||||
channel: string | null;
|
||||
allowDowngrade: boolean;
|
||||
}
|
||||
|
||||
export function configureMacX64UpdateChannel(
|
||||
updater: ChannelConfigurableUpdater,
|
||||
platform: NodeJS.Platform = process.platform,
|
||||
arch: string = process.arch,
|
||||
): void {
|
||||
if (platform !== "darwin" || arch !== "x64") return;
|
||||
|
||||
// AppUpdater.channel enables allowDowngrade as a side effect. This channel
|
||||
// isolates a CPU architecture, not a release train, so preserve normal
|
||||
// monotonic version behavior after selecting the architecture feed.
|
||||
updater.channel = "latest-x64";
|
||||
updater.allowDowngrade = false;
|
||||
}
|
||||
|
||||
// electron-builder does not architecture-suffix macOS update metadata.
|
||||
// package.mjs publishes macOS x64 as `latest-x64-mac.yml`; the established
|
||||
// arm64 feed and runtime path remain unchanged.
|
||||
configureMacX64UpdateChannel(autoUpdater);
|
||||
|
||||
const STARTUP_CHECK_DELAY_MS = 5_000;
|
||||
const PERIODIC_CHECK_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
|
||||
|
||||
|
||||
Reference in New Issue
Block a user