自动化与脚本
不用 Xcode 从零搭建、打包并发布 SwiftPM…
当你需要不依赖 Xcode 工程、用 SwiftPM 构建 macOS 应用并完成 .app 打包、签名、公证与发布时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
不用 Xcode 从零搭建、打包并发布 特定
解决思路
- 复制 assets/templates/bootstrap/ 到新仓库,作为起始布局。
- 重命名 Package.swift、Sources/MyApp/ 和 version.env 中的 MyApp,并自定义 APP_NAME、BUNDLE_ID 和版本号。
- 把 assets/templates/ 中的脚本复制到仓库(例如 Scripts/ 目录)。
- 用 swift build 和 swift test 构建与测试。
- 用 Scripts/package_app.sh 打包成 .app。
- 用 Scripts/compile_and_run.sh(首选)或 Scripts/launch.sh 运行应用。
- 可选发布:运行 Scripts/sign-and-notarize.sh 和 Scripts/make_appcast.sh。
- 可选打标签并发布 GitHub release:创建 git tag,把 zip/appcast 上传到 GitHub release 并发布。
- 打包后验证:用 ls -R build/HelloApp.app/Contents 确认 .app 结构完整,用 file build/HelloApp.app/Contents/MacOS/HelloApp 确认二进制存在且可执行。
- 签名后验证:用 codesign -dv --verbose=4 build/HelloApp.app 检查签名与 entitlements,用 spctl --assess --type execute --verbose build/HelloApp.app 本地验证 Gatekeeper 检查。
- 公证并 stapling 后验证:用 stapler validate build/HelloApp.app 确认 staple ticket 已附加,再跑一次 spctl --assess --type execute --verbose build/HelloApp.app 确认公证被识别。
- 遇到 “The software asset has already been uploaded”:在 version.env 中递增 BUILD_NUMBER 后重新打包。
- 遇到 “Package Invalid: Invalid Code Signing Entitlements”:对照 Apple 允许的集合审查 .entitlements,删除不支持的键。
- 遇到 “The executable does not have the hardened runtime enabled”:编辑 sign-and-notarize.sh,在所有 codesign 调用中加上 --options runtime。
- 遇到公证挂起或无状态邮件:运行 xcrun notarytool history 检查状态,若 App Store Connect API key 过期则重新导出。
- 遇到公证成功后 stapler validate 失败:等待约 60 秒,再重新运行 xcrun stapler staple。
- 保持 entitlements 和签名配置显式;直接编辑模板脚本,不要重新实现。
- 如果不使用 Sparkle 更新,移除 Sparkle 相关步骤。
- Sparkle 依赖 bundle build number(CFBundleVersion),因此每次更新都必须递增 version.env 中的 BUILD_NUMBER。
- 对于菜单栏应用,打包时设置 MENU_BAR_APP=1,以便在 Info.plist 中写入 LSUIElement。
适用边界 · 注意事项
- 需要 Xcode 工程或依赖 Xcode 专有构建流程时。
- 不使用 Sparkle 做更新时,不应保留 appcast 相关步骤。
- 没有 Apple 开发者签名/公证凭据时,无法完成签名与公证发布流程。