移动/游戏
用 asc distribute 向注册设备私下分发…
当需要把已有 iOS 归档/ IPA 私下分发给已注册设备(不走 TestFlight/App Store)时,用 asc distribute 完成计划、签名、发布与验证。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 asc distribute 向注册特定
解决思路
- 先确认已安装的契约:运行 `asc distribute --help`、`asc distribute plan --help`、`asc distribute apply --help`、`asc distribute resume --help`、`asc distribute status --help`、`asc distribute verify --help`。
- 选择工作流:从 `.xcarchive` 开始做端到端、哈希授权的运行,用 `plan` -> `apply` -> `resume`/`status` -> `verify`;若调用方已持有 ad hoc IPA 并想分别操作底层边界,则用 `inspect` -> `prepare` -> `publish`。
- 把分发 spec、devices 文件、PKCS#12 身份、密码文件、运行状态和精确安装链接产物都视为私密,排除在 Git 之外并设为仅属主可读权限。
- 绝不要把 S3 凭据或预签名 URL 放进分发 spec、命令输出、日志、issue 或聊天;改用 `ASC_S3_ACCESS_KEY_ID`、`ASC_S3_SECRET_ACCESS_KEY` 和可选的 `ASC_S3_SESSION_TOKEN`,或标准 AWS SDK 凭据链。
- `plan` 是只读的,可能以 `ready: false` 成功退出;继续前检查类型化的 blockers 和 effects。
- 仅在用户授权确切的 plan hash 和 effect 清单后运行 `apply`;它会注册缺失设备、创建安全的 App ID 和后继 ad hoc profile、写入本地产物并发布不可变对象。
- 注意编排工作流只支持对已有 S3 兼容 bucket 的私有访问,不会创建 bucket、修改策略、删除旧构建、安装或启动应用。
- 遇到输入漂移、不可变对象冲突、签名材料过期或私有链接过期时,必须重新 plan,不要强行推进旧运行。
- 前置条件:已有含单一主 app target 的 iOS `.xcarchive`(内嵌 app、扩展、Watch app、App Clip 会让 v1 plan 不 ready);本地 iOS 分发 PKCS#12 身份和可选的受保护密码文件;受保护的 strict-v1 devices 文件(如 `{"schemaVersion":1,"devices":[{"name":"Test iPhone","udid":"DEVICE_UDID","platform":"IOS"}]}`);可访问 devices、Bundle IDs、certificates、profiles 的 App Store Connect 认证;已有 S3 兼容 bucket 和有效凭据。
- 创建私有分发 spec:相对路径从 spec 目录解析,spec 不插值环境变量也不接受凭据;示例字段包括 `schemaVersion`、`devicesFile`、`signing.identity`(`format`、`path`、`passwordFile`)、`signing.minimumValidityDays`、`signing.maxMutations`、`publication`(`endpoint`、`downloadEndpoint`、`region`、`bucket`、`prefix`、`addressingStyle`、`urlTtl`、`downloadGrace`、`verifyTimeout`)和 `metadata`(`title`、`channel`、`sourceRevision`、`sourceUrl`)。
- `passwordFile`、`certificateSha256`、`downloadEndpoint` 和所有 metadata 字段都是可选的;省略 passwordFile 意味着 PKCS#12 必须使用空密码。
- 规划前保护配置和密钥输入:`chmod 600 ".asc/distribution/config.json" ".asc/distribution/devices.json"`、`chmod 600 ".asc/signing/distribution.p12" ".asc/secrets/distribution-p12-password"`。
- 无变更地规划:运行 `asc distribute plan --archive-path ".asc/artifacts/App.xcarchive" --config ".asc/distribution/config.json" --plan ".asc/distribution/plan.json" --state-dir ".asc/distribution/runs" --output json`。
- 检查 `ready`、`planHash`、签名有效期、目标和完整有序的 `effects` 清单;当 `ready` 为 false 时解决 blockers 并创建新 plan,不要仅凭退出码推断就绪。
- 在批准确切 effects 后应用授权 plan:`PLAN_HASH="$(jq -er '.planHash' ".asc/distribution/plan.json")"`,然后 `asc distribute apply --plan ".asc/distribution/plan.json" --confirm "$PLAN_HASH" --output json`;缺失、格式错误或不匹配的确认会在副作用前被拒绝。
- 理解 apply 成功意味着发布和实时抓取验证已完成,但不代表设备已安装或启动应用。
- 用返回的 `runId` 检查、恢复和验证:`asc distribute status --run "RUN_ID" --state-dir ".asc/distribution/runs" --output json`、`asc distribute resume --run "RUN_ID" --state-dir ".asc/distribution/runs" --output json`、`asc distribute verify --run "RUN_ID" --state-dir ".asc/distribution/runs" --timeout 30s --output json`。
- `status` 仅本地,对 `running`、`recoverable`、`blocked` 运行都成功;应基于类型化字段而非文字描述分支。
- `resume` 在重试前重新验证持久证据,绝不盲目重复远程写入;`verify` 只读但执行实时抓取。
- 仅当用户要求观察已连接设备上匹配的已安装 bundle、版本和 build 时,才加 `--device "DEVICE_SELECTOR"`;该观察不能证明 IPA 字节一致。
- 精确的私有安装 URL 是 bearer 凭据,只存储在完成运行报告的属主私有 link 产物中;仅通过批准的私密渠道分享给目标测试者。
- 底层 IPA 工作流:当签名和导出已完成时,运行 `asc distribute inspect --ipa ".asc/artifacts/App.ipa" --output json`、`asc distribute prepare --ipa ".asc/artifacts/App.ipa" --channel "pull-request-42" --output json`,然后把 `prepare` 返回的确切 `bundleDir` 传给 `publish`:`asc distribute publish --bundle-dir ".asc/distribution/com.example.app/1.2-42-IPA_SHA_PREFIX" --endpoint "https://objects.example.com" --region "auto" --bucket "ios-builds" --prefix "team/app" --receipt ".asc/publishes/app-1.2-42.json" --link-path ".asc/publishes/app-1.2-42-link.json" --output json`。
- `inspect` 除非显式需要 `--include-devices`,否则省略原始设备 UDID;`prepare` 从不覆盖 bundle,只复用完全等价的 bundle。
- 私有 `publish` 是默认行为,只把精确预签名链接写入 mode-0600 的 link 产物;公开发布是单独的显式通道,使用 `--access public --public-base-url`,它假定匿名读取已配置好且从不修改存储策略。
适用边界 · 注意事项
- 构建应通过 Apple 托管的 TestFlight 或 App Store 分发时,改用 TestFlight 或 App Store 发布技能。
- 归档包含内嵌 app、扩展、Watch app 或 App Clip 时,v1 plan 不会 ready。
- 没有已有 S3 兼容 bucket 和有效凭据,或没有 App Store Connect 对 devices/Bundle IDs/certificates/profiles 的访问权限时。