Starship macOS 安装包签名与公证(Codesigning Notarization)完整指南
Starship macOS 安装包签名与公证Codesigning Notarization完整指南【免费下载链接】starship☄️ The minimal, blazing-fast, and infinitely customizable prompt for any shell!项目地址: https://gitcode.com/GitHub_Trending/st/starship导读本文基于 install/macos_packages/readme.md 及同目录下配套脚本系统梳理 starship 在 macOS 上从「构建产物」到「可安全分发安装的 .pkg 安装包」的完整流程包括二进制签名、Apple 公证Notarization、组件包与分发包构建、安装包签名与盖章Stapling。读完本文你将掌握一套可复现的命令级操作步骤、必要的 Apple 开发者凭据配置方法以及 starship 仓库中用于 CI 自动化这一流程的脚本设计与环境变量约定。为什么需要一套专门的脚本macOS 公证流程概览Apple 的公证流程复杂度极高starship 仓库作者在 readme 中直言“The Apple notarization procedure is complex enough that I need an actual pile of scripts and writeup to be able to remember how to do it.” 其核心流程如下构建代码Build code——产出待分发的 starship 二进制构建文档Build docs——生成可离线阅读的 HTML 文档使用 Developer Application ID 签名二进制Sign binary将二进制上传至 Apple 公证服务Notarize binary使用二进制 文档生成组件包Component package使用组件包生成分发包Distribution package使用 Developer Installer ID 签名分发包Sign distribution package将分发包上传至公证服务Notarize distribution package。完成以上步骤后即可得到一份经过公证notarized且可直接安装的分发包。作者在 readme 中也坦言Apple 的流程未来随时可能变化因此这份文档连同脚本共同构成了对整套流程的可追溯记录。唯一必需的本地环境前提是安装 Xcode其命令行工具提供了codesign、productbuild、pkgbuild、notarytool、stapler等关键命令。前置条件Apple Developer 账号与签名密钥Apple Developer Account获取签名密钥的前提是拥有 Apple Developer 账号需每年付费原文档撰写时约为 $100/年。这是唯一的获取途径——没有其他方式能获得非自签名密钥也无法对文件进行公证。签名密钥Signing Keys生成签名密钥可以通过 Xcode GUI 完成也有其他多种途径。无论如何你至少需要两类密钥一个 Application 签名密钥——用于签名二进制一个 Installer 签名密钥——用于签名安装包。查看本机当前可用的签名密钥使用security find-identity -p basic -v输出中左侧十六进制字符串是密钥哈希fingerprint右侧是人可读的密钥名称。公证凭据Notarization Credentials要对文件进行公证需要三样东西App 专用密码app-specific password——需要登录 Apple ID 后在账户安全设置中生成Team ID——可在 Apple Developer 账户的 Membership 页面找到Apple ID通常是邮箱地址。如果不想每次手动输入可以把凭据存入系统钥匙串keychain。Apple 官方推荐做法是使用notarytool的凭据存储命令xcrun notarytool store-credentials AUTH_ITEM_NAME \ --apple-id apple-id --password password --team-id team-id其中AUTH_ITEM_NAME是后续引用凭据时使用的名称。starship 文档后续统一使用AC_PASSWORD作为该名称与 Apple 官网教程保持一致你也可以任选其他名称。部分命令也支持通过--apple-id、--team-id、--password三个参数直接手动传入但存入钥匙串显然更省事。脚本的环境变量假设build_and_notarize.sh 等脚本对本机环境做了如下假设见脚本头部注释与 readme 的 “Script Assumptions” 一节签名密钥与公证凭据已解锁存放在特定钥匙串文件中路径为$RUNNER_TEMP/$KEYCHAIN_FILENAME公证凭据在钥匙串中的条目名AUTH_ITEM_NAME通过环境变量KEYCHAIN_ENTRY提供。build_and_notarize.sh启动时会对这三个环境变量做强制检查缺失即报错退出并验证钥匙串文件真实存在if [[ -z ${KEYCHAIN_ENTRYx} ]]; then error Environmental variable KEYCHAIN_ENTRY must be set. fi # ... RUNNER_TEMP / KEYCHAIN_FILENAME 同理 keychain_path$RUNNER_TEMP/$KEYCHAIN_FILENAME if [[ ! -f $keychain_path ]]; then error Could not find keychain at $keychain_path fi若在本地而非 CI运行与 Apple 教程中默认值对应的环境变量示例如下KEYCHAIN_ENTRYAC_PASSWORD # 或你之前为 AUTH_ITEM_NAME 选择的任意名称 RUNNER_TEMP~/Library/Keychains KEYCHAIN_FILENAMElogin.keychain给开发者的重要警告readme 原文强调由于钥匙串文件可能是用户个人钥匙串脚本中绝对禁止写入该钥匙串文件在 CI 上CI 步骤会在使用完毕后销毁shred钥匙串文件对应 .github/workflows/release.yml 中的security delete-keychain清理步骤。另外签名密钥的身份标识也通过环境变量传入脚本为 CI 场景提供了默认值# APPLICATION_KEY_IDENTE03290CABE09E9E42341C8FC82608E91241FAD4A # INSTALLATION_KEY_IDENTE525359D0B5AE97B7B6F5BB465FEC872C117D681二者既可以是密钥名称也可以是十六进制指纹当本机存在多把密钥时建议使用十六进制指纹以精确定位。一行命令跑通全流程在满足前置条件环境变量、文档已构建、release 二进制已构建的情况下只需一条命令即可生成最终安装包./install/macos_packages/build_and_notarize.sh target/release/starship docs x64在 Apple siliconM 系列上构建时把x64换成arm64脚本用法usage输出为$0 path-to-starship-binary path-to-docs-directory arch [pkgname]若省略pkgname输出包将被自动命名为starship-version-arch.pkg版本号由 common.sh 中的starship_version()函数按优先级从三个来源获取环境变量STARSHIP_VERSIONCI 通常设置→ 执行二进制-V输出 → 从根目录 Cargo.toml 中提取version字段脚本还会校验文档已构建要求docs/.vitepress/dist目录存在否则报错。逐步详解从二进制到公证安装包下面按顺序拆解 build_and_notarize.sh 中执行的每个阶段脚本头部打印标记便于跟踪进度。1. 签名二进制Codesigning a Binary签名二进制本身很简单codesign --timestamp --sign Key ID --verbose -f -o runtime binary--timestamp对签名本身非必需但公证时强制要求Key ID可以是密钥名称security find-identity -p basic -v输出右侧也可以是左侧的密钥哈希密钥较多时建议用哈希-o runtime启用 Hardened Runtime-f强制覆盖已有签名。2. 公证二进制Notarizing a Binary已签名的二进制需要先打包成.zip才能提交给 Applezip starship.zip starship注脚本中若传入的二进制名不是starship会先cp复制为starship再打包公证完成后unzip回源以便后续构建组件包。提交公证--wait会阻塞直到公证完成xcrun notarytool submit starship.zip --keychain-profile AC_PASSWORD --wait如果不希望阻塞可以省略--wait稍后再查询结果starship 的公证通常不超过 60 秒。查看公证记录与日志xcrun notarytool history --keychain-profile AC_PASSWORD # 列出所有公证尝试 xcrun notarytool info run-id --keychain-profile AC_PASSWORD # 查看某次尝试详情 xcrun notarytool log run-id --keychain-profile AC_PASSWORD # 下载 JSON 日志log命令下载的 JSON 日志会揭示应当在下一次提交前修复的警告。关于 Hardened Runtime 与 entitlementsApple 官方文档对公证提出许多要求如 Hardened Runtime 要求、entitlements 列举等。但据 readme 作者的实践经验starship 虽然会发送通知、通过 HTTP 客户端访问网络却并不需要额外的 entitlements。readme 保留了相关页面链接以备将来需要时参考。3. 构建组件包Creating a Component Packagestarship 只涉及一个二进制因此只需构建一个 Component package 和一个 Distribution package。值得注意的背景Apple 并未正式公开 flat package.pkg格式规范社区整理的文档如 matthew-brett 的 flat_packages 指南是目前可用的最佳参考。组件包的构建思路是先创建临时目录在其中构造一个伪文件系统类似 Arch 的 makepkg。例如把二进制放在$TEMP_DIR/usr/local/bin/starship安装器运行时就会把它装到/usr/local/bin/starship。对应脚本 build_component_package.sh 的具体做法pkgdir$(mktemp -d) mkdir -p $pkgdir/usr/local/bin cp $starship_program_file $pkgdir/usr/local/bin/starship文档如何进入安装包readme 中的“笨办法”Vuepress/Vitepress 构建的站点设计上依赖 HTTP 服务器运行无法直接用相对路径离线浏览。因此脚本采用了最直接的方式——启动一个本地 HTTP 服务器下载 Rust 编写的simple-http-server预编译二进制监听127.0.0.1然后用wget --mirror镜像整个站点得到可离线查看的本地副本再放入包内wget --mirror --convert-links --adjust-extension --page-requisites --no-parent 127.0.0.1:8000 wget.log || true mkdir -p $pkgdir/usr/local/share/doc/ mv 127.0.0.1:8000 $pkgdir/usr/local/share/doc/starship注意macOS 默认不安装wget但 GitHub Actions 的 runner 上有wget可能因个别链接如翻译页面中的 404返回非零退出码脚本对此做了容错|| true。最后用pkgbuild生成组件包pkgbuild --identifier com.starshipprompt.starship --version version --root pkgdir starship-component.pkg4. 为什么组件包不需要公证Apple 已确认只需公证最外层的安装机制。因此如果组件包单独分发则现在就应该公证它但 starship 会把组件包继续封装进分发包Distribution package所以组件包本身无需公证。5. 构建分发包Creating a Distribution Package构建分发包分三步见 build_distribution_package.sh用productbuild --synthesize生成骨架 distribution 文件向安装器插入自定义的欢迎/许可/结束页与图标资源用productbuild --distribution构建最终安装器。由于作者担心 fat binary 的启动成本刻意不制作通用二进制fat binary而是提供两个 plist 文件声明目标架构x86_64.pliststringx86_64/stringaarch64.pliststringarm64/string脚本按arch参数支持x86_64/x64与arm64/aarch64两组别名选择对应的 plistproductbuild --synthesize --package starship-component.pkg --product $archplist starship_raw.dist随后脚本用一个朴素的“文本行插入”技巧不引入完整 XML 解析器在installer-gui-script标签后插入欢迎页、许可页、结束页与背景图标echo welcome filewelcome.html mime-typetext-html / echo license filelicense.html mime-typetext-html / echo conclusion fileconclusion.html mime-typetext-html / echo background fileicon.png scalingproportional alignmentbottomleft/该插入方式会遗漏最后一行脚本随后追加/installer-gui-script闭合标签作为修正。这些 HTML 资源位于 pkg_resources/English.lproj/welcome.html、license.html、conclusion.html以及安装器图标 icon.png。其中 welcome.html 的内容说明安装器会把 starship 安装到/usr/local/安装完成后还需修改 shell 启动文件以启用 starship。最后生成分发包productbuild --distribution starship.dist --resources $resources --package-path $component_package starship-unsigned.pkg6. 签名分发包Signing the Distribution Package与签名二进制类似使用 Installer 密钥签名productsign --timestamp --sign Key ID starship-unsigned.pkg starship.pkg7. 公证分发包Notarizing the Distribution Package同样类比二进制公证xcrun notarytool submit starship.pkg --keychain-profile AC_PASSWORD --wait随后照例检查公证日志。readme 提示此步骤可能需要**反复输入密码多次4 次以上**才能成功。8. 盖章Stapling the Result最后把公证票据ticket“钉”进安装包使任何下载者都能离线验证安装包已通过公证xcrun stapler staple starship.pkg需要明确的是.dmg、.app、.pkg可以被 stapled但.zip和裸二进制文件不能后两者单独分发时安装电脑必须能联网才能验证公证状态。9. 收尾与命名脚本完成后按starship-version-arch.pkg或调用方传入的pkgname重命名最终产物并放置到当前目录。验证公证结果Testing Notarization对任意产物可用以下任一命令验证其是否已公证codesign --test-requirementnotarized --verify --verbose file spctl -a -vvv -t install filecodesign --test-requirementnotarized直接断言文件满足“已公证”的代码签名要求spctl -a -vvv -t install通过系统评估策略Assessment以详细输出-vvv检查该文件是否为可信的安装源。CI 中的自动化集成这套脚本并非仅为本地手工使用而设计它们同时也是 starship 发布流水线的一部分。在 .github/workflows/release.yml 的notarize_and_pkgbuildjob运行于macos-latest中可以观察到与 readme 对应的完整配套做法顶层设置KEYCHAIN_FILENAME: app-signing.keychain-db、KEYCHAIN_ENTRY: AC_PASSWORD与 readme 的“Script Assumptions”一致CI 中依次执行security create-keychain创建临时钥匙串 →set-keychain-settings -lut 21600设置超时 →unlock-keychain解锁 → 用security import导入 Application 与 Installer 证书P12 格式→xcrun notarytool store-credentials写入公证凭据然后按架构矩阵运行bash install/macos_packages/build_and_notarize.sh starship docs ${{ matrix.arch }} ${{ matrix.pkgname }}最后security delete-keychain销毁临时钥匙串呼应 readme 中“CI 会在使用后销毁钥匙串文件”的说明。这解释了 readme 中“脚本假设密钥与凭据已在$RUNNER_TEMP/$KEYCHAIN_FILENAME中解锁可用”这一前提的来源——本地用户需要自行满足CI 则由 workflow 自动保证。注意事项与经验总结钥匙串只读脚本因可能指向用户个人钥匙串而绝不写入破坏性清理交由 CI 完成版本号获取顺序优先STARSHIP_VERSION环境变量其次二进制-V最后回退解析 Cargo.toml越往后越脆弱CI 应始终设置STARSHIP_VERSION公证耗时starship 的二进制公证通常在 60 秒内完成可以不使用--wait稍后查日志架构选择因不做 fat binaryx64 与 arm64 需分别构建分发包对应两份架构 plist文档打包依赖simple-http-serverwget镜像方案wget需自行在本地安装CI runner 已自带未来兼容性Apple 的签名与公证要求可能随系统版本演进而变化readme 明确预期这套流程未来可能“坏掉”并保留了 entitlements 等参考页面以备将来需要。综上通过 install/macos_packages/readme.md 及其配套脚本build_and_notarize.sh、common.sh、build_component_package.sh、build_distribution_package.sh你可以完整复现 starship 在 macOS 上“签名 → 公证 → 打包 → 再签名 → 再公证 → 盖章”的发布链路对任何希望以原生 .pkg 形式分发 macOS 软件的 Rust 项目这套流程与脚本结构都是极具参考价值的模板。【免费下载链接】starship☄️ The minimal, blazing-fast, and infinitely customizable prompt for any shell!项目地址: https://gitcode.com/GitHub_Trending/st/starship创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考