diff --git a/.github/workflows/release-mac-build.yml b/.github/workflows/release-mac-build.yml index bd5c5dc9c00..2344157b94f 100644 --- a/.github/workflows/release-mac-build.yml +++ b/.github/workflows/release-mac-build.yml @@ -116,6 +116,9 @@ jobs: # Why: Vite's web build crossed Node's default old-space ceiling on # the macOS release runner, leaving v1.4.2-rc.8 as an incomplete draft. NODE_OPTIONS: --max-old-space-size=4096 + # Why: native sidecars must be built with the same production identity + # that the later signed electron-builder invocation uses. + ORCA_MAC_RELEASE: '1' ORCA_BUILD_IDENTITY: ${{ steps.tag-classify.outputs.identity }} ORCA_DIAGNOSTICS_TOKEN_URL: https://www.onorca.dev/diagnostics/token ORCA_POSTHOG_WRITE_KEY: ${{ secrets.ORCA_POSTHOG_WRITE_KEY }} diff --git a/config/scripts/build-native-for-platform.mjs b/config/scripts/build-native-for-platform.mjs index 8b4f756807f..a416fd99170 100755 --- a/config/scripts/build-native-for-platform.mjs +++ b/config/scripts/build-native-for-platform.mjs @@ -1,9 +1,9 @@ #!/usr/bin/env node import { spawnSync } from 'node:child_process' +import { resolveMacosPackageBundleIdentifiers } from './macos-package-bundle-identifiers.mjs' -const isLocalMacPackage = process.argv.includes('--local-macos-package') -const localMacAppBundleId = 'com.stablyai.orca.local' +const { appBundleId, computerUseBundleId } = resolveMacosPackageBundleIdentifiers() if (process.platform === 'win32') { runNodeScript('config/scripts/build-windows-cli-launcher.mjs') @@ -15,17 +15,11 @@ if (process.platform !== 'darwin') { process.exit(0) } -runPnpmScript( - 'build:computer-macos', - [], - isLocalMacPackage - ? { ...process.env, ORCA_COMPUTER_MACOS_BUNDLE_ID: `${localMacAppBundleId}.computer-use` } - : process.env -) -runPnpmScript( - 'build:notification-status-macos', - isLocalMacPackage ? ['--bundle-id', localMacAppBundleId] : [] -) +runPnpmScript('build:computer-macos', [], { + ...process.env, + ORCA_COMPUTER_MACOS_BUNDLE_ID: computerUseBundleId +}) +runPnpmScript('build:notification-status-macos', ['--bundle-id', appBundleId]) process.exit(0) function runPnpmScript(scriptName, scriptArgs = [], env = process.env) { diff --git a/config/scripts/electron-builder-config.test.mjs b/config/scripts/electron-builder-config.test.mjs index c4db7ddd50d..97a5e803b49 100644 --- a/config/scripts/electron-builder-config.test.mjs +++ b/config/scripts/electron-builder-config.test.mjs @@ -3,6 +3,11 @@ import { createRequire } from 'node:module' import { tmpdir } from 'node:os' import { join } from 'node:path' import { describe, expect, it } from 'vitest' +import { + MACOS_LOCAL_APP_BUNDLE_ID, + MACOS_RELEASE_APP_BUNDLE_ID, + resolveMacosPackageBundleIdentifiers +} from './macos-package-bundle-identifiers.mjs' const require = createRequire(import.meta.url) const electronBuilderConfig = require('../electron-builder.config.cjs') @@ -26,14 +31,24 @@ describe('electron-builder config', () => { delete require.cache[configPath] delete process.env.ORCA_MAC_RELEASE const localConfig = require('../electron-builder.config.cjs') - expect(localConfig.appId).toBe('com.stablyai.orca') - expect(localConfig.mac.appId).toBe('com.stablyai.orca.local') + const localNativeIds = resolveMacosPackageBundleIdentifiers({}) + expect(localConfig.appId).toBe(MACOS_RELEASE_APP_BUNDLE_ID) + expect(localConfig.mac.appId).toBe(MACOS_LOCAL_APP_BUNDLE_ID) + expect(localNativeIds).toEqual({ + appBundleId: localConfig.mac.appId, + computerUseBundleId: `${localConfig.mac.appId}.computer-use` + }) delete require.cache[configPath] process.env.ORCA_MAC_RELEASE = '1' const releaseConfig = require('../electron-builder.config.cjs') - expect(releaseConfig.appId).toBe('com.stablyai.orca') + const releaseNativeIds = resolveMacosPackageBundleIdentifiers({ ORCA_MAC_RELEASE: '1' }) + expect(releaseConfig.appId).toBe(MACOS_RELEASE_APP_BUNDLE_ID) expect(releaseConfig.mac.appId).toBeUndefined() + expect(releaseNativeIds).toEqual({ + appBundleId: releaseConfig.appId, + computerUseBundleId: `${releaseConfig.appId}.computer-use` + }) } finally { if (original === undefined) { delete process.env.ORCA_MAC_RELEASE diff --git a/config/scripts/macos-package-bundle-identifiers.mjs b/config/scripts/macos-package-bundle-identifiers.mjs new file mode 100644 index 00000000000..6426129704a --- /dev/null +++ b/config/scripts/macos-package-bundle-identifiers.mjs @@ -0,0 +1,11 @@ +export const MACOS_RELEASE_APP_BUNDLE_ID = 'com.stablyai.orca' +export const MACOS_LOCAL_APP_BUNDLE_ID = 'com.stablyai.orca.local' + +export function resolveMacosPackageBundleIdentifiers(env = process.env) { + const appBundleId = + env.ORCA_MAC_RELEASE === '1' ? MACOS_RELEASE_APP_BUNDLE_ID : MACOS_LOCAL_APP_BUNDLE_ID + return { + appBundleId, + computerUseBundleId: `${appBundleId}.computer-use` + } +} diff --git a/config/scripts/package-electron-runtime-contract.test.mjs b/config/scripts/package-electron-runtime-contract.test.mjs index ec9f511e5ae..256c898d5f6 100644 --- a/config/scripts/package-electron-runtime-contract.test.mjs +++ b/config/scripts/package-electron-runtime-contract.test.mjs @@ -99,8 +99,8 @@ describe('Electron runtime package contract', () => { expect(scripts['build:linux']).toContain('pnpm run build:desktop') expect(scripts['build:linux']).not.toContain('pnpm run build ') expect(scripts['build:linux']).not.toContain('build:computer-macos') - expect(scripts['build:unpack']).toContain('pnpm run build:native -- --local-macos-package') - expect(scripts['build:mac']).toContain('pnpm run build:native -- --local-macos-package') + expect(scripts['build:unpack']).toContain('pnpm run build:native') + expect(scripts['build:mac']).toContain('pnpm run build:native') expect(scripts['build:mac:release']).not.toContain('com.stablyai.orca.local') expect(scripts['build:release']).toContain('pnpm run build:native') expect(scripts['build:release']).not.toContain('build:computer-macos') @@ -129,6 +129,9 @@ describe('Electron runtime package contract', () => { const macReleaseCommand = macWorkflow.jobs['build-mac'].steps.find( (step) => step.name === 'Publish release artifacts (macOS)' ).with.command + const macBuildStep = macWorkflow.jobs['build-mac'].steps.find( + (step) => step.name === 'Build app' + ) expect([...releaseCommands.keys()].sort()).toEqual(['linux-arm64', 'linux-x64', 'win']) for (const command of [...releaseCommands.values(), macReleaseCommand]) { @@ -139,6 +142,7 @@ describe('Electron runtime package contract', () => { ) } expect(macReleaseCommand).toContain(' && ORCA_MAC_RELEASE=1 ') + expect(macBuildStep.env.ORCA_MAC_RELEASE).toBe('1') expect(releaseCommands.get('linux-x64')).toContain(' && pnpm exec electron-builder ') expect(releaseCommands.get('linux-x64')).toContain('--linux AppImage deb rpm --x64') expect(releaseCommands.get('linux-arm64')).toContain('ORCA_LINUX_ARM64_RELEASE=1') diff --git a/native/computer-use-macos/Sources/OrcaComputerUseMacOS/main.swift b/native/computer-use-macos/Sources/OrcaComputerUseMacOS/main.swift index baa8b9ae296..0dacf809c5d 100644 --- a/native/computer-use-macos/Sources/OrcaComputerUseMacOS/main.swift +++ b/native/computer-use-macos/Sources/OrcaComputerUseMacOS/main.swift @@ -3608,6 +3608,7 @@ private func isTrustedOrcaApplication(_ pid: pid_t) -> Bool { // still authorize these Orca-owned identities. return bundleId == "com.stablyai.orca" || bundleId == "com.stablyai.orca.local" || + bundleId == "com.stablyai.orca.dev" || bundleId.hasPrefix("com.stablyai.orca.dev.") || bundleId == "com.github.Electron" } diff --git a/package.json b/package.json index 0aa0c585ea5..8e989fcb4db 100644 --- a/package.json +++ b/package.json @@ -71,10 +71,10 @@ "postinstall": "node config/scripts/rebuild-native-deps.mjs", "rebuild:electron": "node config/scripts/rebuild-native-deps.mjs", "rebuild:node": "pnpm rebuild node-pty", - "build:unpack": "pnpm run build:desktop && pnpm run build:native -- --local-macos-package && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --dir", + "build:unpack": "pnpm run build:desktop && pnpm run build:native && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --dir", "build:win": "pnpm run build:desktop && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --win", "build:icons": "bash resources/icon-source/generate.sh", - "build:mac": "pnpm run build:desktop && pnpm run build:native -- --local-macos-package && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --mac", + "build:mac": "pnpm run build:desktop && pnpm run build:native && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --mac", "build:mac:release": "node config/scripts/verify-macos-release-env.mjs && ORCA_MAC_RELEASE=1 pnpm run build:desktop && ORCA_MAC_RELEASE=1 pnpm run build:computer-macos && ORCA_MAC_RELEASE=1 pnpm run build:notification-status-macos && pnpm run ensure:electron-runtime && ORCA_MAC_RELEASE=1 electron-builder --config config/electron-builder.config.cjs --mac", "build:linux": "pnpm run build:desktop && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --linux AppImage deb", "test:e2e": "pnpm run ensure:electron-runtime && npx playwright test --config tests/playwright.config.ts --project=electron-headless",