使用 App Center CLI 发布 CodePush 更新

重要

Visual Studio App Center 计划于 2025 年 3 月 31 日停用。 虽然可以继续使用 Visual Studio App Center,直到它完全停用,但你可以考虑迁移到几个建议的替代方法。

详细了解支持时间线和替代方案。

安装

  • 安装 Node.js
  • 安装 App Center CLI: npm install -g appcenter-cli

入门

  1. 使用 appcenter login 命令创建 App Center 帐户或通过 CLI 登录。
  2. 使用 CodePush 注册应用,并选择性地与团队中的其他开发人员共享应用
  3. CodePush-ify 应用,并将其指向想要使用的部署 (Apache CordovaReact Native) 。
  4. 发布和更新应用

帐户管理

在开始发布应用更新之前,请使用现有的 CodePush 帐户登录或创建新的 App Center 帐户。 安装 CLI 后,可以通过运行以下命令来执行此操作:

appcenter login

此命令将启动浏览器,要求你使用 GitHub 或 Microsoft 帐户进行身份验证。 通过身份验证后,它将创建一个“链接”到 GitHub/MSA 标识的 CodePush 帐户,并生成一个访问密钥,你可以复制/粘贴到 CLI 中以登录。

注意

注册后,将自动使用 CLI 登录,因此在显式注销之前,无需从同一台计算机再次登录。

身份验证

App Center CLI 中的大多数命令都需要身份验证,因此在开始管理帐户之前,请使用注册时使用的 GitHub 或 Microsoft 帐户登录。 可以通过执行以下命令来执行此操作:

appcenter login

此命令将启动浏览器窗口,要求使用 GitHub 或 Microsoft 帐户进行身份验证。 它将生成一个访问密钥以复制粘贴到 CLI 中, (它会提示你) 。 现已成功进行身份验证,可以安全地关闭浏览器窗口。

每当想要检查(如果已登录)时,都可以运行以下命令来显示当前身份验证会话的电子邮件地址、用户名和显示名称:

appcenter profile list

从 CLI 登录时,访问密钥在会话期间会保留在磁盘上,这样就不必每次尝试访问帐户时都登录。 若要结束会话并删除此访问密钥,请执行以下命令:

appcenter logout

如果你忘记从不想在 (上保留正在运行的会话的计算机注销,例如,你朋友的笔记本电脑) ,则可以使用以下命令列出和删除任何当前登录会话。

appcenter tokens list
appcenter tokens delete <machineName>

访问令牌

若要在不启动浏览器的情况下对 CodePush 服务进行身份验证,或者无需使用 GitHub 或 Microsoft 凭据 ((例如,在 CI 环境) ),可以执行以下命令来创建“访问令牌” (以及描述其用途的名称) :

appcenter tokens create -d "Azure DevOps Integration"

密钥仅显示一次,因此请记得根据需要将其保存到某个位置! 创建新密钥后,可以使用 命令的 login 标志指定其值--token,这允许使用“无外设”身份验证,而不是启动浏览器。

appcenter login --token <accessToken>

使用此方法登录时,访问令牌不会在注销时自动失效,并且可以在将来的会话中使用,直到从 App Center 服务器中显式删除。 但是,应在会话完成后注销,以从磁盘中删除凭据。

应用管理

在部署更新之前,请使用以下命令通过 App Center 创建应用:

appcenter apps create -d <appDisplayName> -o <operatingSystem>  -p <platform> 

如果你的应用同时面向 Android 和 iOS,我们强烈建议使用 CodePush 创建单独的应用。 每个平台各一个。 这样,你可以单独管理和发布更新,从长远来看,这往往会使事情变得更简单。 大多数人将应用名称后缀为 -Android-iOS。 例如:

appcenter apps create -d MyApp-Android -o Android -p React-Native
appcenter apps create -d MyApp-iOS -o iOS -p Cordova

注意

为 Android 和 iOS 使用相同的应用可能会导致安装异常,因为为 iOS 生成的 CodePush 更新包的内容与为 Android 生成的更新内容不同。

提示

App Center CLI 中的一项重要新功能是能够使用 appcenter apps set-current <ownerName>/<appName>将应用设置为当前应用。 通过将应用设置为当前应用,无需 -a 在其他 CLI 命令中使用 标志。 例如,当设置当前应用时,命令 appcenter codepush deployment list -a <ownerName>/<appName> 可以缩短为 appcenter codepush deployment list 。 可以使用 检查将哪个应用设置为帐户的当前应用appcenter apps get-current。 设置当前应用可使键入大多数 CLI 命令更短。

使用原始 CodePush 时,应用会自动 (和 Production) 两个部署Staging。 在 App Center 中,必须使用以下命令自行创建它们:

appcenter codepush deployment add -a <ownerName>/<appName> Staging
appcenter codepush deployment add -a <ownerName>/<appName> Production

创建部署后,可以使用 访问这两个部署的部署appcenter codepush deployment list --displayKeys密钥,可以使用 这些密钥通过移动客户端各自的 SDK 配置移动客户端, (CordovaReact Native) 的详细信息。

如果你决定不喜欢给应用命名,可以随时使用以下命令重命名它:

appcenter apps update -n <newName> -a <ownerName>/<appName>

警告

更改应用名称可能会在分支配置和生成大约 48 小时内生成一些意外问题。

如果某个时候不再需要应用,可以使用以下命令将其从服务器中删除:

appcenter apps delete -a <ownerName>/<appName>

执行此命令时请小心,因为已配置为使用该命令的任何应用都将停止接收更新。

最后,如果要列出已注册到 App Center 服务器的所有应用,请运行以下命令:

appcenter apps list

应用协作

如果要在同一 CodePush 应用上与其他开发人员合作,则可以按照以下说明使用 App Center 门户将他们添加为协作者:

  1. 在 App Center 门户中,选择要为其添加协作者的应用
  2. 在页面左侧的导航区域中,单击“ 设置”
  3. 单击 协作者 链接
  4. 在协作者菜单中,输入协作者的电子邮件地址以邀请他们。

重要

App Center 的协作者功能要求每个协作者都已使用指定的电子邮件地址 向 App Center 注册

添加后,所有协作者将立即在共享应用中具有以下权限:

  1. 查看应用、其协作者、 部署发布历史记录
  2. 发布 任何应用部署的更新
  3. 应用的任何部署之间升级更新
  4. 回滚 应用的任何部署
  5. 修补 应用的任何部署中的任何版本

协作者无法执行以下操作:

  1. 重命名或删除应用
  2. 在应用中创建、重命名或删除新部署
  3. 清除部署的发布历史记录
  4. 在应用中添加或删除协作者 (*)

注意

开发人员可以将自己作为协作者从与其共享的应用中删除。

随着时间的推移,如果某人不再与你一起处理应用,你还可以使用门户中的此协作者菜单删除他们作为协作者。

每当想要列出已添加到应用的所有协作者时,都可以访问门户中的协作者菜单。

部署管理

从 CodePush 的角度来看,应用是一个或多个“部署”的命名分组。 虽然应用表示特定于平台的应用版本的概念性“命名空间”或“范围” (,例如 Foo 应用) 的 iOS 端口,但其部署表示开发人员) 发布 (更新的实际目标, (最终用户) 同步更新。 部署允许在任何给定时间为每个应用提供多个“环境”,并帮助对应用通常从开发人员的个人环境迁移到测试/QA/过渡环境,然后再进入生产环境这一现实进行建模。

注意

如下所述, releasepromoterollback 命令需要应用名称和部署名称才能正常工作,因为两者的组合唯一标识分发点 (例如,我想将 iOS 应用的更新发布到 beta 测试人员) 。

每当向 CodePush 服务注册应用时,建议创建以下部署: StagingProduction。 这样,便可以开始向内部环境发布更新,在该环境中可以全面测试每个更新,然后再将其推送给最终用户。 此工作流对于确保发布可供大量使用至关重要,并且是一种已在 Web 中长期建立的做法。

如果拥有应用的过渡和生产版本足以满足你的需求,则无需执行任何其他操作。 但是,如果需要 alpha、dev 等部署,可以使用以下命令轻松创建它们:

appcenter codepush deployment add -a <ownerName>/<appName> <deploymentName>

与应用一样,还可以分别使用以下命令删除和重命名部署:

appcenter codepush deployment remove -a <ownerName>/<appName> <deploymentName>
appcenter codepush deployment rename -a <ownerName>/<appName> <deploymentName> <newDeploymentName>

每当想要查看特定应用包含的部署列表时,都可以运行以下命令:

appcenter codepush deployment list -a <ownerName>/<appName>

安装指标具有以下含义:

  • 活动 - 当前运行此版本的成功安装数 (如果用户打开应用,他们将看到/运行此版本) 。 随着最终用户升级到和离开此版本,此数字将更改。 此指标同时显示活动用户总数,以及代表的总体受众的百分比。 这样就可以轻松确定用户当前正在运行的更新的分发,并回答“我的有多少用户收到了我的最新更新?”等问题。

  • 总计 - 此更新接收的成功安装总数。 此数字只会随着新用户/设备安装而增加,因此它始终是总活动计数的超集。 一旦 notifyApplicationReady (或 sync) 在安装后调用更新,就会被视为成功。 从下载更新并将其标记为成功的那一刻起,该更新将被报告为“挂起的”更新 (请参阅下文,了解) 的详细信息。

  • 挂起 - 此版本已下载但尚未安装 (应用) 应用更改的次数。 因此,此指标会随着更新的下载而增加,而随着相应下载的更新的安装而减少。 此指标主要适用于未配置为立即安装的更新,并帮助为依赖应用恢复或重启应用更新的应用提供更广泛的发布采用情况 (例如,我想回滚更新,我很想知道是否有人下载了更新) 。 如果你已将更新配置为立即安装,并且仍然看到报告挂起的更新,则可能是在应用启动时未调用 notifyApplicationReady (或 sync) ,这是开始发送安装报告并将已安装的更新标记为成功的方法。

  • 回滚 - 此版本在客户端上自动回滚的次数。 理想情况下,此数字应为零,在这种情况下,甚至不显示此指标。 但是,如果发布的更新在安装过程中包含崩溃,CodePush 插件会将最终用户回滚到以前的版本,并将该问题报告回服务器。 这样,如果发布中断,最终用户可以保持不受阻止状态;通过在 CLI 中查看此遥测数据,可以识别错误版本,并通过在服务器上 回滚来响应这些 版本。

  • 推出 - 指示有资格接收此更新的用户的百分比。 此属性仅针对表示“活动”推出的版本显示,因此,推出百分比小于 100%。 此外,由于部署在任何给定时间只能有一个活动推出,因此此标签将仅在部署中的最新版本上显示。

  • 已禁用 - 指示版本是否已标记为禁用,因此最终用户可下载。 仅针对禁用的版本显示此属性。

当指标单元格报告 No installs recorded时,指示服务器未看到此版本的任何活动。 这可能是因为它排除了包含遥测支持的插件版本,或者还没有最终用户与 CodePush 服务器同步。 安装完成后,你就会开始在 CLI 中为发布填充指标。

释放汇报

将应用配置为针对 App Center 服务器查询更新后,可以开始发布更新。 为了提供简单性和灵活性,App Center CLI 包含三个用于发布更新的不同命令:

  1. 常规 - 发布由外部工具或生成脚本生成的 App Center 服务器的更新, (例如 Gulp 任务、 react-native bundle 命令) 。 这在适应现有工作流方面提供了最大的灵活性,因为它严格处理特定于 CodePush 的步骤,并将特定于应用的编译过程留给你。

  2. React Native - 使用与常规发布命令相同的功能,但也处理生成更新的应用内容的任务 (JS 捆绑包和资产) ,而不是要求同时运行 react-native bundle ,然后运行 appcenter codepush release

  3. Cordova - 使用与常规发布命令相同的功能,但也处理为你准备应用更新的任务,而不是要求你同时 cordova prepare 运行 (或 phonegap prepare) 然后 appcenter codepush release运行 。

应使用其中哪些命令主要与要求或偏好有关。 但是,我们建议使用特定于平台的相关命令启动 (,因为它大大简化了) 体验,然后在需要更大的控制时使用常规用途 release 命令。

注意

客户端只能发现和下载部署中的 50 个最新版本。

发布汇报 (常规)

appcenter codepush release -a <ownerName>/<appName> -c <updateContentsPath> -t <targetBinaryVersion> -d <deploymentName>

[-t|--target-binary-version <version>]
[-с|--update-contents-path <updateContentsPath>]
[-r|--rollout <rolloutPercentage>]
[--disable-duplicate-release-error]
[-k|--private-key-path <privateKeyPath>]
[-m|--mandatory]
[-x|--disabled]
[--description <description>]
[-d|--deployment-name <deploymentName>]
[-a|--app <ownerName>/<appName>]
[--disable-telemetry]
[-v|--version]

应用名称参数

此参数指定要为其发布此更新的 App Center 应用的名称。 如果要查找它,可以运行 appcenter apps list 命令来查看应用列表。

更新内容参数

此参数指定要发布的已更新应用代码和资产的位置。 例如,可以提供单个文件 (、React Native应用) 的 JS 捆绑包,或目录路径 (例如 /platforms/ios/www Cordova 应用的文件夹) 。 无需压缩多个文件或目录来部署这些更改,因为 CLI 会自动为你压缩这些更改。

请务必指定路径引用特定于平台的、已准备/捆绑的应用版本。 下表概述了在发布之前应运行的命令,以及以后可以使用 updateContentsPath 参数引用的位置:

平台 准备命令 相对于项目根) 的包路径 (
Cordova (Android) cordova prepare android ./platforms/android/assets/www 目录
Cordova (iOS) cordova prepare ios ./platforms/ios/www 目录
React Native wo/assets (Android) react-native bundle --platform android --entry-file <entryFile> --bundle-output <bundleOutput> --dev false 选项的值 --bundle-output
React Native android) (资产 react-native bundle --platform android --entry-file <entryFile> --bundle-output <releaseFolder>/<bundleOutput> --assets-dest <releaseFolder> --dev false --assets-dest选项的值,它应表示包含应用资产和 JS 捆绑包的新创建的目录
React Native wo/assets (iOS) react-native bundle --platform ios --entry-file <entryFile> --bundle-output <bundleOutput> --dev false 选项的值--bundle-output
React Native iOS) (资产 react-native bundle --platform ios --entry-file <entryFile> --bundle-output <releaseFolder>/<bundleOutput> --assets-dest <releaseFolder> --dev false --assets-dest选项的值,它应表示包含应用资产和 JS 捆绑包的新创建的目录

目标二进制版本参数

此参数指定要为其发布更新的应用程序的存储/二进制版本,以便只有运行该版本的用户才能收到更新,而运行较旧或更新版本的应用二进制文件的用户不会收到更新。 由于以下原因,它很有用:

  1. 如果用户运行的是较旧的二进制版本,则 CodePush 更新中可能存在与其运行的内容不兼容的中断性变更。

  2. 如果用户运行的是较新的二进制版本,则假定他们运行的内容较新, (并且可能与 CodePush 更新) 不兼容。

如果曾经希望更新面向多个版本的应用商店二进制文件,我们还允许将 参数指定为 semver 范围表达式。 这样,任何运行满足范围表达式的二进制文件版本的客户端设备 (semver.satisfies(version, range) 将返回 true) 获取更新。 有效 semver 范围表达式的示例如下所示:

范围表达式 谁获取更新
1.2.3 仅运行应用特定二进制版本的 1.2.3 设备
* 配置为使用 CodePush 应用中的更新的任何设备
1.2.x 运行主版本 1、次要版本 2 和应用的任何修补程序版本的设备
1.2.3 - 1.2.7 在 (非独占) 与1.2.7非独占 () 之间1.2.3运行任何二进制版本的设备
>=1.2.3 <1.2.7 在 (非独占) 与 1.2.7 (独占) 之间1.2.3运行任何二进制版本的设备
1.2 等效于 >=1.2.0 <1.3.0
~1.2.3 等效于 >=1.2.3 <1.3.0
^1.2.3 等效于 >=1.2.3 <2.0.0

注意

如果应用的 semver 表达式以特殊 shell 字符或运算符(如 、 ^或 ** *)>开头,则如果不用引号包装值,则命令可能无法正确执行,因为 shell 无法向 CLI 进程提供正确的值。 因此,调用 命令时release,最好将应用的 targetBinaryVersion 参数用双引号包装,例如 appcenter codepush release -a <ownerName>/<appName> updateContents ">1.2.3"

下表概述了 CodePush 希望更新的 semver 范围为每个应用类型满足的版本值:

平台 二进制版本的源
Cordova <widget version>config.xml 文件中的属性
React Native (Android) android.defaultConfig.versionName项目的 build.gradle 文件中的 属性
React Native (iOS) CFBundleShortVersionStringInfo.plist 文件中的键
React Native (Windows) <Identity Version>Package.appxmanifest 文件中的键

注意

如果元数据文件中的二进制版本缺少修补程序版本(例如 2.0),则会将其视为具有 的修补程序版本 02.0 -> 2.0.0即 。

部署名称参数

此参数指定要将更新发布到哪个部署。 它默认为 Staging,但当你准备好部署到 Production或你自己的某个自定义部署时,只需显式设置此参数。

提示

可以使用 或 -d设置 --deployment-name 参数。

Description 参数

此参数为部署提供可选的“更改日志”。 该值舍入到客户端,以便在检测到更新时,应用可以选择 (向最终用户显示它,例如,通过“新增功能?”对话框) 。 此字符串接受和 \t\n控制字符,以便你可以在说明中包含空格格式,以提高可读性。

提示

可以使用 设置 --description此参数。

Disabled 参数

此参数指定最终用户是否应下载更新。 如果未指定,则不会禁用更新。 相反,用户会在应用调用 sync的那一刻下载它。 如果要发布未立即可用的更新,则此参数非常有用,直到显式 修补它 并希望最终用户 (下载它,例如,公告博客文章) 上线。

提示

可以使用 或 -x设置--disabled此参数。

必需参数

此参数指定是否应将更新视为强制更新 (例如,它包含关键安全修补程序) 。 此属性被舍入到客户端,然后客户端可以决定是否以及如何强制执行它。

注意

此参数是一个“标志”,因此它不存在表示发布是可选的,而其存在则表示它是必需的。 可以 (提供值, --mandatory true 例如,) ,但是,指定 --mandatory 就足以将发布标记为必需版本。

必需属性是唯一的,因为服务器会根据需要动态修改它,以确保为最终用户维护应用版本的语义。 例如,假设你向应用发布了以下三个更新:

发布 必需?
v1
v2
v3

如果最终用户当前正在运行 v1,并且他们向服务器查询更新,它将响应 v3 (,因为这是最新的) ,但它会动态地将版本转换为必需版本,因为必需更新是在两者之间发布的。 此行为非常重要,因为 中包含的 v3 代码是增量代码,而 包含在 中 v2v2对于尚未获得 v2的任何人来说,任何强制要求继续成为v3强制性的。

如果最终用户当前正在运行 v2,并且他们向服务器查询更新,它将使用 v3进行响应,但将版本保留为可选版本。 这是因为他们已收到强制更新,因此不需要修改 的策略 v3。 此行为就是为什么我们说服务器将“动态转换”强制标志,因为就发布而言,其强制属性将始终使用释放时指定的值进行存储。 仅当响应最终用户的更新检查时,它才会根据需要进行动态更改。

仅当发布标记为 mandatory的更新时,所描述的行为才适用于你。 仅当存在如上所示的混mandatory杂更新时,服务器才会将版本mandatory更改为 optional

标记为 mandatory 的版本永远不会转换为 optional

提示

可以使用 或 设置 --mandatory 此参数 -m*

无重复发布错误参数

此参数指定如果更新与部署的最新版本相同,CLI 应生成警告而不是错误。 它对于持续集成方案很有用,在这些方案中,小修改可能会触发未更改生产代码的发布。

推出参数

重要

为了使此参数生效,最终用户必须运行 Cordova) 的版本 1.6.0-beta+ (或 1.9.0-beta+ codePush 插件React Native) (。 如果发布指定推出属性的更新,则运行旧版 Cordova 或 React Native 插件的最终用户都不符合更新条件。 在采用之前) 所述的特定于平台的 CodePush 插件 (的必要版本之前,我们不建议在应用的版本中设置推出值,因为没有人最终会收到它。

此参数将 (的用户百分比指定为介于 和 100) 之间1应有资格接收此更新的用户百分比。 如果你希望通过应用的一部分受众 ((例如,25% ) )对新版本进行“外部测试”,并获取反馈或watch异常或崩溃,然后才将其广泛提供给所有人,则此功能非常有用。 如果未设置此参数,则默认为 100%。 只需将其设置为限制接收它的用户数。

使用推出功能时,需要记住一些其他注意事项:

  1. 如果部署的最新版本为“活动”推出, (其推出属性为非 null) ,则无法发布其新更新。 需要“完成”推出 (将 属性设置为 rollout100) ,然后才能发布对部署的进一步更新。

  2. 如果回滚其最新版本为“活动”推出的部署,则会清除推出值,从而有效地“停用”推出行为

  3. mandatory与 和 description 字段不同,将发布从一个部署提升到另一个部署时,它不会传播 rollout 属性,因此,如果希望目标部署中的新版本 () 具有推出值,则必须在调用 promote 命令时显式设置它。

提示

可以使用 或 设置 --rollout 此参数 -r*

释放汇报 (React Native)

appcenter codepush release-react -a <ownerName>/<appName> -d <deploymentName> -t <targetBinaryVersion>
[-t|--target-binary-version <targetBinaryVersion>]
[-o|--output-dir]
[-s|--sourcemap-output]
[-c|--build-configuration-name <arg>]
[--plist-file-prefix]
[-p|--plist-file]
[-g|--gradle-file]
[-e|--entry-file]
[--development]
[-b|--bundle-name <bundleName>]
[-r|--rollout <rolloutPercentage>]
[--disable-duplicate-release-error]
[-k|--private-key-path <privateKeyPath>]
[-m|--mandatory]
[-x|--disabled]
[--description <description>]
[-d|--deployment-name <deploymentName>]
[-a|--app <ownerName>/<appName>]
[--disable-telemetry]
[-v|--version]

release-react命令是特定于React Native版本的“vanilla”release命令,它支持所有相同的参数 (例如 --mandatory--description) ,但通过执行以下附加任务简化了发布更新的过程:

  1. react-native bundle运行 命令以生成将发布到 CodePush 服务器的 JS 捆绑包和资产) (更新内容。 它尽可能使用合理的默认值 (例如,创建非开发版本(假设 iOS 条目文件 命名index.ios.js) ),但也公开相关 react-native bundle 参数以实现灵活性 (,例如 --sourcemap-output ,) 。

  2. 使用项目的 Info.plist (for iOS) 和 build.gradle ((适用于 Android) 文件)中指定的版本名称推断targetBinaryVersion此版本。

为了说明命令可以带来的差异release-react,以下示例演示了如何使用“vanilla”release命令生成和发布React Native应用的更新:

mkdir ./CodePush

react-native bundle --platform ios \
--entry-file index.ios.js \
--bundle-output ./CodePush/main.jsbundle \
--assets-dest ./CodePush \
--dev false

appcenter codepush release -a <ownerName>/MyApp-iOS -c ./CodePush -t 1.0.0

使用 release-react 命令实现等效的行为需要以下命令,这不太容易出错:

appcenter codepush release-react -a <ownerName>/MyApp-iOS

应用名称参数

它与 上一部分所述的参数相同。

部署名称参数

它与 上一部分所述的参数相同。

Description 参数

它与 上一部分所述的参数相同。

必需参数

它与 上一部分所述的参数相同。

无重复发布错误参数

它与 上一部分所述的参数相同。

推出参数

它与 上一部分所述的参数相同。 如果未指定,则发布将提供给所有用户。

目标二进制版本参数

它与 上一部分所述的参数相同。 如果未指定,则默认以应用的 Info.plist ((适用于 iOS) )和适用于 Android) 文件的 build.gradle (中指定的确切版本为目标。

捆绑包名称参数

此参数指定应用于生成的 JS 捆绑包的文件名。 如果未指定,则标准捆绑包名称将用于指定的平台:main.jsbundle (iOS) 、index.android.bundle (Android) ,以及 index.windows.bundle (Windows) 。

提示

可以使用 或 设置 --bundle-name 此参数 -b*

开发参数

此参数指定是否生成未优化的开发 JS 捆绑包。 如果未指定,则默认禁用 false 警告并缩小捆绑包。

提示

可以使用 设置此参数 --development*

Disabled 参数

它与 上一部分所述的参数相同。

入口文件参数

此参数指定应用的根/条目 JavaScript 文件的相对路径。 如果未指定,则默认为 iOS )index.ios.js (、Android) 的index.android.js (或 windows) 的 index.windows.bundle ((如果该文件存在),否则 index.js

提示

可以使用 或 设置 --entry-file 此参数 -e*

仅限 Android (Gradle 文件参数)

此参数指定 CLI 在尝试自动检测发布的目标二进制版本时应使用的 build.gradle 文件的相对路径。 此参数仅适用于高级方案,因为 CLI 可以在“标准”React Native项目中自动查找项目的 build.gradle 文件。 但是,如果项目的 gradle 文件位于 CLI 无法发现的任意位置,则使用此参数可以继续发布 CodePush 更新,而无需显式设置 --target-binary-version 参数。 由于 build.gradle 是必需的文件名,因此指定包含文件夹的路径或文件本身的完整路径将达到相同的效果。

appcenter codepush release-react -a <ownerName>/MyApp-Android  -g "./foo/bar/"
appcenter codepush release-react -a <ownerName>/MyApp-Android  -g "./foo/bar/build.gradle"

提示

可以使用 或 来设置 --gradle-file 此参数 -g*

plist 文件参数仅 (iOS)

此参数指定在尝试自动检测发布的目标二进制版本时 CLI 应使用的 Info.plist 文件的相对路径。 此参数仅适用于高级方案,因为 CLI 可以在“标准”React Native项目中自动查找项目的 Info.plist 文件,并且你可以使用 --plistFilePrefix 参数支持每个环境的 plist 文件 (例如 STAGING-Info.plist) 。 但是,如果项目的 plist 位于 CLI 无法发现的任意位置,则使用此参数可以继续发布 CodePush 更新,而无需显式设置 --target-binary-version 参数。

appcenter codepush release-react -a <ownerName>/MyApp-iOS -p "./foo/bar/MyFile.plist"

提示

可以使用 或 来设置 --plist-file 此参数 -p*

plist 文件前缀参数仅 (iOS)

此参数指定 CLI 在尝试自动检测发布的目标二进制版本时应使用的 Info.plist 文件的文件名前缀。 如果已 (DEV-Info.plist、STAGING-Info.plist) 创建了每个环境 plist 文件,并且想要发布 CodePush 更新而无需显式设置 --target-binary-version 参数,则这非常有用。 通过指定 , --plist-file-prefixCLI 将在以下位置查找名为 <prefix>-Info.plist的文件,而不是 Info.plist (这是) 的默认行为: ./ios./ios/<appName>。 例如,如果项目的 plist 文件不位于其中任一目录 (,则应用是一个本机 iOS 应用,) 嵌入 RN 视图,或使用完全不同的文件命名约定,请考虑使用 --plist-file 参数。

# Autodetect the target binary version of this release by looking up the
# app version within the STAGING-Info.plist file in either the ./ios or ./ios/<APP> directories.
appcenter codepush release-react -a <ownerName>/MyApp-iOS  --plist-file-prefix "STAGING"

# Tell the CLI to use your dev plist (`DEV-Info.plist`).
# The hyphen separator can be explicitly stated.
appcenter codepush release-react -a <ownerName>/MyApp-iOS --plist-file-prefix "DEV-"

源映射输出参数

此参数指定生成的 JS 捆绑包的源映射文件的相对路径。 如果未指定,则不会生成源映射。

提示

可以使用 或 来设置 --sourcemap-output 此参数 -s*

生成配置名称

生成配置的名称,该配置指定要以此版本为目标的二进制版本。 例如,“调试”或“发布” (iOS 仅) 。

注意

使用 Xcode 11 及更高版本生成时,应使用此参数来替代 Xcode 使用的默认配置。

释放汇报 (Cordova)

appcenter codepush release-cordova -a <ownerName>/<appName> -d <deploymentName> -t <targetBinaryVersion>
[-t|--target-binary-version <targetBinaryVersion>]
[--is-release-build-type]
[-b|--build]
[-r|--rollout <rolloutPercentage>]
[--disable-duplicate-release-error]
[-k|--private-key-path <privateKeyPath>]
[-m|--mandatory]
[-x|--disabled]
[--description <description>]
[-d|--deployment-name <deploymentName>]
[-a|--app <ownerName>/<appName>]
[--disable-telemetry]
[-v|--version]

release-cordova 命令是特定于 Cordova 的“vanilla” release 命令版本,它支持所有相同的参数 (例如 --mandatory--description) ,但通过执行以下附加任务简化了发布更新的过程:

  1. cordova prepare 运行 (或 phonegap prepare) 命令以 (生成将发布到 CodePush 服务器的 www 文件夹) 的更新内容

  2. 使用项目的config.xmltargetBinaryVersion 文件中指定的 版本名称推断此版本的 。

为了说明命令可以产生的差异 release-cordova ,以下示例演示了如何使用“vanilla” release 命令生成和发布 Cordova 应用的更新:

cordova prepare ios
appcenter codepush release -a <ownerName>/MyApp-iOS -c ./platforms/ios/www -t 1.0.0

使用 release-cordova 命令实现等效行为需要以下命令,这不太容易出错:

appcenter codepush release-cordova -a <ownerName>/MyApp-iOS

应用名称参数

它与 上一部分所述的参数相同。

部署名称参数

它与 上一部分所述的参数相同。

Description 参数

它与 上一部分所述的参数相同。

必需参数

它与 上一部分所述的参数相同。

没有重复的发布错误参数

它与 上一部分所述的参数相同。

推出参数

它与 上一部分所述的参数相同。 如果未指定,则发布将提供给所有用户。

目标二进制版本参数

它与 上一部分所述的参数相同。 如果未指定,则命令默认仅面向项目元数据 (Info.plist 中的指定版本(如果此更新适用于 iOS 客户端),而 android 客户端的 build.gradle) 。

Disabled 参数

它与 上一部分所述的参数相同。

版本参数

此参数指定在生成更新的 cordova prepare Web 资产时,是否要运行cordova build而不是 (这是) 的默认行为。 如果项目在生成之前或之后包括挂钩 (,例如,转译 TypeScript) ,因此,运行 CodePush cordova prepare 不足以创建和发布更新,这很有价值。 如果未指定,则默认为 false

提示

可以使用 或 来设置 --build 此参数 -b*

修补更新元数据

发布更新后,在某些情况下,你可能想要修改一个或多个元数据属性, (例如,忘记将关键 bug 修复标记为必需,想要增加更新) 的推出百分比。 可以通过运行以下命令轻松执行此操作:

appcenter codepush patch -a <ownerName>/<appName> <deploymentName> <existing-release-label>
[-r|--rollout <rolloutPercentage>]
[-d|--description <description>]
[-t|--target-binary-version <targetBinaryVersion>]
[-a|--app <ownerName>/<appName>]
[--disable-telemetry]
[-v|--version]

注意

此命令不允许修改发布的实际更新内容 (例如 Cordova www 应用) 的文件夹。 如果要响应已标识为已损坏的版本,应使用 回滚 命令立即回滚该版本,然后在必要时使用相应的修补程序发布新的更新(如果可用)。

除了 <ownerName>/<appName>deploymentName之外,所有参数都是可选的,因此可以使用此命令一次性更新单个属性或全部属性。 patch在不指定任何属性标志的情况下调用命令将导致 no-op。

# Mark the latest production release as mandatory
appcenter codepush patch -a <ownerName>/MyApp-iOS Production -m

# Increase the rollout for v23 to 50%
appcenter codepush patch -a <ownerName>/MyApp-iOS Production v23 -rollout 50%

Label 参数

例如, v23 指示要在指定部署中更新) 哪个版本 (。 如果省略,则请求的更改将应用于指定部署中的最新版本。 若要查找要更新的版本标签,可以运行 appcenter codepush deployment history 命令并引用 列 Label

必需参数

它与 上一部分所述的参数相同,可用于更新是否应将发布视为强制发布。 请注意, --mandatory--mandatory true 是等效的,但缺少此标志并不等效 --mandatory false于 。 如果省略参数,则不会更改目标版本的必需属性的值。 将此参数设置为 以 --mandatory false 显式将发布设为可选。

Description 参数

它与 上一部分所述的参数相同,可用于更新发布说明 (例如,发布时出现拼写错误,或忘记在) 添加说明。 如果省略此参数,则不会更改目标版本的 description 属性的值。

Disabled 参数

它与 上一部分所述的参数相同,可用于更新是否应禁用发布。 请注意 --disabled--disabled true 是等效的,但缺少此标志并不等效 --disabled false于 。 如果省略参数,则不会对目标版本的 disabled 属性的值进行更改。 将此参数设置为 --disabled false 以显式使发布可获取(如果以前已禁用)。

推出参数

它与 上一部分所述的参数相同,可用于增加目标版本的推出百分比。 此参数只能设置为值大于当前推出值的整数。 此外,如果要“完成”推出并让所有人都可以使用该版本,可以将此参数设置为 --rollout 100。 如果省略此参数,则不会更改目标版本的推出参数的值。

此外,如上所述,发布没有推出值的更新时,其处理等效于将推出设置为 100。 如果在未推出的情况下发布了更新,则无法通过 patch 命令更改更新的推出属性,因为这会被视为降低推出百分比。

目标二进制版本参数

它与 上一部分所述的参数相同,可用于更新 semver 范围,指示版本与哪个二进制版本兼容。 如果你在最初发布更新 (时出错,例如,你指定 1.0.0 但意在 1.1.0) ,或者你想要增加或减少版本支持的版本范围 (例如,你发现发布在) 后不起作用 1.1.2 。 如果省略此参数,则不会更改目标版本的版本属性的值。

# Add a "max binary version" to an existing release
# by scoping its eligibility to users running >= 1.0.5
appcenter codepush patch -a <ownerName>/MyApp-iOS Staging -t "1.0.0 - 1.0.5"

提升汇报

针对特定部署 ((例如, Staging) )测试更新后,想要将其提升为“下游” (例如开发>过渡、过渡->生产) ,可以使用以下命令将发布从一个部署复制到另一个部署:

appcenter codepush promote -a <ownerName>/<appName> -s <sourceDeploymentName> -d <destDeploymentName>
[-s|--source-deployment-name <sourceDeploymentName>]
[-d|--destination-deployment-name <destDeploymentName>]
[-t|--target-binary-version <targetBinaryVersion>] 
[-r|--rollout <rolloutPercentage>]
[--disable-duplicate-release-error]
[--description <description>]
[-a|--app <ownerName>/<appName>] 
[--disable-telemetry] 

命令 promote 为目标部署创建新版本,其中包括源部署的最新版本) 说明、必需和目标二进制版本 (确切的代码和元数据 。 虽然可以使用 release 命令“手动”将更新从一个环境迁移到另一个环境, promote 但该命令具有以下优点:

  1. 速度更快,因为无需重新组合要发布的发布资产,也无需记住源部署发布的说明/二进制版本。

  2. 它不太容易出错,因为升级操作可确保已在源部署中测试的确切内容 (例如, Staging) 将在目标部署 (变为活动状态, Production 例如,) 。

我们建议所有用户都利用自动创建StagingProduction的环境,并直接对 Staging执行所有版本,然后在promote进行适当的测试后从 StagingProduction 执行所有版本。

Description 参数

它与 上一部分所述的参数相同,可用于替代将用于升级版本的说明。 如果未指定,新版本将从要升级的版本继承说明。

Disabled 参数

它与 上一部分所述的参数相同,可用于替代将用于升级版本的已禁用标志的值。 如果未指定,新版本将从要升级的版本继承 disabled 属性。

必需参数

它与 上一部分所述的参数相同,可用于替代将用于升级版本的强制标志。 如果未指定,新版本将从要升级的版本继承强制属性。

没有重复的发布错误参数

它与 上一部分所述的参数相同。

推出参数

它与 上一部分所述的参数相同,可用于指定是否应仅向部分用户提供新创建的版本。 与其他发布元数据参数 (不同, description 例如,) , rollout 发布的 不会作为升级的一部分进行传递/继承,因此,如果不希望新创建的版本可供所有用户使用,则必须显式设置此参数。

目标二进制版本参数

它与 上一部分所述的参数相同,可用于替代将用于升级版本的目标二进制版本。 如果未指定,新版本将从要升级的版本继承目标二进制版本属性。

# Promote the release to production and make it
# available to all versions using that deployment
appcenter codepush promote -a <ownerName>/MyApp-iOS -s Staging -d Production -t "*"

回滚汇报

部署的发布历史记录是不可变的,因此在发布更新后无法删除更新。 但是,如果发布已损坏或包含意外功能的更新,则可以轻松地使用 rollback 命令回滚它:

appcenter codepush rollback <ownerName>/<appName> <deploymentName>
appcenter codepush rollback -a <ownerName>/MyApp-iOS Production

执行此命令会为部署创建一个新版本,其中包含与最新版本之前的版本 完全相同的代码和元数据 。 例如,假设你向应用发布了以下更新:

发布 说明 必需
v1 初始版本!
v2 添加了新功能
v3 Bug 修复

如果在rollback该部署上运行命令,则会创建包含发布内容的v2新版本 (v4) 。

发布 说明 必需
v1 初始版本!
v2 添加了新功能
v3 Bug 修复
v4 (从 v3 回滚到 v2) 添加了新功能

现在,当应用执行更新检查时,已获取v3的最终用户将“移回” 。v2 此外,任何仍在运行v2(因此从未获取 v3)的用户都不会收到更新,因为他们已经运行最新版本 (这就是更新检查除了发布标签) 之外使用包哈希的原因。

如果要将部署回滚到上一个 (以外的版本,例如 v3 ->v2) ,可以指定可选 --target-release 参数:

appcenter codepush rollback -a <ownerName>/MyApp-iOS Production --target-release v34

注意

回滚生成的版本将在命令的 deployment history 输出中批注,以帮助更轻松地识别它们。

查看发布历史记录

可以使用以下命令查看特定应用部署的 50 个最新版本的历史记录:

appcenter codepush deployment history -a <ownerName>/<appName> <deploymentName>

历史记录将显示有关每个版本的所有属性 (例如标签、强制) ,以及指示是否由于升级或回滚操作而发布了任何版本。

部署历史记录

此外,历史记录还显示每个版本的安装指标。 可以在上述命令的文档中 deployment list 查看有关如何解释指标数据的详细信息。

清除发布历史记录

可以使用以下命令清除部署的发布历史记录:

appcenter codepush deployment clear -a <ownerName>/<appName> <deploymentName>

运行此命令后,配置为使用其关联部署密钥接收更新的客户端设备将不再接收已清除的更新。 此命令不可逆,因此不应在生产部署中使用。

代码签名

它是什么?

代码签名是一种为捆绑包创建数字签名的方法,以后可以在安装前在客户端进行验证。

我们为什么需要它?

开发人员希望知道他们提供的代码是他们编写的代码。 代码签名是提供此类保证的主要机制,可帮助缓解或消除一整类中间人攻击。

它是如何工作的?

首先,开发人员生成非对称密钥对:私钥将用于签名捆绑包;用于捆绑包签名验证的公钥。 然后,CodePush CLI 在 和 release-reactrelease-cordova 命令期间release使用私钥对捆绑包进行签名。 公钥随移动应用程序一起提供。 由开发人员控制密钥的生成和管理。

在发布命令结束时,CLI 会计算捆绑包的内容哈希,并将此值放入使用私钥签名的 JWT 中。 当 CodePush 插件将捆绑包下载到设备时,它会检查 .codepushrelease 包含 JWT 的文件,并使用公钥验证 JWT 签名。 如果验证失败,则不会安装更新。

使用此功能的要求

如果计划使用此功能,请执行以下步骤:

  1. 生成新的二进制更新,包括

    • 更新了支持代码签名的 CodePush 插件
    • 配置代码推送 sdk 以使用公钥 (请参阅相关React Native SDK (iOSAndroid) 或 Cordova SDK 部分了解详细信息)
  2. 生成面向新二进制版本并指定 --private-key-path (或 -k) 参数值的新 CodePush 更新

请参阅我们的兼容性表,以确定 SDK/CLI 中是否支持代码签名功能:

CodePush SDK 支持代码签名的版本 支持的平台 所需的最低 CodePush CLI 版本
react-native-code-push 5.1.0 Android、iOS 2.1.0
cordova-plugin-code-push 1.10.0 Android、iOS 2.1.2

密钥生成

代码签名支持 PEM 编码的 RSA 密钥 (用于签名的非证书) 。 可以通过 openssl 生成它们,如下所示:

# generate private RSA key and write it to private.pem file
openssl genrsa -out private.pem

# export public key from private.pem into public.pem
openssl rsa -pubout -in private.pem -out public.pem

生成的密钥示例:

# public key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4moC3GsqF7YISFMQ0fnU
0rUF2xhxNqSGx9/GTxCynsQhR3hceroDXj3rAOTxnNkePB27uZfRDHrH3/LLoj9V
k2ghKRtfjDwXa85uDK8slSQDB9ZlD1TLQEJDZpKr1OTXY9VwbgtFaotSXoFmG3MO
RQeALCbrAgDxQ5Q2kJn6rfBuBoszfUz1qZqrlrY74Axerv1/UtTjL8uyF5r00Bxj
kvTveC2Pm5A3kq6QANktgfKWy9Ugs/4ykZF7fxfH+ukJW+iXwLACrdfzhegg/41H
5w06m30h0jqhIBZ3nbj5MN+qVbANHJMjz+fXqXx1Ovr1DfGtdKOku/BTWDxojCl1
iwIDAQAB
-----END PUBLIC KEY-----

# private key
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4moC3GsqF7YISFMQ0fnU0rUF2xhxNqSGx9/GTxCynsQhR3hc
eroDXj3rAOTxnNkePB27uZfRDHrH3/LLoj9Vk2ghKRtfjDwXa85uDK8slSQDB9Zl
D1TLQEJDZpKr1OTXY9VwbgtFaotSXoFmG3MORQeALCbrAgDxQ5Q2kJn6rfBuBosz
fUz1qZqrlrY74Axerv1/UtTjL8uyF5r00BxjkvTveC2Pm5A3kq6QANktgfKWy9Ug
s/4ykZF7fxfH+ukJW+iXwLACrdfzhegg/41H5w06m30h0jqhIBZ3nbj5MN+qVbAN
HJMjz+fXqXx1Ovr1DfGtdKOku/BTWDxojCl1iwIDAQABAoIBAQCdwf/8VS8fFlbv
DfHKXKlNp5RM9Nrtl/XRjro+nQPYXBBUHClT2gg+wiXcmalAAIhwmscSqhWe/G4I
PMRmaHrYGtYALnKE49nt5AgKDoSh5lW2QExqQkrcm08bSVcxH8J0bWPJSVE0y564
+rCKr8BhmLhWC0f0PXPeAoeCeceRKYX2oDgO8A0yZRSQUdRWiXOiQ4mUQ3IPCmBc
gD1JJNZ5kR4O904PZz5pbgyvN2t5BKOgLKq+x+8Pa8Rb21rFZKMHO8W04oKaRiGs
f4xwOBAWDOfzDKJzT5xepcPyycgjxcuvyKB2g8biWnDGGOTxDgqMX+R4XeP1aISC
h9bzfRoBAoGBAPREuPhIXRJOsIgSWAAiC5vhLZ9wWELWG95eibQm2SfpY4F0sPpE
lNQJ4yzC7J4BiApFzs1yxwwRmgpVd+wF9iMb4NSzaiTM7fju/Xv4aGhBqRXEokGF
v3QxIlbAwBqeL0rJAAadjbUTTO/u6sC80LI3bfPrn/z1hupZQGR559gjAoGBAO1J
xQ2ODVS4dSH2P+Ocd9LiUBPGyV97+MFixh6z1c2Fd3bNuiIhCxkrng45Dq0CkX84
nPUvtYxEQZoFvyB7gAm0SVlLHnJwBiq+Mp9g0UXSy6rZbjhiFkQs1W/W+Z2OIDsC
y+uXZT7No/J9VyjdrWzZJaBImO8/E4NONXWn8M95AoGACH97j+e0lTZ3ncRFm3uT
u9CRrcJSz8BzJ8FSORpA48qS06YjohFQvC+734rIgJa9DN5w22Tq19ik60cd7PAo
KACISd4UC0O147ssxmtV9oqSP1ef7XehuYEcGLiL9mEadBeaEKDalToeqxo8wIfR
GuIiySGhZ0ODdhO00coL7tECgYBargddD70udDNnICj4PbJY5928QQpxr/m3RZz6
3LTHDstBnosUQdZw7wc+3jUqjsG1gZgR5wKVMPx09N8+dZPPoZMqSZfAGelxajAE
UkaHTXBBwUfqyilCMnP6gofv2wGcK4xsYvXxEzslDxtA5b5By5Yic7vmKg+17Sxm
4yAW2QKBgDyEUzXq3Rrm7ZT720pPhuQDDSO0eHe1L1MUjTRsJ96GkIl0iqQCVgK8
A/6rFFTEeVf8L6GNMTwdtnDFz/CqIU+K1X4HLXmUY2suffWVxZ4KYqiEszCbyrdO
puayMcrx2unhKQyDYjUvD8GxHyquA+p52KDke2TkKfDxfzv0WOE1
-----END RSA PRIVATE KEY-----

发布已签名的更新

若要发布已签名的更新,应为 releaserelease-react 或 命令使用 --private-key-path (或 -k) 选项。