首页 > 解决方案 > 如何更新 UWP appxupload 包而不重建以针对多个环境

问题描述

我们正在构建一个针对 iOS 和 UWP 的 Xamarin.Forms 应用。我们要求该应用程序应作为单独安装用于暂存和生产。基本上,每个环境都有自己的设置(服务器 URL、应用程序配置等),这些设置存储在外部Configuration.json文件中。要点是,为了Configuration.json为每个环境动态选择正确的文件,不应重新构建应用程序。我们应该只构建一次应用程序,并且只更改配置。我们能够为 iOS 解决这个问题

为了支持 iOS 的动态配置,我们做了以下工作

  1. 将所有环境配置文件存储在项目中StagingConfiguration.json,如ProductionConfiguration.json.
  2. 在 iTunes 中注册单独的应用程序连接每个环境并使用其自己的捆绑 ID - 例如com.mycompany.app.staging用于登台,com.mycompany.app用于生产
  3. 构建应用程序并ipa生成文件后,我们使用fastlane新的捆绑 ID 和配置文件对应用程序进行签名,如下所示(我们使用 Azure DevOps CI/CD 管道进行构建和发布,这一步是在发布时执行命令行管道,并引用环境变量来完成它的工作)
fastlane run  resign ipa:"PATH_TO.ipa" signing_identity:"$(SigningIdentity)" bundle_id:$(BundleId) provisioning_profile:"$(provisioningProfile.secureFilePath)"
  1. 然后只需将辞职的管道上传到 AppStore
  2. 在应用程序中,我们检测应用程序的捆绑 ID 是什么,并根据该 ID 选择正确的配置文件

因此,我们也在尝试为 UWP 寻找类似的解决方案。UWP 应用的输出包就是这样的包QQPad.Mobile.UWP_0.39.0.0_x86_x64_arm_bundle.appxupload。可能,我们需要执行以下操作之一来支持我们的方案

同样,要点是能够动态选择或更改配置,而无需重新构建应用程序。UWP 是否有任何与fastlaneiOS 等效的实用程序,它也允许应用程序包操作?还是我必须手动执行此操作?如果是这样,具体如何?

标签: iosxamarin.formsuwpdevops

解决方案


经过大量试验和失败后,我设法解决了这个问题。

我已经在这里发布了进行必要转换的脚本

以下是总结基本策略的步骤

  1. 该脚本接受环境、appxupload路径、签名证书和密码
  2. 我们要做的第一件事是提取appxupload存档。为此,我们需要复制appxupload带有扩展名的文件*.zip,以便它成为Expand-Archivepowershell 实用程序的有效输入
  3. 在提取的档案中,我们有appxbundle. 对于这个和appx包,还有一个很好的工具来打包/解包它们,叫做MakeAppx。首先我们使用这个工具来解压appxbundle.
  4. 在解压后的文件夹中,我们将找到appx不同架构和规模的包文件。我们将不得不解压其中的每一个并对AppxManifest.xml文件进行必要的更改。
  5. AppxManifest.xml然后将文件作为对象打开xml,我们找到该PackageName属性,并将其替换为类似CURRENT_PACKAGE_NAME - STAGING暂存环境的内容。
  6. 之后,我们将不得不appx通过替换旧包来重新打包并签署每个包
  7. 然后,在appx重新打包所有包后,我们可以appxbundle使用MakeAppx实用程序打包。我们也必须签这个
  8. 然后我们需要appxupload使用Compress-Archivepowershell 实用程序重新创建存档。这种类型的捆绑不需要签名。
  9. YEAAAH,我们已经准备好推appxupload送到 UWP 商店了!

上述步骤是复杂的。为了读取包名称并提取 UWP 运行时中的环境名称,我必须编写几行代码

var name = Windows.ApplicationModel.Package.Current.DisplayName;
string[] parts = name.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 1) return "Production";

string environmentName = parts.Last().Trim().ToLower();

我假设如果环境说明符在“-”之后不存在,它就是生产。

其余的配置已经由您决定。我个人使用嵌入到程序集中的文件Microsoft.Extensions.Configuration作为appsettings.jsonEmbeddedResources

var configs = new ConfigurationBuilder();
var fileProvider = new EmbeddedFileProvider(typeof(Bootstrapper).Assembly, typeof(Startup).Namespace);
configs.AddJsonFile(fileProvider, "appsettings.json", false, false)
        .AddJsonFile(fileProvider, $"appsettings.{environmentName.ToLower()}.json", true, false);

更新

不幸的是我不得不放弃这个想法......为什么我认为它首先起作用,是因为我只执行了脚本并将其上传到 STAGING 航班。之后,我们的 CI 管道,一旦 QA 完成测试,就尝试将原始未修改的appxupload文件上传到生产 Alpha 测试飞行,这就是问题出现的地方,我收到了类似这样的错误

InvalidParameterValue: Appxbundles (including previously published and currently uploaded) must be uniquely identified by their full names. You have provided two packages with the full name ****_0.55.3.0_X86_ which have different contents. Please remove one of these packages, or increment current package versions to continue.

看来门户网站不能接受相同的包,具有相同的身份名称和相同的版本号。

我想我也可以更新 appx 文件名并将 STAGING 附加到所有文件是必要的(请参阅脚本,我已经用这些更改更新了它),但这也没有解决问题。

最终,我决定放弃试验,因为它花费了太多时间并采用了多次构建方法,并分别为每个环境重建应用程序,并将 STAGING 版本部署到不同的应用程序中,而是创建了完全独立的应用程序来托管暂存版本。


推荐阅读