diff --git a/.github/workflows/alpha-macos-aarch64.yml b/.github/workflows/alpha-macos-aarch64.yml index ad432faec..eadfa2997 100644 --- a/.github/workflows/alpha-macos-aarch64.yml +++ b/.github/workflows/alpha-macos-aarch64.yml @@ -4,9 +4,9 @@ name: Alpha Channel (macOS arm64) # alpha release channel. # # The alpha channel is macOS-only today. It lives as a rolling GitHub -# release under the fixed tag `alpha-macos-latest` so the Tauri updater -# manifest URL stays stable while the underlying artifact gets replaced on -# every run. +# release under the fixed tag `alpha-macos-latest` so both the Tauri updater +# manifest and Electron updater feed stay stable while the underlying +# artifacts get replaced on every run. # # See: # - apps/app/src/app/lib/release-channels.ts (updater endpoint URLs) @@ -306,7 +306,21 @@ jobs: uploadUpdaterJson: false releaseAssetNamePattern: openwork-desktop-[platform]-[arch][ext] - - name: Build Electron alpha package + - name: Reject unsigned Electron alpha release + if: env.MACOS_NOTARIZE != 'true' + shell: bash + run: | + echo "Electron alpha artifacts must be signed and notarized. Set MACOS_NOTARIZE=true and provide Apple signing secrets." >&2 + exit 1 + + - name: Build Electron alpha app + if: env.MACOS_NOTARIZE == 'true' + shell: bash + env: + TARGET: aarch64-apple-darwin + run: pnpm --filter @openwork/desktop build:electron + + - name: Package Electron alpha (macOS, signed + notarized) if: env.MACOS_NOTARIZE == 'true' env: CSC_LINK: ${{ secrets.APPLE_CODESIGN_CERT_P12_BASE64 }} @@ -317,8 +331,11 @@ jobs: APPLE_API_KEY_PATH: ${{ env.NOTARY_KEY_PATH }} run: | set -euo pipefail - pnpm --filter @openwork/desktop run build:electron - pnpm --dir apps/desktop exec electron-builder --config electron-builder.yml --mac --arm64 --publish never + pnpm --dir apps/desktop exec electron-builder \ + --config electron-builder.yml \ + --mac \ + --arm64 \ + --publish never - name: Upload Electron alpha updater assets if: env.MACOS_NOTARIZE == 'true' diff --git a/apps/app/src/react-app/domains/settings/state/electron-updater-state.ts b/apps/app/src/react-app/domains/settings/state/electron-updater-state.ts index 30c539119..8fa0e7564 100644 --- a/apps/app/src/react-app/domains/settings/state/electron-updater-state.ts +++ b/apps/app/src/react-app/domains/settings/state/electron-updater-state.ts @@ -104,11 +104,16 @@ export function useElectronUpdaterState(options: UseElectronUpdaterStateOptions) let cancelled = false; void bridge .getChannel() - .then((state) => { + .then(async (state) => { if (cancelled) return; setAppVersion(state.currentVersion ?? null); - if (state.channel && state.channel !== releaseChannel) { - onReleaseChannelChange(state.channel); + if (state.channel && state.channel !== releaseChannel && bridge.setChannel) { + const nextState = await bridge.setChannel(releaseChannel); + if (cancelled) return; + setAppVersion(nextState.currentVersion ?? null); + if (nextState.channel && nextState.channel !== releaseChannel) { + onReleaseChannelChange(nextState.channel); + } } }) .catch(() => { diff --git a/apps/desktop/electron/updater.mjs b/apps/desktop/electron/updater.mjs index 509c795b9..143363cf7 100644 --- a/apps/desktop/electron/updater.mjs +++ b/apps/desktop/electron/updater.mjs @@ -80,6 +80,8 @@ function updaterChannelState(app, channel) { async function applyElectronUpdaterFeed(app, updater) { const channel = await readElectronUpdaterChannel(app); const state = updaterChannelState(app, channel); + updater.allowPrerelease = state.channel === "alpha"; + updater.channel = state.channel; if (updater?.setFeedURL) { updater.setFeedURL({ provider: "generic", url: state.feedUrl }); }