跨平台Electron应用自动化签名与分发:基于Github Actions的实战指南

跨平台Electron应用自动化签名与分发:基于Github Actions的实战指南

1. 为什么需要自动化签名与分发?

开发过macOS桌面应用的朋友应该都遇到过这样的场景:好不容易写完代码打包成应用,用户下载后却提示"无法验证开发者"。这是因为macOS的Gatekeeper安全机制会拦截未签名的应用。传统解决方案是手动签名+公证,但每次更新都要重复操作,效率极低。

我在团队中负责Electron应用的CI/CD流程搭建,最初每次发布都要花2小时处理签名问题。后来改用Github Actions实现全自动化后,现在从代码提交到发布只需点个按钮。这套方案特别适合中小团队——不需要额外服务器,直接利用Github的免费额度就能跑起来。

自动化流程的核心价值在于:

  • 解决信任问题:自动完成开发者ID签名+Apple公证,确保应用能通过Gatekeeper验证
  • 提升发布效率:代码合并后自动触发构建、签名、发布,无需人工干预
  • 降低操作门槛:新成员无需学习复杂的证书管理,提交代码即可获得合规安装包
  • 多平台统一:同一套配置可同时处理macOS/Windows/Linux的构建任务

2. 前期准备工作

2.1 获取Apple开发者证书

没有证书就像没有身份证,应用寸步难行。我建议选择$99/年的个人开发者账号,比企业账号审批更快。注册时注意:

  1. 准备CSR文件(证书签名请求)。如果有Mac电脑,直接用钥匙串访问生成;如果是Linux/Win环境,可以用OpenSSL:
openssl genrsa -out macos.key 2048 openssl req -new -sha256 -key macos.key -out macos.csr

执行第二条命令时会要求填写个人信息,其中Common Name建议用邮箱地址,后面公证流程会用到。

  1. 登录Apple开发者后台,进入Certificates页面,选择"Developer ID Application"类型证书。上传刚才生成的CSR文件后,会下载到.cer格式证书。

  2. 将证书转换为P12格式(后续Github Actions要用):

openssl x509 -in developerID_application.cer -inform DER -outform PEM -out developerID_application.pem openssl pkcs12 -export -inkey macos.key -in developerID_application.pem -out developerID_application.p12

2.2 配置应用专用密码

Apple要求双重认证账号才能进行公证。我们需要在Apple ID账户页面生成专用密码(注意不是开发者后台):

  1. 登录Apple ID管理页面
  2. 在"安全"板块找到"应用专用密码"
  3. 输入描述(如"Electron公证")后生成密码
  4. 妥善保存这个密码,后面配置Github Secrets时会用到

3. Electron项目配置实战

3.1 基础环境搭建

我的项目基于electron-builder+vue3,如果你用其他框架,调整对应配置即可。关键依赖:

yarn add @electron/notarize dotenv --dev

在项目根目录创建.env文件(记得加入.gitignore):

XCODE_APP_LOADER_EMAIL=你的AppleID邮箱 XCODE_APP_LOADER_PASSWORD=上一步生成的应用专用密码

3.2 配置自动公证脚本

创建scripts/notarize.js

require('dotenv').config() const { notarize } = require("@electron/notarize") module.exports = async (context) => { if (context.electronPlatformName !== 'darwin') return const appPath = `${context.appOutDir}/${context.packager.appInfo.productFilename}.app` await notarize({ appBundleId: "com.yourcompany.app", // 改成你的应用ID appPath, appleId: process.env.XCODE_APP_LOADER_EMAIL, appleIdPassword: process.env.XCODE_APP_LOADER_PASSWORD }) }

然后在vue.config.js中配置electronBuilder:

pluginOptions: { electronBuilder: { builderOptions: { afterSign: 'scripts/notarize.js', appId: 'com.yourcompany.app', mac: { category: 'public.app-category.developer-tools', target: ['dmg', 'zip'] } } } }

4. Github Actions完整流水线

4.1 配置仓库密钥

在Github仓库Settings > Secrets > Actions中添加:

  • BUILD_CERTIFICATE_BASE64: 执行base64 developerID_application.p12输出的内容
  • P12_PASSWORD: 生成P12文件时设置的密码
  • XCODE_APP_LOADER_EMAIL: 你的Apple ID邮箱
  • XCODE_APP_LOADER_PASSWORD: 应用专用密码
  • GH_TOKEN: 有repo权限的Personal Access Token

4.2 编写workflow文件

创建.github/workflows/release.yml

name: Release Pipeline on: push: tags: v* jobs: build: strategy: matrix: os: [macos-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: node-version: 18 - name: Install dependencies run: yarn - name: Setup certificate (macOS) if: matrix.os == 'macos-latest' run: | echo ${{ secrets.BUILD_CERTIFICATE_BASE64 }} | base64 --decode > cert.p12 KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain security create-keychain -p mypassword $KEYCHAIN_PATH security import cert.p12 -P ${{ secrets.P12_PASSWORD }} -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH - name: Build env: CSC_LINK: file://$RUNNER_TEMP/cert.p12 CSC_KEY_PASSWORD: ${{ secrets.P12_PASSWORD }} run: yarn electron:build - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: ${{ runner.os }}-build path: dist_electron/ release: needs: build runs-on: ubuntu-latest steps: - name: Download artifacts uses: actions/download-artifact@v3 with: path: artifacts - name: Create release uses: softprops/action-gh-release@v1 with: files: | artifacts/*.dmg artifacts/*.zip artifacts/*.AppImage

5. 常见问题排查指南

5.1 公证失败怎么办?

查看Github Actions日志中Notarization步骤的输出。常见错误:

  • Invalid credentials:检查Apple ID密码是否使用应用专用密码
  • App not found:确认appBundleId配置与Info.plist中的CFBundleIdentifier一致
  • Timeout:Apple服务器响应慢时,可以重试job

5.2 多平台构建优化技巧

  1. Windows签名需要购买EV代码签名证书(比Apple证书贵很多),中小团队可以考虑用开源工具osslsigncode进行自签名
  2. Linux构建时注意处理不同发行版的依赖,推荐使用AppImage通用格式
  3. 矩阵构建会并行执行,如果遇到资源限制可以改用include语法顺序执行

5.3 提升构建速度

  1. 使用actions/cache缓存node_modules:
- uses: actions/cache@v3 with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('yarn.lock') }}
  1. macOS构建特别耗时,可以单独拆分到手动触发的workflow
  2. 使用electron-builder的asar: false配置能显著加快增量构建

这套方案在我们团队稳定运行一年多,累计完成300+次自动发布。最惊喜的是当Apple调整公证规则时,只需更新notarize.js脚本就能适配,所有项目都能受益。对于需要同时维护多个Electron应用的团队,还可以将配置提取成共享的Github Action,进一步统一流程。