diff --git a/.electron-builder.config.js b/.electron-builder.config.js index 4220a83..2bfaa16 100644 --- a/.electron-builder.config.js +++ b/.electron-builder.config.js @@ -9,6 +9,7 @@ * @see https://www.electron.build/configuration/configuration */ require('dotenv').config(); + function getBuildTime() { return process.env.BUILD_TIME || new Date().getTime(); } @@ -100,20 +101,34 @@ module.exports = async function () { target: [ { target: 'dmg', - arch: ['x64', 'arm64'], + arch: process.env.BUILD_ARCH || 'arm64', }, ], category: 'public.app-category.developer-tools', - hardenedRuntime: false, + hardenedRuntime: true, gatekeeperAssess: false, - entitlements: null, - entitlementsInherit: null, + entitlements: 'buildResources/entitlements.mac.plist', + entitlementsInherit: 'buildResources/entitlements.mac.plist', artifactName: '${productName}-${version}-${arch}-${os}-' + getBuildTime() + '.${ext}', compression: 'store', darkModeSupport: true, + signIgnore: [ + 'node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node', + 'node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-x64/node_sqlite3.node', + ], + // extendInfo: { + // NSAppleEventsUsageDescription: "Please allow access to system events", + // NSCameraUsageDescription: "Please allow access to camera", + // }, + // protocols: [], + // helperBundleId: `${process.env.APP_BUNDLE_ID}.helper`, + // helperEHBundleId: `${process.env.APP_BUNDLE_ID}.helper.EH`, + // helperGPUBundleId: `${process.env.APP_BUNDLE_ID}.helper.GPU`, + // helperPluginBundleId: `${process.env.APP_BUNDLE_ID}.helper.Plugin`, + // helperRendererBundleId: `${process.env.APP_BUNDLE_ID}.helper.Renderer`, }; config.dmg = { - sign: false, + sign: true, writeUpdateInfo: false, format: 'ULFO', }; @@ -146,5 +161,21 @@ module.exports = async function () { releaseType: 'draft', }; + // CI 环境特定配置(GitHub Actions 使用) + if (process.env.CI && process.platform === 'darwin') { + config.mac = { + ...config.mac, // 保留基础配置 + identity: process.env.APPLE_IDENTITY, // CI 环境使用签名 + hardenedRuntime: true, + gatekeeperAssess: false, + entitlements: 'buildResources/entitlements.mac.plist', + entitlementsInherit: 'buildResources/entitlements.mac.plist', + signIgnore: [ + 'node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-arm64/node_sqlite3.node', + 'node_modules/sqlite3/lib/binding/napi-v6-darwin-unknown-x64/node_sqlite3.node', + ], + }; + } + return config; }; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c0e9d6..f368c2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,5 +41,9 @@ jobs: dry-run: ${{ github.event_name != 'push' || (github.ref_type != 'tag' && github.ref_name != 'main') }} secrets: GH_TOKEN: ${{ secrets.GH_TOKEN }} + BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} + P12_PASSWORD: ${{ secrets.P12_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} VITE_APP_API: ${{ secrets.VITE_APP_API }} VITE_START_PAGE_URL: ${{ secrets.VITE_START_PAGE_URL }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6592df9..3d57b27 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,14 @@ on: secrets: GH_TOKEN: required: true + BUILD_CERTIFICATE_BASE64: + required: true + P12_PASSWORD: + required: true + KEYCHAIN_PASSWORD: + required: true + APPLE_IDENTITY: + required: true VITE_APP_API: required: true VITE_START_PAGE_URL: @@ -156,31 +164,69 @@ jobs: echo "VITE_APP_API=${{ secrets.VITE_APP_API }}" > .env.production.local echo "VITE_START_PAGE_URL=${{ secrets.VITE_START_PAGE_URL }}" >> .env.production.local - - name: Build Project + - name: Install Apple certificates + if: matrix.os == 'macos-latest' + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} + P12_PASSWORD: ${{ secrets.P12_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} run: | - npm run build - ls -la packages/main/dist/ - ls -la packages/preload/dist/ - ls -la packages/renderer/dist/ + CERTIFICATE_PATH=$HOME/certificates + KEYCHAIN_PATH=$HOME/Library/Keychains/build.keychain-db + + mkdir -p $CERTIFICATE_PATH + + # 输出证书长度(不要显示内容) + echo "Certificate length: ${#BUILD_CERTIFICATE_BASE64}" + + # 使用 -D 参数进行解码 + echo "$BUILD_CERTIFICATE_BASE64" | base64 -D > $CERTIFICATE_PATH/certificate.p12 + + # 检查证书文件 + ls -l $CERTIFICATE_PATH/certificate.p12 + + # 创建并配置钥匙串 + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security set-keychain-settings -t 3600 -u build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + + # 导入证书 + security import $CERTIFICATE_PATH/certificate.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign + + # 列出所有身份 + echo "All identities in keychain:" + security find-identity -v -p codesigning build.keychain + + # 设置钥匙串访问权限 + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain + + # 尝试查找特定证书 + echo "Looking for specific certificate: $APPLE_IDENTITY" + security find-certificate -a -c "$APPLE_IDENTITY" -Z build.keychain || true - name: Build macOS if: matrix.os == 'macos-latest' run: | - # 设置 Xcode - sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer - sudo xcodebuild -license accept + # 设置构建架构 + export BUILD_ARCH="${{ matrix.arch }}" - # 构建 native addon(添加详细日志) - npm run build:native-addon:mac --verbose - npm run rebuild-deps:mac --verbose - - # 检查构建产物 - ls -la packages/main/src/native-addon/build/Release/ + # 构建指定架构 + if [ "$BUILD_ARCH" = "x64" ]; then + npm run rebuild-deps:mac:x64 --verbose + npm run build:native-addon:mac:x64 --verbose + elif [ "$BUILD_ARCH" = "arm64" ]; then + npm run rebuild-deps:mac:arm64 --verbose + npm run build:native-addon:mac:arm64 --verbose + fi # 构建和发布 npm run publish --verbose env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} + BUILD_ARCH: ${{ matrix.arch }} - name: Build and Publish uses: nick-fields/retry@v2 diff --git a/buildResources/entitlements.mac.plist b/buildResources/entitlements.mac.plist index cb492c5..1361ffa 100644 --- a/buildResources/entitlements.mac.plist +++ b/buildResources/entitlements.mac.plist @@ -27,5 +27,10 @@ NSAccessibilityUsageDescription Chrome Power needs accessibility permission to manage windows. Please enable it in System Preferences. + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + \ No newline at end of file diff --git a/package.json b/package.json index e197500..a79a151 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,9 @@ "postinstall": "electron-builder install-app-deps && cross-env ELECTRON_RUN_AS_NODE=1 electron scripts/update-electron-vendors.mjs && npm run build:native-addon", "format": "npx prettier --write \"**/*.{js,mjs,cjs,ts,mts,cts,vue,json}\"", "rebuild-deps": "npm rebuild sqlite3 --build-from-source --arch=x64 && npm rebuild sqlite3 --build-from-source --arch=arm64", - "rebuild-deps:mac": "npm rebuild sqlite3 --build-from-source --arch=x64 && npm rebuild sqlite3 --build-from-source --arch=arm64" + "rebuild-deps:mac": "npm rebuild sqlite3 --build-from-source --arch=x64 && npm rebuild sqlite3 --build-from-source --arch=arm64", + "rebuild-deps:mac:x64": "npm rebuild sqlite3 --build-from-source --arch=x64", + "rebuild-deps:mac:arm64": "npm rebuild sqlite3 --build-from-source --arch=arm64" }, "devDependencies": { "@iconify/react": "^4.1.1", diff --git a/packages/main/src/fingerprint/index.ts b/packages/main/src/fingerprint/index.ts index a7f9234..8cd6bdf 100644 --- a/packages/main/src/fingerprint/index.ts +++ b/packages/main/src/fingerprint/index.ts @@ -403,7 +403,7 @@ async function createSocksProxy(proxyData: DB.Proxy) { }); // 添加更多错误处理 - proxyServer.on('error', (err) => { + proxyServer.on('error', err => { logger.error('Socks server error:', err); }); diff --git a/packages/main/src/proxy-server/socks-server.ts b/packages/main/src/proxy-server/socks-server.ts index 6483840..4374ca0 100644 --- a/packages/main/src/proxy-server/socks-server.ts +++ b/packages/main/src/proxy-server/socks-server.ts @@ -57,11 +57,11 @@ class HttpProxy extends EventEmitter { }; // 添加未捕获异常处理 - this.on('error', (error) => { + this.on('error', error => { logger.error('Proxy server error:', error); }); - - process.on('uncaughtException', (error) => { + + process.on('uncaughtException', error => { if (error instanceof Error && 'code' in error && error.code === 'ECONNRESET') { logger.error('Connection reset by peer'); } else { @@ -106,7 +106,7 @@ class HttpProxy extends EventEmitter { proxy: `${proxy.ipaddress}:${proxy.port}`, url: uReq.url, }); - + if (this.retryCount < this.maxRetries) { this.retryCount++; setTimeout(() => handleRequest(), 1000); @@ -127,7 +127,7 @@ class HttpProxy extends EventEmitter { pReq.on('response', pRes => { try { this.retryCount = 0; - + // 为响应添加错误处理 pRes.on('error', error => { logger.error('Response error:', error); @@ -144,7 +144,7 @@ class HttpProxy extends EventEmitter { pRes.pipe(uRes); uRes.writeHead(pRes.statusCode!, pRes.headers); } - + this.emit('request:success'); } catch (error) { logger.error('Error handling response:', error); diff --git a/packages/main/src/server/index.ts b/packages/main/src/server/index.ts index b16c413..6181ae0 100644 --- a/packages/main/src/server/index.ts +++ b/packages/main/src/server/index.ts @@ -29,7 +29,7 @@ app.get('/status', async (req, res) => { app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => { console.error('Express error:', err); if (!res.headersSent) { - res.status(500).json({ error: 'Internal server error' }); + res.status(500).json({error: 'Internal server error'}); } next(err); });