Skip to content

Commit 5413eb5

Browse files
7418claude
andcommitted
refactor: 简化 macOS 构建 — 只签名不公证,禁用原生热更新
CI (.github/workflows/build.yml): - 删除 mac_notarize 输入、notarization strategy/credentials 步骤 - 双架构回归单步构建,统一 -c.mac.notarize=false - 证书缺失时硬失败,不 fallback ad-hoc - 上传产物移除 blockmap / latest-mac.yml - release 收集资产移除 blockmap / yml 元数据 electron-builder.yml: - mac.notarize 固定为 false Electron 主进程 (main.ts): - 移除 initAutoUpdater / setUpdaterWindow 调用和 import Preload (preload.ts): - 移除 updater bridge,不再暴露 electronAPI.updater Updater (updater.ts): - 恢复为 no-op stub 前端 AppShell 无需改动 — isNativeUpdater 运行时检测 updater 不存在, 自动走 /api/app/updates 浏览器模式(全量下载链接)。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5629da9 commit 5413eb5

File tree

5 files changed

+25
-233
lines changed

5 files changed

+25
-233
lines changed

.github/workflows/build.yml

Lines changed: 12 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,6 @@ on:
1313
- windows
1414
- macos
1515
- linux
16-
mac_notarize:
17-
description: "mac notarization mode (arm64 only)"
18-
required: false
19-
default: "auto"
20-
type: choice
21-
options:
22-
- auto
23-
- "on"
24-
- "off"
2516
push:
2617
tags:
2718
- "v*"
@@ -56,8 +47,6 @@ jobs:
5647
name: build-windows
5748
path: |
5849
release/*.exe
59-
release/*.exe.blockmap
60-
release/latest.yml
6150
retention-days: 3
6251

6352
build-macos:
@@ -80,154 +69,51 @@ jobs:
8069
run: npm run electron:build
8170

8271
- name: Decode signing certificate
83-
if: ${{ env.HAS_CERT == 'true' }}
8472
env:
8573
MAC_CERT_P12_BASE64: ${{ secrets.MAC_CERT_P12_BASE64 }}
8674
MAC_CERT_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
8775
run: |
76+
if [ "${HAS_CERT}" != "true" ]; then
77+
echo "::error::Missing signing certificate (MAC_CERT_P12_BASE64 secret not set)"
78+
exit 1
79+
fi
8880
printf '%s' "$MAC_CERT_P12_BASE64" | tr -d '\r\n' | base64 --decode > /tmp/cert.p12
8981
openssl pkcs12 -in /tmp/cert.p12 -passin pass:"$MAC_CERT_PASSWORD" -noout
82+
echo "Certificate decoded and validated"
9083
91-
- name: Resolve arm64 notarization strategy
92-
id: mac_mode
93-
shell: bash
94-
env:
95-
MANUAL_MODE: ${{ github.event_name == 'workflow_dispatch' && inputs.mac_notarize || 'auto' }}
96-
REF_NAME: ${{ github.ref_name }}
97-
run: |
98-
set -euo pipefail
99-
MODE="${MANUAL_MODE:-auto}"
100-
NOTARIZE=false
101-
102-
if [[ "$MODE" == "on" ]]; then
103-
NOTARIZE=true
104-
elif [[ "$MODE" == "off" ]]; then
105-
NOTARIZE=false
106-
else
107-
# auto: vX.Y.0 公证;vX.Y.Z(Z>0) 只签名
108-
if [[ "$REF_NAME" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
109-
PATCH="${BASH_REMATCH[3]}"
110-
if [[ "$PATCH" == "0" ]]; then
111-
NOTARIZE=true
112-
fi
113-
fi
114-
fi
115-
116-
echo "mode=$MODE" >> "$GITHUB_OUTPUT"
117-
echo "notarize=$NOTARIZE" >> "$GITHUB_OUTPUT"
118-
echo "Resolved arm64 notarization: $NOTARIZE (mode=$MODE, ref=$REF_NAME)"
119-
120-
- name: Validate notarization credentials
121-
if: ${{ env.HAS_CERT == 'true' && steps.mac_mode.outputs.notarize == 'true' }}
122-
env:
123-
APPLE_ID: ${{ secrets.APPLE_ID }}
124-
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
125-
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
126-
run: |
127-
echo "APPLE_ID len=${#APPLE_ID}, TEAM=$APPLE_TEAM_ID, APP_PWD len=${#APPLE_APP_SPECIFIC_PASSWORD}"
128-
xcrun notarytool history \
129-
--apple-id "$APPLE_ID" \
130-
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
131-
--team-id "$APPLE_TEAM_ID" >/dev/null
132-
133-
# ── x64: sign only, no notarization ──────────────────────────────────
134-
- name: Package for macOS (x64, sign only)
84+
- name: Package for macOS (x64 + arm64, sign only)
13585
timeout-minutes: 15
13686
env:
137-
CSC_LINK: ${{ env.HAS_CERT == 'true' && '/tmp/cert.p12' || '' }}
138-
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
139-
run: |
140-
set -euo pipefail
141-
for i in 1 2 3; do
142-
echo "electron-builder x64 attempt $i/3 (notarize=false)"
143-
if npx electron-builder --mac --x64 --config electron-builder.yml -c.mac.notarize=false --publish never; then
144-
exit 0
145-
fi
146-
if [ "$i" -lt 3 ]; then sleep $((i * 30)); fi
147-
done
148-
exit 1
149-
150-
# Move x64 artifacts aside so arm64 build produces clean latest-mac.yml
151-
- name: Stash x64 artifacts
152-
run: |
153-
mkdir -p release/x64-stash
154-
mv release/*.dmg release/*.zip release/*.blockmap release/x64-stash/ 2>/dev/null || true
155-
rm -f release/latest-mac.yml
156-
157-
# ── arm64: sign + conditional notarization ───────────────────────────
158-
- name: Package for macOS (arm64)
159-
timeout-minutes: 35
160-
env:
161-
CSC_LINK: ${{ env.HAS_CERT == 'true' && '/tmp/cert.p12' || '' }}
87+
CSC_LINK: /tmp/cert.p12
16288
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
163-
APPLE_ID: ${{ steps.mac_mode.outputs.notarize == 'true' && secrets.APPLE_ID || '' }}
164-
APPLE_APP_SPECIFIC_PASSWORD: ${{ steps.mac_mode.outputs.notarize == 'true' && secrets.APPLE_APP_SPECIFIC_PASSWORD || '' }}
165-
APPLE_TEAM_ID: ${{ steps.mac_mode.outputs.notarize == 'true' && secrets.APPLE_TEAM_ID || '' }}
166-
DEBUG: electron-notarize*
167-
run: |
168-
set -euo pipefail
169-
170-
NOTARIZE="${{ steps.mac_mode.outputs.notarize }}"
171-
172-
for i in 1 2 3; do
173-
echo "electron-builder arm64 attempt $i/3 (notarize=$NOTARIZE)"
174-
175-
if [[ "$NOTARIZE" == "true" ]]; then
176-
npx electron-builder --mac --arm64 --config electron-builder.yml --publish never
177-
else
178-
npx electron-builder --mac --arm64 --config electron-builder.yml -c.mac.notarize=false --publish never
179-
fi
180-
181-
if [ $? -eq 0 ]; then
182-
exit 0
183-
fi
184-
185-
if [ "$i" -lt 3 ]; then sleep $((i * 60)); fi
186-
done
187-
188-
exit 1
189-
190-
# Restore x64 artifacts alongside arm64 output
191-
- name: Restore x64 artifacts
192-
run: mv release/x64-stash/* release/ && rmdir release/x64-stash
89+
run: npx electron-builder --mac --config electron-builder.yml --publish never
19390

19491
- name: Verify code signature
195-
if: ${{ env.HAS_CERT == 'true' }}
19692
run: |
197-
# Verify every .app bundle produced (arm64 + x64)
19893
APPS=$(find release -name "CodePilot.app" -maxdepth 3)
19994
if [ -z "$APPS" ]; then
200-
echo "::warning::No CodePilot.app found, skipping signature verification"
201-
exit 0
95+
echo "::error::No CodePilot.app found after build"
96+
exit 1
20297
fi
20398
20499
FAILED=0
205100
while IFS= read -r APP_PATH; do
206101
echo "========== Verifying: $APP_PATH =========="
207-
208-
# Display signature details
209102
codesign -dv --verbose=4 "$APP_PATH" 2>&1 | tee /tmp/codesign-info.txt || true
210103
211-
# Assert Developer ID authority
212104
if ! grep -q 'Authority=Developer ID Application' /tmp/codesign-info.txt; then
213105
echo "::error::$APP_PATH is NOT signed with Developer ID Application"
214106
FAILED=1
215107
continue
216108
fi
217109
218-
# Assert correct Team Identifier
219110
if ! grep -q 'TeamIdentifier=K9X599X9Q2' /tmp/codesign-info.txt; then
220111
echo "::error::$APP_PATH has unexpected TeamIdentifier"
221112
FAILED=1
222113
continue
223114
fi
224115
225-
# Strict verification (must pass)
226116
codesign --verify --deep --strict --verbose=4 "$APP_PATH"
227-
228-
# Gatekeeper assessment (best-effort, does not fail the build)
229-
spctl -a -vvv --type execute "$APP_PATH" || echo "::warning::spctl assessment did not pass for $APP_PATH (may be expected in CI)"
230-
231117
echo "✓ $APP_PATH passed all checks"
232118
done <<< "$APPS"
233119
@@ -236,23 +122,13 @@ jobs:
236122
exit 1
237123
fi
238124
239-
- name: Print mac release mode
240-
run: |
241-
echo "mac_notarize_mode=${{ steps.mac_mode.outputs.mode }}"
242-
echo "arm64_notarize=${{ steps.mac_mode.outputs.notarize }}"
243-
echo "x64_notarize=false (always sign-only)"
244-
echo "latest-mac.yml comes from arm64 build"
245-
246125
- name: Upload artifacts
247126
uses: actions/upload-artifact@v4
248127
with:
249128
name: build-macos
250129
path: |
251130
release/*.dmg
252-
release/*.dmg.blockmap
253131
release/*.zip
254-
release/*.zip.blockmap
255-
release/latest-mac.yml
256132
retention-days: 3
257133

258134
build-linux:
@@ -286,7 +162,6 @@ jobs:
286162
release/*.AppImage
287163
release/*.deb
288164
release/*.rpm
289-
release/latest-linux*.yml
290165
retention-days: 3
291166

292167
release:
@@ -381,13 +256,12 @@ jobs:
381256
CHANGELOG_INLINE_EOF
382257
fi
383258
384-
# Collect all release files (handle filenames with spaces)
259+
# Collect release files: installers only (no blockmap / update metadata)
385260
FILES=()
386261
while IFS= read -r f; do
387262
FILES+=("$f")
388-
done < <(find artifacts -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.blockmap" -o -name "*.yml" \) | sort)
263+
done < <(find artifacts -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \) | sort)
389264
390-
# Create release and upload all assets in one shot
391265
gh release create "${GITHUB_REF_NAME}" \
392266
--title "CodePilot v${VERSION}" \
393267
--notes-file release-notes.md \

electron-builder.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ mac:
5252
gatekeeperAssess: false
5353
entitlements: build/entitlements.mac.plist
5454
entitlementsInherit: build/entitlements.mac.inherit.plist
55-
notarize: true
55+
notarize: false
5656
target:
5757
- target: dmg
5858
arch: [x64, arm64]

electron/main.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { execFileSync, spawn, ChildProcess } from 'child_process';
44
import fs from 'fs';
55
import net from 'net';
66
import os from 'os';
7-
import { initAutoUpdater, setUpdaterWindow } from './updater';
87

98
let mainWindow: BrowserWindow | null = null;
109
let serverProcess: Electron.UtilityProcess | null = null;
@@ -163,9 +162,6 @@ function createTray(): void {
163162
click: () => {
164163
if (BrowserWindow.getAllWindows().length === 0) {
165164
createWindow(`http://127.0.0.1:${serverPort || 3000}`);
166-
if (!isDev && mainWindow) {
167-
setUpdaterWindow(mainWindow);
168-
}
169165
} else {
170166
mainWindow?.focus();
171167
}
@@ -194,9 +190,6 @@ function createTray(): void {
194190
tray.on('double-click', () => {
195191
if (BrowserWindow.getAllWindows().length === 0) {
196192
createWindow(`http://127.0.0.1:${serverPort || 3000}`);
197-
if (!isDev && mainWindow) {
198-
setUpdaterWindow(mainWindow);
199-
}
200193
} else {
201194
mainWindow?.focus();
202195
}
@@ -938,12 +931,6 @@ app.whenReady().then(async () => {
938931
autoStartReq.end();
939932
}
940933

941-
// Initialize auto-updater in packaged mode only.
942-
// Disabled on macOS x64 (Intel) — those users get browser-mode update check.
943-
const skipNativeUpdater = process.platform === 'darwin' && process.arch === 'x64';
944-
if (!isDev && mainWindow && !skipNativeUpdater) {
945-
initAutoUpdater(mainWindow);
946-
}
947934
} catch (err) {
948935
console.error('Failed to start:', err);
949936
dialog.showErrorBox(
@@ -990,10 +977,6 @@ app.on('activate', async () => {
990977
createWindow(`http://127.0.0.1:${serverPort || 3000}`);
991978
}
992979

993-
// Re-attach updater to the new window
994-
if (!isDev && mainWindow) {
995-
setUpdaterWindow(mainWindow);
996-
}
997980
} catch (err) {
998981
console.error('Failed to restart server:', err);
999982
}

electron/preload.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,4 @@ contextBridge.exposeInMainWorld('electronAPI', {
2828
bridge: {
2929
isActive: () => ipcRenderer.invoke('bridge:is-active'),
3030
},
31-
// Native updater: disabled on macOS x64 (Intel) — those users get browser-mode
32-
// update check (download link to GitHub Releases) instead.
33-
...(process.platform === 'darwin' && process.arch === 'x64' ? {} : {
34-
updater: {
35-
checkForUpdates: () => ipcRenderer.invoke('updater:check'),
36-
downloadUpdate: () => ipcRenderer.invoke('updater:download'),
37-
quitAndInstall: () => ipcRenderer.invoke('updater:quit-and-install'),
38-
onStatus: (callback: (data: unknown) => void) => {
39-
const listener = (_event: unknown, data: unknown) => callback(data);
40-
ipcRenderer.on('updater:status', listener);
41-
return () => { ipcRenderer.removeListener('updater:status', listener); };
42-
},
43-
},
44-
}),
4531
});

0 commit comments

Comments
 (0)