ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

App-Store-Connect-CLI 确定性 Xcode 签名设置:`asc xcode signing plan/apply` 全解析

App-Store-Connect-CLI 确定性 Xcode 签名设置:`asc xcode signing plan/apply` 全解析 【免费下载链接】App-Store-Connect-CLIFast, scriptable CLI for the App Store Connect API. Automate TestFlight, builds, submissions, signing, analytics, screenshots, subscriptions, and more项目地址https://gitcode.com/gh_mirrors/ap/App-Store-Connect-CLI点击查看免费下载导读asc xcode signing plan/apply是 App-Store-Connect-CLI 在asc xcode命令组下新增的本地工程签名设置管理子命令它以计划plan— 校验verify— 应用apply的两阶段模型将 Xcode 工程的签名相关构建设置Team、签名样式、描述文件、entitlements 等收敛到一份确定性、可审计的 JSON 计划中。读完本文你将掌握该命令的完整契约、7 个受支持设置的取值约束、Xcode 四层构建设置优先级解析模型、共享 xcconfig 的安全改写策略以及 plan/apply 工件的校验与原子回滚机制并能够把它接入自己的 CI 与本地构建流水线。定位只改本地工程配置不碰签名资源与asc signing的职责边界asc xcode signing被刻意设计为asc signing的独立子组。asc signing管理的是 App Store Connect 侧的签名资源证书、描述文件、设备与受保护的本地签名文件keychain 材料等而asc xcode signing只修改本地 Xcode 工程配置——即告诉 Xcode 如何去消费那些资源的那部分工程设置。实现上命令组在 internal/cli/xcode/xcode.go 中以XcodeSigningCommand()注册为xcode的第 12 个子命令其核心执行逻辑在 internal/cli/xcode/xcode_signing.go。4.11 之前无持久化签名设置命令的现状设计文档明确指出在引入本命令之前asc xcode家族对签名设置只有一次性、不落盘的间接控制asc xcode export --signing-style ... --team-id ...只为单次导出生成 export options不编辑工程asc xcode build/asc xcode archive把设置作为构建参数传给单次xcodebuild调用asc xcode version结构化编辑版本设置但对签名设置没有契约asc signing fetch/sync/run/reconcile作用于证书、描述文件、设备或隔离命令而非工程设置。本命令填补的正是把签名设置持久化写回工程文件这一空白。Apple 关于 target/project 构建设置优先级与代码签名设置的官方背景可参考设计文档中引用的 build settings reference 与 target build settings guide链接见文档末尾本文不展开外部站点。命令契约plan 与 apply 两阶段完整命令形态asc xcode signing plan \ --project PATH \ --settings-file PATH \ [--state-dir PATH] [--allow-external-xcconfig] [--overwrite] \ [--output json|table|markdown] asc xcode signing apply \ --plan PATH [--allow-external-xcconfig] --confirm \ [--output json|table|markdown]从 internal/cli/xcode/xcode_signing.go 的 flag 定义看plan的实际参数比设计文档更丰富完整清单如下参数适用命令说明--project PATHplan必填精确选择一个.xcodeproj不接受 workspace--settings-file PATHplan严格 JSON 设置清单与--profile至少二选一--profile PATH可重复plan从.mobileprovision/.provisionprofile推断签名设置--configuration NAMEplan配合--profile将推断限制到单个构建配置--export-method METHODplan配合--profileapp-store、ad-hoc、development、developer-id、enterprise--export-options-out PATHplan配合--profile写出推断得到的ExportOptions.plist--skip-target NAME可重复plan配合--profile允许目标未匹配而不阻塞计划--state-dir PATHplan默认.asc/xcode/signing存放 plan/receipt 工件--allow-external-xcconfigplan / apply授权读写工程目录外的 xcconfig两次调用都需提供--overwriteplan替换已存在的 plan 工件及--export-options-out目标--plan PATHapply必填指向先前生成的 plan--confirmapply必填确认本地工程变更--output json\|table\|markdownplan / apply输出格式设计契约中有三点值得强调--project只接受.xcodeproj构建设置归工程文件所有workspace 不拥有这些设置因此被拒绝。设置文件是严格 JSON要求schemaVersion: 1与显式的 target/configuration 条目。源码 readSigningSettingsManifest 会对文件做双重校验——先rejectDuplicateJSONKeys拒绝重复键再用DisallowUnknownFields拒绝未知字段并拒绝多余 JSON 值schemaVersion必须是 1targets不能为空。apply 必须--confirm没有该标志直接返回 usage 错误见 xcodeSigningApplyCommand。受支持的设置白名单只有以下 7 个签名相关设置可以被写入源码allowedSigningSetting见 internal/xcode/signing_settings.goCODE_SIGN_STYLEDEVELOPMENT_TEAMCODE_SIGN_IDENTITYPROVISIONING_PROFILE_SPECIFIERPROVISIONING_PROFILECODE_SIGN_ENTITLEMENTSPRODUCT_BUNDLE_IDENTIFIER其余任意构建设置、shell 片段、远程响应中的路径一律不接受。任意构建设置的意图是不能写入这个白名单本身就是审计边界——命令可写的设置被收敛到一个可以人工审查的小集合。null的移除语义与取值校验null仅对可选的identity、profile、entitlements 设置移除直接赋值对 signing style、team、bundle ID 传null是非法的。源码signingSettingAllowsRemovalinternal/xcode/signing_settings.go明确只允许CODE_SIGN_IDENTITY、PROVISIONING_PROFILE_SPECIFIER、PROVISIONING_PROFILE、CODE_SIGN_ENTITLEMENTS被移除。每个设置还有类型级校验normalizeSigningValueCODE_SIGN_STYLE必须为automatic或manual归一化为Automatic/ManualDEVELOPMENT_TEAM必须匹配^[A-Z0-9]{10}$的 10 位大写字母数字 Team IDPROVISIONING_PROFILE必须是合法且非零的 UUIDPRODUCT_BUNDLE_IDENTIFIER必须是 reverse-DNS bundle identifierCODE_SIGN_ENTITLEMENTS必须是 POSIX 分隔符的相对路径禁止绝对路径、~、反斜杠、Windows 盘符与..遍历组件validateSigningRelativePath。所有值必须是静态字符串validateSigningStaticValueinternal/xcode/signing_settings.go拒绝 NUL、换行、////*/*/注释语法以及$(/${构建设置表达式。状态目录与工件权限默认状态目录是.asc/xcode/signing。plan 命令写入 mode-0600 的plan.jsonapply 写入 mode-0600 的receipt.json设计契约源码 WriteSigningPlanArtifact 通过 rootfs 以CreateNewFile(..., 0o600)创建不--overwrite时已存在即报错。planning 阶段不会改动工程或设置输入文件。解析与变更模型四层优先级与安全改写复用既有结构化模型杜绝第二套解析器实现直接复用asc xcode version使用的结构化 pbxproj 与 xcconfig 模型——即 internal/xcode/version_project.go 与 internal/xcode/version_xcconfig.go不引入第二个工程解析器。这也是设计文档必须不引入第二个 project parser的直接落地签名设置编辑器与版本编辑器共享同一套解析与无损改写能力。按 Xcode 有效顺序解析设置对每个显式 target/configuration命令按 Xcode 的有效顺序解析设置target 级 pbxproj 设置target 级 xcconfig 及其 include 图project 级 pbxproj 设置project 级 xcconfig 及其 include 图。改写规则采用最小侵入策略已存在的直接赋值原地修改xcconfig 赋值仅当该文件的所有消费者都被选中时才改写若 xcconfig 被未选中的消费者共享则新增一个窄范围 target/config 覆盖而不是扩大变更面缺失设置在选中的 target/configuration 层新增。测试对共享文件安全的覆盖可见 internal/xcode/signing_settings_test.go 的TestSigningPlanUsesExclusiveXCConfigWhenSelected与TestSigningPlanRejectsContinuedXCConfigAssignmentBeforeEditing前者验证独占 xcconfig 被直接改写后者验证共享 xcconfig 上的赋值延续会作为 blocker 拒绝。隐式变量只解析可确定的绝不猜测构建设置引用会先在显式的 pbxproj 与 xcconfig 层展开仅当没有任一层赋值该引用名时才回退到 Xcode 由工程位置推导的隐式上下文。受支持的隐式变量只有SRCROOT、SOURCE_ROOT、PROJECT_DIR选中.xcodeproj所在目录PROJECT_FILE_PATH选中.xcodeproj的绝对路径PROJECT_NAMEbundle 名称去掉扩展名TARGET_NAME拥有被解析配置的目标project 级配置无单一目标拥有者故未定义。其余隐式 Xcode 变量CONFIGURATION、PLATFORM_NAME、SDKROOT、EFFECTIVE_PLATFORM_NAME、BUILT_PRODUCTS_DIR等需要真实构建上下文保持不解析。原因很直接该命令从不调用xcodebuild猜测这些值会错误报告 plan 盘点的是哪个文件。解析出的隐式路径仍受与字面路径相同的rooted、no-follow 包含性 工件别名检查约束——不能命名选中工程根之外的文件而不被报告。Blocker 语义不猜测、不压平条件性、发散、未解析、格式错误、歧义或缺失的值全部是 blocker。没有不受支持的表达式会被猜测或压平。外部 xcconfig默认拒绝授权绑定进 plan外部 xcconfig 写入默认被拒绝。--allow-external-xcconfig必须同时提供给 plan 与 apply且精确路径与 digest 会绑定进 plan——apply 时若该 flag 与 plan 记录不一致直接报错ApplySigningPlan 中的plan.AllowExternalXCConfig ! opts.AllowExternalXCConfig检查。最终符号链接始终禁止。这里有一个设计上非常关键的安全推理任何未授权的外部 xcconfig 是硬性 planning 失败而不是一个ready: false工件。因为未读取的内容可能定义 entitlement 值或引用无法盘点的 entitlement 路径跨出授权边界盘点就会破坏安全性因此在源被--allow-external-xcconfig明确授权之前planner 不会发布任何distinct 或可覆盖的plan 工件。对应实现是signingUnauthorizedExternalXCConfigErrorinternal/xcode/signing_settings.go其消息为unauthorized external xcconfig cannot be safely inventoried without --allow-external-xcconfig配套测试见 internal/xcode/signing_authorization_test.go。Plan 与 apply 工件确定性 JSON 与事务化提交plan.json 内容结构plan 包含版本化、确定性的 JSONcommand、schema version、生成时间、规范内容哈希project 与 settings-file 路径每个可能被写入源文件的 SHA-256 digest显式的 target/configuration/setting 变更set/remove 操作来源溯源pbxproj或xcconfig排序后的 blockers 与 warnings。对应数据结构是SigningPlaninternal/xcode/signing_settings.go它把Ready、ProjectPath、SettingsFilePath、PlanPath、ReceiptPath、AllowExternalXCConfig、Desired、Files、Changes、Blockers、Warnings全部序列化每条变更SigningSettingChange第 245-255 行记录 target/configuration/setting、operation、resolution、旧值/新值与来源。哈希语义哈希只排除generatedAt与哈希字段本身但包含期望设置、选中范围、旧值与来源、源文件 digest、输出路径与外部文件授权。即任何输入变化都会使 plan 失效。Ready判定是len(plan.Blockers) 0有效但被阻塞的计划以ready: false发出畸形输入则是 exit-2 usage 错误。apply 的严格校验与原子提交apply 的流程ApplySigningPlan是一连串先验证、后写入的关卡严格解码并验证 plan校验PlanPath与工件实际位置一致、--allow-external-xcconfig匹配、Ready为 true、PlanHash有效重新解析工程与设置清单若重新构建的 plan 不Ready或哈希不一致判定为 stale报 signing plan is stale; regenerate it before applying在写任何文件之前拒绝过期或被重定向的 plan检查每个输入 digest包括MissingOptionalIncludes的迟到断言重新解析所选设置暂存所有写入重新解析暂存后的工程/配置文件以 rooted atomic no-follow 写入提交。回滚语义后续写入失败时仅当先前写入的当前身份与字节仍匹配本次事务才恢复它们若恢复不完整则单独报告 rollback failure。apply 在 receipt 发布前后都会重新验证每个源并在报告成功前通过保留的身份验证创建的 receipt。Receipt 移除同样使用 rooted no-follow 与 digest 检查但设计文档诚实指出由于可移植 rootfs API 没有 compare-and-unlink 原语最后一次身份检查后的最终路径替换仍存在残余并发窗口。此时保留当前文件apply 报告回滚不确定性而不是删除未验证的替换物。这部分由测试直接固化例如 internal/xcode/signing_settings_test.go 的TestSigningApplyRollsBackProjectWhenReceiptFinalizationFails、第 593 行TestSigningApplyRejectsUntouchedSourceChangeAfterReceiptPublication、第 819 行TestSigningApplyRollsBackProjectWhenReceiptIdentityObservationFailsAfterPublication与第 867 行TestSigningApplyPreservesReceiptReplacementWhenRollbackIdentityChanges。输出与退出码分类plan/apply 的输出由 internal/cli/xcode/xcode_signing_output.go 提供支持json、table、markdown输出中包含Ready、Blockers、Warnings等字段。确定性输入/工件形态类失败manifest 校验、artifact 别名检查被归类为 usage 错误signingInputErrorinternal/xcode/signing_settings.go由 xcodeSigningInputUsageError 包装为带DiagnosticInvalidInput的报告文件系统、解析器与暂存失败则保持普通运行时错误。命令边界测试见 internal/cli/cmdtest/xcode_signing_plan_test.go命令存在性与必填 flag 的简洁诊断与 internal/cli/xcode/xcode_signing_test.go。兼容性与验证平台支持矩阵planning 跨平台project/xcconfig 计划不依赖 Xcode 进程可在任意平台生成apply 需要原生身份耦合的文件替换/删除支持在 Windows 上rooted 文件系统层具备 handle-backed 原语之前apply 会在任何变更前 fail closed对应测试 internal/xcode/signing_settings_test.goTestSigningApplyUnsupportedOnWindowsLeavesProjectUntouched与第 287 行TestSigningApplyDoesNotUseStablePortableWriteFallbackmacOS 实时验证使用xcodebuild -list、xcodebuild -showBuildSettings以及一次 no-signing archive 语法检查。设计约束明确本变更中的任何命令都不调用 App Store Connect、不修改证书或描述文件、不导入 keychain 材料、不签名二进制、不执行 shell。测试矩阵与仓库门禁测试从命令边界开始覆盖严格输入/输出契约再逐层覆盖direct/project/xcconfig 优先级、共享文件安全、stale plan、符号链接、原子回滚、no-op receipt如 internal/xcode/signing_settings_test.goTestSigningPlanWritesCompletedNoOpReceipt、第 405 行TestSigningApplyRefusesExistingReceiptBeforeMutation、第 520 行TestWriteSigningPlanArtifactRejectsSymlinkParent。实现必须通过仓库完整的 build、format、docs、lint 与ASC_BYPASS_KEYCHAIN1 make test门禁。既有 Xcode 与 signing 命令及其 JSON 契约保持不变。典型工作流示例以下是把 plan/apply 接入本地与 CI 的完整流程# 1. 用 settings-file 生成计划只读不碰工程 asc xcode signing plan \ --project ./App.xcodeproj \ --settings-file .asc/xcode-signing.json \ --state-dir .asc/xcode/signing \ --output markdown # 2. 或用本地描述文件推断签名设置 asc xcode signing plan \ --project ./App.xcodeproj \ --profile ./signing/App.mobileprovision \ --configuration Release # 3. 审查 plan.json含 changes 与 blockers后应用 asc xcode signing apply \ --plan .asc/xcode/signing/plan.json \ --confirm \ --output json如果工程引用了工程目录之外的 xcconfigplan 与 apply 都必须带--allow-external-xcconfig且 apply 时该 flag 必须与 plan 内记录一致。若 plan 被阻塞ready: falseapply 会直接拒绝若工程在 plan 生成后被改动apply 会因为重新解析后哈希不一致而报 stale需要重新生成 plan。替代方案与设计取舍设计文档明确比较过两条路线直接编辑原始 pbxproj 行代码更短但对格式敏感、不理解 target/project 继承且可能静默修改共享配置复用仓库既有结构化工程解析器与无损 xcconfig 编辑器本命令所选与版本编辑器保持对齐同时把可写设置限制在一个小型可审计白名单内。从源码看这一取舍还带来了第二个收益由于 xcconfig 消费者分析会读取未选中的共享图来判定某文件是否可安全改写internal/xcode/signing_settings.goplan 会把所有被咨询过的 xcconfig 源文件 digest 都绑定进 plan——任何被咨询输入的变化都会在提交前使 plan 失效进一步压缩了计划与现场不一致的窗口。进一步阅读设计文档docs/design/xcode-signing-settings-plan.md命令实现internal/cli/xcode/xcode_signing.go计划构建与 apply 核心internal/xcode/signing_settings.go复用的结构化工程/xcconfig 模型internal/xcode/version_project.go、internal/xcode/version_xcconfig.go安全授权相关测试internal/xcode/signing_authorization_test.go核心行为测试internal/xcode/signing_settings_test.go命令边界测试internal/cli/xcode/xcode_signing_test.go、internal/cli/cmdtest/xcode_signing_plan_test.go赞分享【免费下载链接】App-Store-Connect-CLIFast, scriptable CLI for the App Store Connect API. Automate TestFlight, builds, submissions, signing, analytics, screenshots, subscriptions, and more项目地址https://gitcode.com/gh_mirrors/ap/App-Store-Connect-CLI点击查看免费下载相关推荐wagmi 的 WagmiProviderReact 应用接入 Ethereum 的上下文 Provider 完整指南wagmi 的 WagmiProviderReact 应用接入 Ethereum 的上下文 Provider 完整指南 本篇指南聚焦 wagmiReactiMongoDB 内置 TCMalloc 的 Temeraire 巨页感知分配器设计解析MongoDB 内置 TCMalloc 的 Temeraire 巨页感知分配器设计解析 导读 Temeraire法语意为鲁莽、大胆也是一系列英国主力战舰Radix Vue PinInputRoot 组件完全指南构建高质量验证码与 OTP 输入框Radix Vue PinInputRoot 组件完全指南构建高质量验证码与 OTP 输入框 PinInputRoot 是 radix vueReka UI上一篇Nemotron-3-Embed-1B-NVFP4安全部署隐私保护与合规性完整指南下一篇go-queue 项目常见问题解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表