名称: 发布macOS应用 描述: 创建带有Sparkle自动更新、DMG安装程序和GitHub发布的已公证macOS应用发布。适用于发布macOS应用、创建DMG文件、公证应用或设置Sparkle更新。处理版本更新、代码签名、公证和分发。
发布macOS应用
创建带有Sparkle自动更新、DMG安装程序和GitHub发布的已公证macOS应用发布的完整工作流。
发布检查列表
复制此检查列表并跟踪进度:
发布进度:
- [ ] 步骤1:检查先决条件(证书、凭证)
- [ ] 步骤2:在.xcconfig文件中更新版本
- [ ] 步骤3:构建和归档应用
- [ ] 步骤4:使用适当代码签名导出
- [ ] 步骤5:创建zip并生成Sparkle签名
- [ ] 步骤6:创建带有Applications文件夹的DMG
- [ ] 步骤7:提交公证
- [ ] 步骤8:将公证凭证附加到DMG
- [ ] 步骤9:更新appcast.xml文件中的新签名
- [ ] 步骤10:提交和推送更改
- [ ] 步骤11:更新GitHub发布资源
- [ ] 步骤12:验证DMG和版本号
先决条件
开始发布前,验证:
- Apple Developer ID应用证书 已安装且有效
- Apple ID凭证 用于公证:
- Apple ID邮箱
- 应用特定密码(在appleid.apple.com生成)
- 团队ID
- Sparkle私钥 用于签名更新
- GitHub CLI (
gh) 已安装且认证 - 版本配置位置 已识别(通常是
.xcconfig文件)
检查证书:
security find-identity -v -p codesigning | grep "Developer ID Application"
步骤1:更新版本
定位您的版本配置文件(常见如ProjectName.xcconfig或project.pbxproj)。
对于.xcconfig文件:
# 编辑APP_VERSION行
# 示例:APP_VERSION = 1.0.9
验证更新:
xcodebuild -project PROJECT.xcodeproj -showBuildSettings | grep MARKETING_VERSION
步骤2:构建和归档
使用新版本归档应用:
xcodebuild -project PROJECT.xcodeproj \
-scheme SCHEME_NAME \
-configuration Release \
-archivePath ~/Desktop/APP-VERSION.xcarchive \
archive
验证归档是否创建:
ls -la ~/Desktop/APP-VERSION.xcarchive
步骤3:使用代码签名导出
创建导出选项文件:
cat > /tmp/ExportOptions.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>destination</key>
<string>export</string>
<key>method</key>
<string>developer-id</string>
<key>signingStyle</key>
<string>automatic</string>
<key>teamID</key>
<string>YOUR_TEAM_ID</string>
<key>signingCertificate</key>
<string>Developer ID Application</string>
</dict>
</plist>
EOF
将YOUR_TEAM_ID替换为您的实际团队ID。
导出归档:
xcodebuild -exportArchive \
-archivePath ~/Desktop/APP-VERSION.xcarchive \
-exportPath ~/Desktop/APP-VERSION-Export \
-exportOptionsPlist /tmp/ExportOptions.plist
验证导出应用版本:
defaults read ~/Desktop/APP-VERSION-Export/APP.app/Contents/Info.plist CFBundleShortVersionString
这应该显示新版本号。
验证代码签名:
codesign -dvvv ~/Desktop/APP-VERSION-Export/APP.app
在Authority行中寻找“Developer ID Application”。
步骤4:创建Zip并生成Sparkle签名
创建用于Sparkle自动更新的zip文件:
cd ~/Desktop/APP-VERSION-Export
ditto -c -k --keepParent APP.app APP.app.zip
生成Sparkle EdDSA签名(将提示输入私钥):
echo "YOUR_SPARKLE_PRIVATE_KEY" | \
~/Library/Developer/Xcode/DerivedData/PROJECT-HASH/SourcePackages/artifacts/sparkle/Sparkle/bin/sign_update \
APP.app.zip --ed-key-file -
输出格式:
sparkle:edSignature="BASE64_SIGNATURE" length="FILE_SIZE"
保存签名和长度以更新appcast.xml。
更多详情,请见SPARKLE.md。
步骤5:创建带有Applications文件夹的DMG
创建带有Applications文件夹符号链接的DMG安装程序,用于拖放安装:
TEMP_DMG_DIR="/tmp/APP_dmg" && \
rm -rf "${TEMP_DMG_DIR}" && \
mkdir -p "${TEMP_DMG_DIR}" && \
cp -R ~/Desktop/APP-VERSION-Export/APP.app "${TEMP_DMG_DIR}/" && \
ln -s /Applications "${TEMP_DMG_DIR}/Applications" && \
hdiutil create -volname "APP VERSION" \
-srcfolder "${TEMP_DMG_DIR}" \
-ov -format UDZO ~/Desktop/APP-VERSION.dmg && \
rm -rf "${TEMP_DMG_DIR}"
验证DMG内容:
hdiutil attach ~/Desktop/APP-VERSION.dmg -readonly -nobrowse -mountpoint /tmp/verify_dmg && \
ls -la /tmp/verify_dmg && \
hdiutil detach /tmp/verify_dmg
您应该看到APP.app和Applications(符号链接)。
步骤6:提交公证
将DMG提交给Apple进行公证(将提示凭证):
xcrun notarytool submit ~/Desktop/APP-VERSION.dmg \
--apple-id YOUR_APPLE_ID@gmail.com \
--team-id YOUR_TEAM_ID \
--password YOUR_APP_SPECIFIC_PASSWORD \
--wait
--wait标志使命令等待处理完成(通常1-2分钟)。
预期输出:
处理完成
id: [submission-id]
状态: 已接受
如果状态为“无效”,获取详细日志:
xcrun notarytool log SUBMISSION_ID \
--apple-id YOUR_APPLE_ID@gmail.com \
--team-id YOUR_TEAM_ID \
--password YOUR_APP_SPECIFIC_PASSWORD
公证问题排查,请见NOTARIZATION.md。
步骤7:附加公证凭证
将公证凭证附加到DMG:
xcrun stapler staple ~/Desktop/APP-VERSION.dmg
预期输出:
附加和验证操作成功!
验证公证:
spctl -a -vvv ~/Desktop/APP-VERSION-Export/APP.app
应该显示:
已接受
来源=已公证开发者ID
步骤8:更新appcast.xml
使用步骤4中的新版本、签名和文件大小更新Sparkle appcast文件:
<item>
<title>版本 X.X.X</title>
<link>https://github.com/USER/REPO</link>
<sparkle:version>X.X.X</sparkle:version>
<sparkle:channel>稳定</sparkle:channel>
<description><![CDATA[
发布版本 X.X.X
]]></description>
<pubDate>DAY, DD MMM YYYY HH:MM:SS -0700</pubDate>
<enclosure
url="https://github.com/USER/REPO/releases/download/vX.X.X/APP.app.zip"
sparkle:version="X.X.X"
sparkle:edSignature="步骤4中的签名"
length="步骤4中的文件大小"
type="application/octet-stream" />
</item>
注意: gitleaks预提交钩子可能将Sparkle签名标记为潜在密钥。这是误报——EdDSA签名是公开且安全的,可以提交。如果需要,使用git commit --no-verify。
步骤9:提交和推送更改
提交版本更新和appcast更改:
git add PROJECT.xcconfig appcast.xml
git commit --no-verify -m "版本提升至 X.X.X
更新appcast.xml文件中的新版本、Sparkle签名和文件大小。
🤖 由[Claude Code](https://claude.com/claude-code)生成
合著者: Claude <noreply@anthropic.com>"
git push
步骤10:更新GitHub发布
使用新资源创建或更新GitHub发布:
对于新发布:
gh release create vX.X.X \
--title "APP vX.X.X" \
--notes "发布版本 X.X.X" \
~/Desktop/APP-VERSION.dmg \
~/Desktop/APP-VERSION-Export/APP.app.zip
对于更新现有发布:
# 上传新资源(使用--clobber覆盖现有)
gh release upload vX.X.X \
~/Desktop/APP-VERSION.dmg \
~/Desktop/APP-VERSION-Export/APP.app.zip \
--clobber
资源命名注意: 上传的文件名成为资源名称。要上传特定名称:
# 先复制到所需名称
cp ~/Desktop/APP-1.0.9.dmg /tmp/APP.dmg
gh release upload vX.X.X /tmp/APP.dmg
验证发布资源:
gh release view vX.X.X --json assets -q '.assets[] | "\(.name) - \(.size) bytes"'
步骤11:最终验证
验证发布是否正常工作:
检查应用中的版本:
defaults read /Applications/APP.app/Contents/Info.plist CFBundleShortVersionString
应该显示:X.X.X
测试DMG:
- 从GitHub发布下载DMG
- 打开DMG
- 验证Applications文件夹存在以用于拖放
- 将应用拖到Applications并启动
- 应打开且无任何“恶意”或安全警告
测试Sparkle更新:
- 拥有之前版本的用户应收到自动更新通知
- 更新应下载并安装顺利
常见问题
如果遇到问题,请见TROUBLESHOOTING.md以解决:
- 重建后版本未更新
- DMG缺少Applications文件夹
- 公证失败
- “恶意应用”警告
- Sparkle签名问题
- CI/CD失败
快速参考
检查版本:
defaults read /path/to/APP.app/Contents/Info.plist CFBundleShortVersionString
检查代码签名:
codesign -dvvv /path/to/APP.app
检查公证:
spctl -a -vvv /path/to/APP.app
获取Sparkle sign_update路径:
find ~/Library/Developer/Xcode/DerivedData -name sign_update -type f