fastlane 之 sigh(get_provisioning_profile):一行命令创建、续期、下载与修复 iOS 预置描述文件实战指南
【免费下载链接】fastlane🚀 The easiest way to automate building and releasing your iOS and Android apps项目地址: https://gitcode.com/GitHub_Trending/fa/fastlane
本文以 fastlane 内置动作文档 get_provisioning_profile 为主体,结合仓库中 sigh 工具的真实源码(动作封装、sigh 核心实现 等)深度展开。你将掌握
sigh用于 App Store / Ad Hoc / Development / Enterprise 描述文件的生成与维护方法、与cert和match的分工关系,以及它在 fastlane 签名流程中的完整调用链与底层原理。
fastlane sigh是 fastlane 家族中处理Provisioning Profile(预置描述文件)的专用命令,对应 fastlane 动作名为get_provisioning_profile(别名sigh)。它能够在一条命令内完成描述文件的创建(Create)、续期(Renew)、下载(Download)与修复(Repair),支持 App Store、Ad Hoc、Development 与 Enterprise 四种类型,并自动把全部测试设备加入 Ad Hoc / Development 描述文件。读完本文,你可以用它替代在开发者后台手动维护.mobileprovision的繁琐流程,并将其嵌入 Jenkins 等 CI 服务器或自己的Fastfile流水线。
提示:根据 fastlane 官方建议(见文档与代码内注释),一般签名场景优先使用
match来生成和维护描述文件(详见仓库内 fastlane/docs/Codesigning/GettingStarted.md 与 match 主页);只有当你希望完全掌控签名细节、熟悉代码签名机制时才直接使用sigh。
功能总览
根据 动作文档,sigh提供如下能力:
- Download:为你的应用下载最新的预置描述文件;
- Renew:描述文件过期时自动续期;
- Repair:描述文件损坏或失效时自动修复;
- Create:当描述文件尚不存在时自动新建;
- 支持App Store、Ad Hoc、Development三种主流类型,并额外支持Enterprise(企业 In-House)描述文件;
- 支持多个 Apple 账号与多个 Team,账号凭据安全地存放在系统 Keychain 中;
- 支持 macOS / Catalyst / tvOS 等平台目标(见下文
--platform参数)。
若你需要自动化的是iOS 推送证书(Push Profile),可以改用同一仓库中的pem工具。
为什么不让 Xcode 来生成?
文档给出的理由非常实际:
sigh可以轻松集成进CI 服务器(例如 Jenkins、Bamboo、Circle 等,参见 fastlane/docs/Jenkins.md);- Xcode 有时会使本机全部现存描述文件失效(SignErrors.png 展示的就是这类签名报错),让人措手不及;
- 你可以完全掌控每个环节发生了什么、何时发生;
- 生成的签名文件会保留下来,可以直接供构建脚本使用,或提交到 git 仓库统一管理。
基本用法:一条命令搞定
最简单的用法就是直接运行:
fastlane sigh没错,这就是全部命令。默认情况下,sigh会为当前工程处理App Store 类型描述文件,完成「存在则下载、不存在则创建、过期/损坏则修复」这一整套逻辑。
传入 App 的 Bundle Identifier 与开发者账号(Apple ID):
fastlane sigh -a com.krausefx.app -u username其中-a对应app_identifier,-u对应username。值得说明的是:从 sigh 的选项定义源码 看,app_identifier的默认值会自动读取Appfile中的配置(CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)),username同样会回退到Appfile中的apple_id/apple_dev_portal_id(sigh/lib/sigh/options.rb#L84-L91),因此只要你在 Appfile 中配置妥当,通常连-a/-u都可以省略。
选择描述文件类型
生成Ad Hoc描述文件(而非默认的 App Store 类型):
fastlane sigh --adhoc生成Development描述文件:
fastlane sigh --development生成Developer ID描述文件(macOS 分发用):
fastlane sigh --developer_id以上三种开关在源码中彼此互斥::adhoc、:development、:developer_id两两设置了conflicting_options,同时开启会直接报错「You can't enable both :x and :y」(sigh/lib/sigh/options.rb#L16-L42)。此外,Enterprise(In-House)描述文件属于企业开发者账号场景,会依据账号类型自动判定,无需显式开关。
指定输出目录
默认描述文件输出在当前目录,若要存到指定文件夹:
fastlane sigh -o "~/Certificates/"-o/output_path的默认值为.(当前目录),若设置了自定义目录,会先自动创建目录,再移动生成结果(参见 sigh/lib/sigh/manager.rb#L18-L24)。
批量下载全部描述文件
需要把账号下所有描述文件都拉下来做备份或迁移时:
fastlane sigh download_all可选的--download_xcode_profiles标志用于把 Xcode 托管(Xcode managed)的描述文件也一并下载:
fastlane sigh download_all --download_xcode_profiles不过注意:在仓库源码 download_all.rb 中,--download_xcode_profiles已被标注为 deprecated——因为App Store Connect API 本身不支持查询 Xcode 托管的描述文件,仅当使用 Apple ID 账号密码方式登录时才可能拿到相关数据。该命令内部会按平台枚举 App Store / InHouse / AdHoc / Development 等全部类型并逐个拉取,跳过其中已过期或无效(invalid)的描述文件(sigh/lib/sigh/download_all.rb#L29-L88)。
查看全部参数
运行下述命令即可查看完整参数、环境变量与示例:
fastlane action sigh它相当于「本地文档查阅器」,会把动作的available_options(最终来自 sigh/lib/sigh/options.rb)以及 Fastfile 示例一次性打印出来。
进阶用法详解
文档中的「Advanced」部分给出几个高频进阶开关,下面逐一说明(含源码中的默认值与作用):
跳过本地安装
默认情况下,sigh下载描述文件后会自动安装到本机(写入 Xcode 的描述文件目录,便于后续真机调试/归档直接使用)。如果你只想拿到文件而不安装:
fastlane sigh --skip_install对应配置项:skip_install(默认false,环境变量SIGH_SKIP_INSTALL),安装这一步由Manager.install_profile调用FastlaneCore::ProvisioningProfile.install完成(sigh/lib/sigh/manager.rb#L26-L45)。
自定义保存文件名
用-q指定输出文件名(必须以.mobileprovision结尾,源码中有校验):
fastlane sigh -a com.krausefx.app -u username -q "myProfile.mobileprovision"若未指定,文件名会由Manager.start依据生成路径自动推导(sigh/lib/sigh/manager.rb#L12-L19)。
跳过证书校验
默认sigh在挑选/复用描述文件时,会校验其中的签名证书是否已安装到本机(使用FastlaneCore::CertChecker.installed?,见 runner.rb 中的校验循环)。如果某些场景下不想要这层校验(例如在非本机生成后统一分发):
fastlane sigh --skip_certificate_verification一个细节:在 options.rb 中:skip_certificate_verification的默认值是!FastlaneCore::Helper.mac?,即非 macOS 环境默认自动跳过证书校验(因为证书是否在本机通常只在 Mac 上才有意义)。
强制续期以获取最长生命周期
--force会让sigh无视描述文件当前状态,一律重建,从而拿到最大生命周期的新描述文件;对于 Ad Hoc 类型,--force还会自动把账号下所有可用测试设备加进新描述文件:
fastlane sigh --force源码中force的含义正是「Renew provisioning profiles regardless of its state - to automatically add all devices for ad hoc profiles」(sigh/lib/sigh/options.rb#L48-L53)。在 runner.rb 中,--force会先profile.delete!删除旧文件再调用create_profile!重建。
指定使用哪个签名证书
默认策略是:Development 描述文件包含全部可用证书,其余类型只使用「第一个」证书。需要指定证书时,既可以设环境变量SIGH_CERTIFICATE,也可以通过-c直接传证书的拥有者名称或证书(过期日期):
fastlane sigh -c "SunApps GmbH"对应配置项:cert_owner_name(环境变量SIGH_CERTIFICATE)。此外还有更精确的-i/:cert_id(环境变量SIGH_CERTIFICATE_ID),传的是证书在开发者后台的 ID(形如78ADL6LVAA)。在 certificates_to_use 方法 中,这两个过滤条件会同时作用于证书列表,若多个证书都命中且非 Development 类型,则打印提示并选用第一个;若一个都匹配不到,会建议你先用match或cert生成证书(代码会输出提示并报错)。
其他实用的隐藏开关(来自选项源码)
下表按 sigh/lib/sigh/options.rb 整理了完整选项与环境变量的对应关系,供你在 CI 中直接以环境变量方式注入:
| 参数(key) | 短选项 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|---|
adhoc | — | SIGH_AD_HOC | false | 生成 AdHoc 描述文件(与 development/developer_id 互斥) |
development | — | SIGH_DEVELOPMENT | false | 生成 Development 描述文件 |
developer_id | — | SIGH_DEVELOPER_ID | false | 生成 Developer ID 描述文件 |
skip_install | — | SIGH_SKIP_INSTALL | false | 下载后不自动安装到本机 |
force | -f | SIGH_FORCE | false | 无论状态一律重建(获取最大生命周期、自动包含全部设备) |
app_identifier | -a | SIGH_APP_IDENTIFIER | 取 Appfile | App 的 Bundle Identifier |
username | -u | SIGH_USERNAME | 取 Appfile | Apple ID 账号 |
team_id | -b | SIGH_TEAM_ID | 取 Appfile | 多 Team 时指定 Developer Portal Team ID |
team_name | -l | SIGH_TEAM_NAME | 取 Appfile | 多 Team 时指定 Team 名称 |
provisioning_name | -n | SIGH_PROVISIONING_PROFILE_NAME | — | 开发者后台使用的描述文件名称 |
ignore_profiles_with_different_name | — | SIGH_IGNORE_PROFILES_WITH_DIFFERENT_NAME | false | 与-n组合,仅下载完全同名描述文件 |
output_path | -o | SIGH_OUTPUT_PATH | . | 描述文件保存目录 |
cert_id | -i | SIGH_CERTIFICATE_ID | — | 使用的签名证书 ID |
cert_owner_name | -c | SIGH_CERTIFICATE | — | 使用的签名证书名称 |
filename | -q | SIGH_PROFILE_FILE_NAME | — | 输出文件名(必须 .mobileprovision 结尾) |
skip_fetch_profiles | -w | SIGH_SKIP_FETCH_PROFILES | false | 跳过既有描述文件的校验查找(账号下描述文件极多时提速) |
include_all_certificates | — | SIGH_INCLUDE_ALL_CERTIFICATES | false | 描述文件包含所有匹配证书(仅对 development 生效) |
skip_certificate_verification | -z | SIGH_SKIP_CERTIFICATE_VERIFICATION | 非 Mac 为 true | 跳过证书本机安装校验 |
platform | -p | SIGH_PLATFORM | ios | 平台:ios/tvos/macos/catalyst |
readonly | — | SIGH_READONLY | false | 只拉取既有描述文件、绝不新建(与 force 互斥) |
fail_on_name_taken | — | SIGH_FAIL_ON_NAME_TAKEN | false | 当待创建名称在后台已存在时报错退出 |
api_key_path | — | SIGH_API_KEY_PATH | — | App Store Connect API Key 的 JSON 文件路径 |
api_key | — | SIGH_API_KEY | — | App Store Connect API Key 的 Hash 配置(敏感) |
需要特别强调的是平台维度:虽然动作get_provisioning_profile声明支持[:ios, :mac](get_provisioning_profile.rb#L88-L90),但底层sigh的platform选项实际覆盖ios、tvos、macos、catalyst四种。以 macOS 为例,development会生成 Mac App Development、developer_id会生成MAC_APP_DIRECT(Developer ID),而 InHouse 在 API Key 方式下不可用(详见 module.rb 的 profile_type_for_config)。
与 fastlane(Fastfile)配合:cert + sigh 黄金组合
sigh的威力在于嵌进Fastfile与其他动作联动。文档给出的经典 beta 分发场景是先用cert保证本机装有正确的签名证书,再用sigh强制重建描述文件:
lane :beta do cert sigh(force: true) endforce: true保证每次运行都重新生成描述文件,这样sigh拿到的始终是「与本机已安装证书精确匹配」的那一个——cert负责生成/安装证书,sigh负责绑定该证书生成描述文件,二者天然衔接。从 get_provisioning_profile.rb 的实现 可以看到动作实际做了这些事:
- 若传了
api_key_path之外的 API Key(会从 lane 上下文APP_STORE_CONNECT_API_KEY继承),优先使用 API Key 认证(#L17-L20); - 把当前已完成配置的对象赋给
Sigh.config,调用Sigh::Manager.start(#L22-L24); - 将结果的绝对路径写进 lane 上下文
SIGH_PROFILE_PATH、追加到SIGH_PROFILE_PATHS列表(#L26-L28); - 读取环境变量
SIGH_UUID/SIGH_NAME同步到 lane 上下文(#L30-L33); - 依据开关计算并输出描述文件类型
app-store/ad-hoc/development/developer-id/enterprise,存入SIGH_PROFILE_TYPE(#L40-L50); - 最终返回该描述文件的 UUID(String)。
因此后续动作(比如build_app/gym)可以读取这些输出值。动作对外公布的输出汇总如下(源码 output 数组):
| Lane 上下文键 | 说明 |
|---|---|
SIGH_PROFILE_PATH | 本次导出描述文件的绝对路径 |
SIGH_PROFILE_PATHS | 多次调用累计的描述文件路径列表 |
SIGH_UUID | 本次获取/生成描述文件的 UUID |
SIGH_NAME | 描述文件的名称 |
SIGH_PROFILE_TYPE | 描述文件类型(app-store/ad-hoc/development/enterprise/developer-id),可作为build_app的export_method默认值 |
Fastfile 中的等效写法(注意sigh是get_provisioning_profile的动作别名,源码 example_code 给出了三种等价形式):
lane :beta do cert get_provisioning_profile(adhoc: true, force: true) # 或 sigh( adhoc: true, force: true, filename: "myFile.mobileprovision" ) end一键修复:repair
repair子命令会自动扫描并修复你全部「已过期或无效」的既有描述文件:
fastlane sigh repair其入口在 commands_generator.rb 的 repair 子命令,实际逻辑由 sigh/lib/sigh/repair.rb 中的Sigh::Repair.new.repair_all完成。适合定期在 CI 或发版前跑一遍,保证签名物料始终可用。
重新签名:resign
当你手上已经有一个.ipa,却想换成另一套签名(比如换证书、换描述文件后再分发),用sigh resign:
fastlane sigh resign如果.ipa文件和.mobileprovision文件恰好都在当前目录,sigh会自动帮你找到它们(分别按修改时间取最新的*.ipa与*.mobileprovision,见 resign.rb#L111-L121)。也可以显式传入全部参数:
fastlane sigh resign ./path/app.ipa --signing_identity "iPhone Distribution: Felix Krause" -p "my.mobileprovision"resign子命令的完整 CLI 参数(commands_generator.rb 的 resign 定义)包括:
| 参数 | 说明 |
|---|---|
-i/--signing_identity | 使用的签名身份(须与描述文件中定义匹配,支持名称或自动映射到 SHA-1) |
-p/--provisioning_profile | 描述文件路径;可重复传入多次,若 App 含扩展/嵌套 App,可用BUNDLE_ID=PATH前缀指定各自使用的描述文件 |
-d/--display_name | 修改 App 显示名称 |
-e/--entitlements | 指定使用的 entitlements 文件路径 |
-x/--version_number | 强制二进制及所有嵌套二进制使用该版本号(同时改CFBundleShortVersionString与CFBundleVersion) |
--short_version | 仅强制CFBundleShortVersionString |
--bundle_version | 仅强制CFBundleVersion |
--use_app_entitlements | 抽取 App bundle 自身签名 entitlements,并与新描述文件中的 entitlements 合并 |
-g/--new_bundle_id | 修改应用 Bundle ID(CFBundleIdentifier) |
--keychain_path | 指定codesign使用的钥匙串路径 |
--page_size | 设置codesign --pagesize(2 的幂) |
需要留意一个易混淆点:在resign上下文中-n/provisioning_name不适用,此时请改用-p指定描述文件路径(resign.rb 会打印相应提醒,见 resign.rb#L104-L106)。从实现看,整个重签过程最终会拼装命令调用仓库内置的 sigh/lib/assets/resign.sh 脚本(resign.rb#L58-L88),底层依赖/usr/bin/codesign,并会先通过security find-identity -v -p codesigning枚举本机可用签名身份。
本地描述文件管理:manage
manage子命令用于盘点本机已安装的预置描述文件,并支持清理:
列出本机全部已安装描述文件:
fastlane sigh manage输出会按Valid(有效)/ Expiring within 30 days(30 天内到期,黄色)/ Expired(已过期,红色)三档分组,并给出汇总统计(local_manage.rb#L51-L92)。
删除所有已过期的描述文件:
fastlane sigh manage -e用正则表达式批量删除(例如清除 Xcode 自动生成的iOS Team Provisioning Profile系列,注意反斜杠转义空格):
fastlane sigh manage -p "iOS\ ?Team Provisioning Profile:"删除前会逐条列出命中项并请求确认;在 CI 服务器上必须附加-f(--force)跳过确认交互,否则会直接报错(local_manage.rb#L102-L127)。manage读取的是 fastlane_core 认定的 Xcode 描述文件安装目录下的*.mobileprovision,逐个用security cms -D -i解出 plist 后按名称排序(local_manage.rb#L129-L145)。
认证与原理:它背后是怎么工作的?
sigh的工作本质是通过 spaceship 访问 Apple 开发者后台 / App Store Connect API,去下载、续期或生成.mobileprovision文件。这一设计在仓库内完整可见:
- API 层:所有对 Apple 服务的通信都由仓库中的 spaceship 完成;
- 认证方式:支持两套——① App Store ConnectAPI Key(
api_key/api_key_path,生成 JWT token);② 传统Apple ID 账号密码(username,登录 Developer Portal)。Runner 启动时会先尝试 API Key,否则强制询问用户名并调用Spaceship::ConnectAPI.login(runner.rb#L20-L35); - 主流程(sigh/lib/sigh/runner.rb#L16-L66):
- 按平台与配置(
adhoc/development/developer_id/企业账号 in_house)解析出目标描述文件类型(映射逻辑见 module.rb 的 profile_type_for_config); - 拉取并过滤候选描述文件:要求
bundle_id匹配、profile 有效(或开启force)、证书已安装本机(除非跳过校验)等(fetch_profiles); - 若没有可用描述文件且未开
readonly,先确认 App Identifier 存在(ensure_app_exists!,不存在时会提示你改用produce创建 App ID),再按需自动选择/创建证书与新描述文件(create_profile!); - 下载得到 profile 内容(Base64 解码后写入临时目录),随后由
Manager移动到output_path并按需安装(download_profile + manager.rb)。
- 按平台与配置(
一个值得注意的行为约束:Development 类型描述文件可包含多个证书,而其他类型只取「第一个」匹配证书(runner.rb 末尾的certificates_to_use逻辑,runner.rb#L300-L301);Development/AdHoc 类型才会拉取设备列表并写入设备(devices_to_use)。
密码与凭据存在哪?
sigh使用 fastlane 的CredentialsManager来管理 Apple ID 凭据——它会将账号密码安全地写入macOS 系统钥匙串(Keychain),并在后续运行中自动复用,不会在命令行或脚本里明文留存。详见仓库中的 credentials_manager 模块。
使用建议与常见问题
优先推荐match管理签名物料
尽管sigh功能完整,文档和源码注释都明确建议:常规情况下用match配合 codesigning.guide 的推荐流程来集中生成与维护签名材料(把证书与描述文件加密后存入 git 仓库、团队共享),仅在需要完全掌控细节时才直接使用sigh。相关入门材料见 fastlane/docs/Codesigning/GettingStarted.md 与 match 工具主页。
用 ProvisionQL 在 Finder 中预览描述文件
安装 ProvisionQL 插件后,.mobileprovision文件可以直接在 Finder 的 Quick Look 中查看其包含的 App ID、设备、证书、过期时间等关键信息,对排查「装错描述文件」类问题非常高效。你可将描述文件拖到该目录手工管理,而sigh生成的文件默认已自动安装到系统描述文件目录。
提示「App Identifier couldn't be found」
当开发者后台尚不存在对应的 App Identifier 时,sigh会打印类似下面这样的建议,指引你先创建 App ID(源码 ensure_app_exists! / print_produce_command):
fastlane produce -u <username> -a <bundle_identifier> --skip_itcproduce正是同一仓库中负责在 Developer Portal(以及可选地 App Store Connect)上创建 App 的工具,详见 produce 主页。
会不会动我 Xcode 托管的描述文件?
不会。sigh从不触碰 Xcode 自动创建/托管的描述文件,它只管理自己生成的那一套(默认还会主动避开 Xcode 管理的命名空间)。这意味着你完全可以放心地让 Xcode 与sigh/match两套体系并存。基于此前提,若你的工程使用了 Xcode 的自动签名而手动生成的描述文件又恰好同名,需要留意 Xcode 版本可能对描述文件目录的读取策略存在差异——这正是文档建议「同一套体系用到底」的原因。
小结
sigh(get_provisioning_profile)把描述文件的「查、建、续、修、批量下载、本地盘点、重签 ipa」全部收敛为一条命令,是 fastlane 签名流水线中承上启下的关键一环:向下通过 spaceship 直连 Apple 服务,向上与cert(提供证书)、match(统一托管)、produce(创建 App ID)、gym(打包,可读取SIGH_PROFILE_TYPE作为导出方式默认值)无缝衔接。若你准备摆脱在开发者后台手动维护.mobileprovision的重复劳动,把描述文件管理纳入自动化,本文覆盖的命令行参数、环境变量映射与源码级行为说明即可作为直接可用的参考手册。
相关阅读:动作文档原文见 fastlane/lib/fastlane/actions/docs/get_provisioning_profile.md,动作封装见 fastlane/lib/fastlane/actions/get_provisioning_profile.rb,sigh全部实现位于 sigh/lib/sigh,对应测试位于 sigh/spec(含 resign_spec.rb、manager_spec.rb 等,可进一步佐证上述行为)。
【免费下载链接】fastlane🚀 The easiest way to automate building and releasing your iOS and Android apps项目地址: https://gitcode.com/GitHub_Trending/fa/fastlane
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考