From 44b54d5e5784017344ea4e6a1844d36dd8e9ac7f Mon Sep 17 00:00:00 2001 From: Muhammad Danish <88161975+mdanish-kh@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:40:56 +0500 Subject: [PATCH 1/5] Bump manifest schema version to 1.10.0 --- src/WingetCreateCLI/Commands/UpdateCommand.cs | 1 + .../Properties/Resources.Designer.cs | 36 ++++ src/WingetCreateCLI/Properties/Resources.resx | 12 ++ src/WingetCreateCLI/WingetCreateCLI.csproj | 2 +- src/WingetCreateCore/Common/GitHub.cs | 1 + .../Models/DefaultLocaleManifestModels.cs | 7 +- .../Models/InstallerManifestModels.cs | 92 +++++++++- .../Models/LocaleManifestModels.cs | 7 +- .../Models/SingletonManifestModels.cs | 95 ++++++++++- .../Models/VersionManifestModels.cs | 4 +- src/WingetCreateCore/WingetCreateCore.csproj | 12 +- .../WingetCreateTests/E2ETests/E2ETests.cs | 10 +- .../TestPublisher.FullJsonSingleton1_10.json | 157 ++++++++++++++++++ .../TestPublisher.FullJsonSingleton1_6.json | 8 +- .../TestPublisher.FullJsonSingleton1_7.json | 8 +- .../TestPublisher.FullJsonSingleton1_9.json | 8 +- .../TestPublisher.FullYamlSingleton1_10.yaml | 116 +++++++++++++ .../TestPublisher.FullYamlSingleton1_6.yaml | 10 +- .../TestPublisher.FullYamlSingleton1_7.yaml | 8 +- .../TestPublisher.FullYamlSingleton1_9.yaml | 10 +- .../UnitTests/UpdateCommandTests.cs | 26 +++ .../WingetCreateTests.csproj | 6 + 22 files changed, 585 insertions(+), 51 deletions(-) create mode 100644 src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_10.json create mode 100644 src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_10.yaml diff --git a/src/WingetCreateCLI/Commands/UpdateCommand.cs b/src/WingetCreateCLI/Commands/UpdateCommand.cs index 1c4926dd..b7e573de 100644 --- a/src/WingetCreateCLI/Commands/UpdateCommand.cs +++ b/src/WingetCreateCLI/Commands/UpdateCommand.cs @@ -617,6 +617,7 @@ private static Manifests ConvertSingletonToMultifileManifest(WingetCreateCore.Mo cfg.CreateMap(); cfg.CreateMap(); cfg.CreateMap(); + cfg.CreateMap(); }); var mapper = config.CreateMapper(); diff --git a/src/WingetCreateCLI/Properties/Resources.Designer.cs b/src/WingetCreateCLI/Properties/Resources.Designer.cs index 1eb6b026..17aa4667 100644 --- a/src/WingetCreateCLI/Properties/Resources.Designer.cs +++ b/src/WingetCreateCLI/Properties/Resources.Designer.cs @@ -240,6 +240,24 @@ public static string ArgumentLimitExceeded_Error { } } + /// + /// Looks up a localized string similar to Authentication information for Entra Id secured private sources. + /// + public static string Authentication_KeywordDescription { + get { + return ResourceManager.GetString("Authentication_KeywordDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type of authentication to use for Entra Id authentication. + /// + public static string AuthenticationType_KeywordDescription { + get { + return ResourceManager.GetString("AuthenticationType_KeywordDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to The package author. /// @@ -1826,6 +1844,15 @@ public static string Markets_KeywordDescription { } } + /// + /// Looks up a localized string similar to Information required for Entra Id authentication in private sources. + /// + public static string MicrosoftEntraIdAuthenticationInfo_KeywordDescription { + get { + return ResourceManager.GetString("MicrosoftEntraIdAuthenticationInfo_KeywordDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to The installer minimum operating system version. /// @@ -2690,6 +2717,15 @@ public static string ResolveMatchingConflicts_Message { } } + /// + /// Looks up a localized string similar to The resource to use for Microsoft Entra Id authentication. + /// + public static string Resource_KeywordDescription { + get { + return ResourceManager.GetString("Resource_KeywordDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to List of restricted MSIX capabilities. /// diff --git a/src/WingetCreateCLI/Properties/Resources.resx b/src/WingetCreateCLI/Properties/Resources.resx index 14180ffb..7014c6c9 100644 --- a/src/WingetCreateCLI/Properties/Resources.resx +++ b/src/WingetCreateCLI/Properties/Resources.resx @@ -1406,4 +1406,16 @@ Warning: Using this argument may result in the token being logged. Consider an a The forked repository could not be synced with the upstream commits due to a merge conflict. Resolve conflicts manually and try again. + + The type of authentication to use for Entra Id authentication + + + The resource to use for Microsoft Entra Id authentication + + + Information required for Entra Id authentication in private sources + + + Authentication information for Entra Id secured private sources + \ No newline at end of file diff --git a/src/WingetCreateCLI/WingetCreateCLI.csproj b/src/WingetCreateCLI/WingetCreateCLI.csproj index ed20a01c..d52213c5 100644 --- a/src/WingetCreateCLI/WingetCreateCLI.csproj +++ b/src/WingetCreateCLI/WingetCreateCLI.csproj @@ -5,7 +5,7 @@ net8.0-windows10.0.22000.0 WingetCreateCLI Microsoft.WingetCreateCLI - 1.9 + 1.10 x64;x86 win-x64;win-x86 true diff --git a/src/WingetCreateCore/Common/GitHub.cs b/src/WingetCreateCore/Common/GitHub.cs index 7ace29de..1321750c 100644 --- a/src/WingetCreateCore/Common/GitHub.cs +++ b/src/WingetCreateCore/Common/GitHub.cs @@ -19,6 +19,7 @@ namespace Microsoft.WingetCreateCore.Common using Microsoft.WingetCreateCore.Models.Installer; using Octokit; using Polly; + using AuthenticationType = Octokit.AuthenticationType; /// /// Provides functionality for interacting a user's GitHub account. diff --git a/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs b/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs index 86ad3080..182fa6f0 100644 --- a/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs +++ b/src/WingetCreateCore/Models/DefaultLocaleManifestModels.cs @@ -84,7 +84,8 @@ public partial class Icon /// /// The url of the hosted icon file /// - [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.StringLength(2048)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^([Hh][Tt][Tt][Pp][Ss]?)://.+$")] public string IconUrl { get; set; } @@ -132,7 +133,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.9.0 + /// A representation of a multiple-file manifest representing a default app metadata in the OWC. v1.10.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class DefaultLocaleManifest @@ -334,7 +335,7 @@ public partial class DefaultLocaleManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.9.0"; + public string ManifestVersion { get; set; } = "1.10.0"; diff --git a/src/WingetCreateCore/Models/InstallerManifestModels.cs b/src/WingetCreateCore/Models/InstallerManifestModels.cs index fb7f4a46..03aaa420 100644 --- a/src/WingetCreateCore/Models/InstallerManifestModels.cs +++ b/src/WingetCreateCore/Models/InstallerManifestModels.cs @@ -436,6 +436,39 @@ public enum RepairBehavior } + /// + /// The authentication requirement for downloading the installer. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class Authentication + { + /// + /// The authentication type + /// + [Newtonsoft.Json.JsonProperty("AuthenticationType", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public AuthenticationType AuthenticationType { get; set; } + + /// + /// The Microsoft Entra Id authentication info + /// + [Newtonsoft.Json.JsonProperty("MicrosoftEntraIdAuthenticationInfo", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public MicrosoftEntraIdAuthenticationInfo MicrosoftEntraIdAuthenticationInfo { get; set; } + + + + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class Installer { @@ -594,6 +627,9 @@ public partial class Installer [Newtonsoft.Json.JsonProperty("ArchiveBinariesDependOnPath", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? ArchiveBinariesDependOnPath { get; set; } + [Newtonsoft.Json.JsonProperty("Authentication", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Authentication Authentication { get; set; } + private System.Collections.Generic.IDictionary _additionalProperties; @@ -608,7 +644,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a single-file manifest representing an app installers in the OWC. v1.9.0 + /// A representation of a single-file manifest representing an app installers in the OWC. v1.10.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class InstallerManifest @@ -755,6 +791,9 @@ public partial class InstallerManifest [Newtonsoft.Json.JsonProperty("ArchiveBinariesDependOnPath", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? ArchiveBinariesDependOnPath { get; set; } + [Newtonsoft.Json.JsonProperty("Authentication", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Authentication Authentication { get; set; } + [Newtonsoft.Json.JsonProperty("Installers", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required] [System.ComponentModel.DataAnnotations.MinLength(1)] @@ -774,7 +813,7 @@ public partial class InstallerManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.9.0"; + public string ManifestVersion { get; set; } = "1.10.0"; @@ -860,6 +899,54 @@ public partial class Files + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public enum AuthenticationType + { + + [System.Runtime.Serialization.EnumMember(Value = @"none")] + None = 0, + + + [System.Runtime.Serialization.EnumMember(Value = @"microsoftEntraId")] + MicrosoftEntraId = 1, + + + [System.Runtime.Serialization.EnumMember(Value = @"microsoftEntraIdForAzureBlobStorage")] + MicrosoftEntraIdForAzureBlobStorage = 2, + + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class MicrosoftEntraIdAuthenticationInfo + { + /// + /// The resource value for Microsoft Entra Id authentication. + /// + [Newtonsoft.Json.JsonProperty("Resource", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.StringLength(512, MinimumLength = 1)] + public string Resource { get; set; } + + /// + /// The scope value for Microsoft Entra Id authentication. + /// + [Newtonsoft.Json.JsonProperty("Scope", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.StringLength(512, MinimumLength = 1)] + public string Scope { get; set; } + + + private System.Collections.Generic.IDictionary _additionalProperties; [Newtonsoft.Json.JsonExtensionData] @@ -945,6 +1032,7 @@ public partial class ExpectedReturnCode public long InstallerReturnCode { get; set; } [Newtonsoft.Json.JsonProperty("ReturnResponse", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public ExpectedReturnCodeReturnResponse ReturnResponse { get; set; } diff --git a/src/WingetCreateCore/Models/LocaleManifestModels.cs b/src/WingetCreateCore/Models/LocaleManifestModels.cs index 896f5aab..c7fd7dde 100644 --- a/src/WingetCreateCore/Models/LocaleManifestModels.cs +++ b/src/WingetCreateCore/Models/LocaleManifestModels.cs @@ -84,7 +84,8 @@ public partial class Icon /// /// The url of the hosted icon file /// - [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.StringLength(2048)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^([Hh][Tt][Tt][Pp][Ss]?)://.+$")] public string IconUrl { get; set; } @@ -132,7 +133,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.9.0 + /// A representation of a multiple-file manifest representing app metadata in other locale in the OWC. v1.10.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class LocaleManifest @@ -323,7 +324,7 @@ public partial class LocaleManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.9.0"; + public string ManifestVersion { get; set; } = "1.10.0"; diff --git a/src/WingetCreateCore/Models/SingletonManifestModels.cs b/src/WingetCreateCore/Models/SingletonManifestModels.cs index 9b11053f..1b6ee467 100644 --- a/src/WingetCreateCore/Models/SingletonManifestModels.cs +++ b/src/WingetCreateCore/Models/SingletonManifestModels.cs @@ -84,7 +84,8 @@ public partial class Icon /// /// The url of the hosted icon file /// - [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [Newtonsoft.Json.JsonProperty("IconUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.StringLength(2048)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^([Hh][Tt][Tt][Pp][Ss]?)://.+$")] public string IconUrl { get; set; } @@ -558,6 +559,39 @@ public enum RepairBehavior } + /// + /// The authentication requirement for downloading the installer. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class Authentication + { + /// + /// The authentication type + /// + [Newtonsoft.Json.JsonProperty("AuthenticationType", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + public AuthenticationType AuthenticationType { get; set; } + + /// + /// The Microsoft Entra Id authentication info + /// + [Newtonsoft.Json.JsonProperty("MicrosoftEntraIdAuthenticationInfo", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public MicrosoftEntraIdAuthenticationInfo MicrosoftEntraIdAuthenticationInfo { get; set; } + + + + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class Installer { @@ -716,6 +750,9 @@ public partial class Installer [Newtonsoft.Json.JsonProperty("ArchiveBinariesDependOnPath", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? ArchiveBinariesDependOnPath { get; set; } + [Newtonsoft.Json.JsonProperty("Authentication", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Authentication Authentication { get; set; } + private System.Collections.Generic.IDictionary _additionalProperties; @@ -730,7 +767,7 @@ public System.Collections.Generic.IDictionary AdditionalProperti } /// - /// A representation of a single-file manifest representing an app in the OWC. v1.9.0 + /// A representation of a single-file manifest representing an app in the OWC. v1.10.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class SingletonManifest @@ -1039,6 +1076,9 @@ public partial class SingletonManifest [Newtonsoft.Json.JsonProperty("ArchiveBinariesDependOnPath", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool? ArchiveBinariesDependOnPath { get; set; } + [Newtonsoft.Json.JsonProperty("Authentication", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Authentication Authentication { get; set; } + [Newtonsoft.Json.JsonProperty("Installers", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required] [System.ComponentModel.DataAnnotations.MinLength(1)] @@ -1058,7 +1098,7 @@ public partial class SingletonManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.9.0"; + public string ManifestVersion { get; set; } = "1.10.0"; @@ -1250,6 +1290,54 @@ public partial class Files + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public enum AuthenticationType + { + + [System.Runtime.Serialization.EnumMember(Value = @"none")] + None = 0, + + + [System.Runtime.Serialization.EnumMember(Value = @"microsoftEntraId")] + MicrosoftEntraId = 1, + + + [System.Runtime.Serialization.EnumMember(Value = @"microsoftEntraIdForAzureBlobStorage")] + MicrosoftEntraIdForAzureBlobStorage = 2, + + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class MicrosoftEntraIdAuthenticationInfo + { + /// + /// The resource value for Microsoft Entra Id authentication. + /// + [Newtonsoft.Json.JsonProperty("Resource", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.StringLength(512, MinimumLength = 1)] + public string Resource { get; set; } + + /// + /// The scope value for Microsoft Entra Id authentication. + /// + [Newtonsoft.Json.JsonProperty("Scope", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.StringLength(512, MinimumLength = 1)] + public string Scope { get; set; } + + + private System.Collections.Generic.IDictionary _additionalProperties; [Newtonsoft.Json.JsonExtensionData] @@ -1335,6 +1423,7 @@ public partial class ExpectedReturnCode public long InstallerReturnCode { get; set; } [Newtonsoft.Json.JsonProperty("ReturnResponse", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public ExpectedReturnCodeReturnResponse ReturnResponse { get; set; } diff --git a/src/WingetCreateCore/Models/VersionManifestModels.cs b/src/WingetCreateCore/Models/VersionManifestModels.cs index 91b3af74..4a4ea057 100644 --- a/src/WingetCreateCore/Models/VersionManifestModels.cs +++ b/src/WingetCreateCore/Models/VersionManifestModels.cs @@ -10,7 +10,7 @@ namespace Microsoft.WingetCreateCore.Models.Version #pragma warning disable // Disable all warnings /// - /// A representation of a multi-file manifest representing an app version in the OWC. v1.9.0 + /// A representation of a multi-file manifest representing an app version in the OWC. v1.10.0 /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "11.0.0.0 (Newtonsoft.Json v13.0.0.0)")] public partial class VersionManifest @@ -55,7 +55,7 @@ public partial class VersionManifest [Newtonsoft.Json.JsonProperty("ManifestVersion", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] [System.ComponentModel.DataAnnotations.RegularExpression(@"^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){2}$")] - public string ManifestVersion { get; set; } = "1.9.0"; + public string ManifestVersion { get; set; } = "1.10.0"; diff --git a/src/WingetCreateCore/WingetCreateCore.csproj b/src/WingetCreateCore/WingetCreateCore.csproj index f4df191a..511ec1dc 100644 --- a/src/WingetCreateCore/WingetCreateCore.csproj +++ b/src/WingetCreateCore/WingetCreateCore.csproj @@ -19,7 +19,7 @@ - + @@ -48,11 +48,11 @@ - - - - - + + + + + diff --git a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs index dce082c0..7be668b8 100644 --- a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs +++ b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs @@ -55,11 +55,11 @@ public void Setup() [TestCase(TestConstants.YamlConstants.TestZipPackageIdentifier, TestConstants.YamlConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.YamlManifestFormat)] // JSON E2E Tests - [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestPortablePackageIdentifier, TestConstants.JsonConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestZipPackageIdentifier, TestConstants.JsonConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.JsonManifestFormat)] + [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] + [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] + [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] + [TestCase(TestConstants.JsonConstants.TestPortablePackageIdentifier, TestConstants.JsonConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] + [TestCase(TestConstants.JsonConstants.TestZipPackageIdentifier, TestConstants.JsonConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] public async Task SubmitAndUpdateInstaller(string packageId, string manifestName, string installerName, ManifestFormat format) { diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_10.json b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_10.json new file mode 100644 index 00000000..0a8c8221 --- /dev/null +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_10.json @@ -0,0 +1,157 @@ +{ + "PackageIdentifier": "TestPublisher.FullJsonSingleton1_10", + "PackageVersion": "0.1.2.3", + "PackageLocale": "en-US", + "DefaultLocale": "en-US", + "Publisher": "TestPublisher", + "PublisherUrl": "https://fakeTestUrl.com", + "PublisherSupportUrl": "https://fakeTestUrl.com", + "PrivacyUrl": "https://fakeTestUrl.com", + "Author": "fakeAuthor", + "PackageName": "Full Singleton 1.10 Test", + "PackageUrl": "https://fakeTestUrl.com", + "License": "MIT", + "LicenseUrl": "https://fakeTestUrl.com", + "Copyright": "fakeCopyright", + "CopyrightUrl": "https://fakeTestUrl.com", + "ShortDescription": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", + "Description": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", + "Moniker": "testMoniker", + "Tags": [ + "testSingleton" + ], + "Agreements": [ + { + "AgreementLabel": "fakeAgreementLabel", + "AgreementUrl": "https://fakeTestUrl.com", + "Agreement": "fakeAgreementContent" + } + ], + "ReleaseNotes": "fakeReleaseNotes", + "ReleaseNotesUrl": "https://fakeTestUrl.com", + "PurchaseUrl": "https://fakeTestUrl.com", + "InstallationNotes": "fakeInstallationNotes", + "Documentations": [ + { + "DocumentLabel": "fakeDocumentLabel" + }, + { + "DocumentUrl": "fakeDocumentUrl" + } + ], + "Icons": [ + { + "IconUrl": "https://fakeTestIcon", + "IconFileType": "png", + "IconResolution": "32x32", + "IconTheme": "light", + "IconSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321" + } + ], + "Installers": [ + { + "MinimumOSVersion": "10.0.0.0", + "Architecture": "x64", + "InstallerUrl": "https://fakedomain.com/WingetCreateTestExeInstaller.exe", + "InstallerType": "exe", + "InstallerSha256": "A7803233EEDB6A4B59B3024CCF9292A6FFFB94507DC998AA67C5B745D197A5DC", + "ProductCode": "FakeProductCode", + "PackageFamilyName": "FakePackageFamilyName", + "InstallModes": [ + "silent" + ], + "InstallerSwitches": { + "Silent": "/s", + "Upgrade": "/u", + "Repair": "/r" + }, + "InstallerSuccessCodes": [ + 1 + ], + "ExpectedReturnCodes": [ + { + "InstallerReturnCode": 123, + "ReturnResponse": "alreadyInstalled", + "ReturnResponseUrl": "https://fakeTestUrl.com" + } + ], + "UpgradeBehavior": "install", + "Commands": [ + "fakeCommand" + ], + "Protocols": [ + "fakeProtocol" + ], + "FileExtensions": [ + ".exe" + ], + "Dependencies": { + "WindowsFeatures": [ + "fakeValue" + ], + "WindowsLibraries": [ + "fakeValue" + ], + "PackageDependencies": [ + { + "MinimumVersion": "10.0.0.0" + } + ], + "ExternalDependencies": [ + "fakeValue" + ] + }, + "Markets": { + "AllowedMarkets": [ + "fakeAllowedMarket" + ], + "ExcludedMarkets": [ + "fakeExcludedMarket" + ] + }, + "InstallerAbortsTerminal": true, + "InstallLocationRequired": true, + "RequireExplicitUpgrade": true, + "UnsupportedOSArchitectures": [ + "arm64" + ], + "AppsAndFeaturesEntries": [ + { + "DisplayName": "testName", + "Publisher": "testPublisher", + "DisplayVersion": "testVersion", + "UpgradeCode": "fakeProductCode" + } + ], + "ElevationRequirement": "elevationRequired", + "ReleaseDate": "2022-01-01", + "DisplayInstallWarnings": true, + "UnsupportedArguments": [ + "log", + "location" + ], + "NestedInstallerFiles": [ + { + "RelativeFilePath": "RelativeFilePath", + "PortableCommandAlias": "PortableCommandAlias" + } + ], + "InstallationMetadata": { + "DefaultInstallLocation": "%ProgramFiles%\\TestApp", + "Files": [ + { + "RelativeFilePath": "main.exe", + "FileSha256": "69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82", + "FileType": "launch", + "InvocationParameter": "/arg" + } + ] + }, + "DownloadCommandProhibited": true, + "RepairBehavior": "modify", + "ArchiveBinariesDependOnPath": true + } + ], + "ManifestType": "singleton", + "ManifestVersion": "1.10.0" +} \ No newline at end of file diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_6.json b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_6.json index e0ba9af8..082d3be8 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_6.json +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_6.json @@ -1,5 +1,5 @@ { - "PackageIdentifier": "TestPublisher.FullJsonSingleton1_5", + "PackageIdentifier": "TestPublisher.FullJsonSingleton1_6", "PackageVersion": "0.1.2.3", "PackageLocale": "en-US", "DefaultLocale": "en-US", @@ -8,14 +8,14 @@ "PublisherSupportUrl": "https://fakeTestUrl.com", "PrivacyUrl": "https://fakeTestUrl.com", "Author": "fakeAuthor", - "PackageName": "Full Singleton 1.5 Test", + "PackageName": "Full Singleton 1.6 Test", "PackageUrl": "https://fakeTestUrl.com", "License": "MIT", "LicenseUrl": "https://fakeTestUrl.com", "Copyright": "fakeCopyright", "CopyrightUrl": "https://fakeTestUrl.com", - "ShortDescription": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated.", - "Description": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri", + "ShortDescription": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", + "Description": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", "Moniker": "testMoniker", "Tags": [ "testSingleton" diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_7.json b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_7.json index 7e5cdd63..14731bc3 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_7.json +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_7.json @@ -1,5 +1,5 @@ { - "PackageIdentifier": "TestPublisher.FullJsonSingleton1_5", + "PackageIdentifier": "TestPublisher.FullJsonSingleton1_7", "PackageVersion": "0.1.2.3", "PackageLocale": "en-US", "DefaultLocale": "en-US", @@ -8,14 +8,14 @@ "PublisherSupportUrl": "https://fakeTestUrl.com", "PrivacyUrl": "https://fakeTestUrl.com", "Author": "fakeAuthor", - "PackageName": "Full Singleton 1.5 Test", + "PackageName": "Full Singleton 1.7 Test", "PackageUrl": "https://fakeTestUrl.com", "License": "MIT", "LicenseUrl": "https://fakeTestUrl.com", "Copyright": "fakeCopyright", "CopyrightUrl": "https://fakeTestUrl.com", - "ShortDescription": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated.", - "Description": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri", + "ShortDescription": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", + "Description": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", "Moniker": "testMoniker", "Tags": [ "testSingleton" diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_9.json b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_9.json index c47e4980..8e3e4f89 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_9.json +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullJsonSingleton1_9.json @@ -1,5 +1,5 @@ { - "PackageIdentifier": "TestPublisher.FullJsonSingleton1_5", + "PackageIdentifier": "TestPublisher.FullJsonSingleton1_9", "PackageVersion": "0.1.2.3", "PackageLocale": "en-US", "DefaultLocale": "en-US", @@ -8,14 +8,14 @@ "PublisherSupportUrl": "https://fakeTestUrl.com", "PrivacyUrl": "https://fakeTestUrl.com", "Author": "fakeAuthor", - "PackageName": "Full Singleton 1.5 Test", + "PackageName": "Full Singleton 1.9 Test", "PackageUrl": "https://fakeTestUrl.com", "License": "MIT", "LicenseUrl": "https://fakeTestUrl.com", "Copyright": "fakeCopyright", "CopyrightUrl": "https://fakeTestUrl.com", - "ShortDescription": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated.", - "Description": "A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri", + "ShortDescription": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", + "Description": "A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated.", "Moniker": "testMoniker", "Tags": [ "testSingleton" diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_10.yaml b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_10.yaml new file mode 100644 index 00000000..cc69e059 --- /dev/null +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_10.yaml @@ -0,0 +1,116 @@ +PackageIdentifier: TestPublisher.FullYamlSingleton1_10 +PackageVersion: 0.1.2.3 +PackageLocale: en-US +DefaultLocale: en-US +Publisher: TestPublisher +PublisherUrl: https://fakeTestUrl.com +PublisherSupportUrl: https://fakeTestUrl.com +PrivacyUrl: https://fakeTestUrl.com +Author: fakeAuthor +PackageName: Full Singleton 1.10 Test +PackageUrl: https://fakeTestUrl.com +License: MIT +LicenseUrl: https://fakeTestUrl.com +Copyright: fakeCopyright +CopyrightUrl: https://fakeTestUrl.com +ShortDescription: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated. +Description: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated. +Moniker: testMoniker +Tags: +- testSingleton +Agreements: +- AgreementLabel: fakeAgreementLabel + AgreementUrl: https://fakeTestUrl.com + Agreement: fakeAgreementContent +ReleaseNotes: fakeReleaseNotes +ReleaseNotesUrl: https://fakeTestUrl.com +PurchaseUrl: https://fakeTestUrl.com +InstallationNotes: fakeInstallationNotes +Documentations: +- DocumentLabel: fakeDocumentLabel +- DocumentUrl: fakeDocumentUrl +Icons: + - IconUrl: https://fakeTestIcon + IconFileType: png + IconResolution: 32x32 + IconTheme: light + IconSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8321 +Installers: +- MinimumOSVersion: 10.0.0.0 + Architecture: x64 + InstallerUrl: https://fakedomain.com/WingetCreateTestExeInstaller.exe + InstallerType: exe + InstallerSha256: A7803233EEDB6A4B59B3024CCF9292A6FFFB94507DC998AA67C5B745D197A5DC + ProductCode: FakeProductCode + PackageFamilyName: FakePackageFamilyName + InstallModes: + - silent + InstallerSwitches: + Silent: /s + Upgrade: /u + Repair: /r + InstallerSuccessCodes: + - 1 + ExpectedReturnCodes: + - InstallerReturnCode: 123 + ReturnResponse: alreadyInstalled + ReturnResponseUrl: https://fakeTestUrl.com + UpgradeBehavior: install + Commands: + - fakeCommand + Protocols: + - fakeProtocol + FileExtensions: + - .exe + Dependencies: + WindowsFeatures: + - fakeValue + WindowsLibraries: + - fakeValue + PackageDependencies: + - MinimumVersion: 10.0.0.0 + ExternalDependencies: + - fakeValue + Markets: + AllowedMarkets: + - fakeAllowedMarket + ExcludedMarkets: + - fakeExcludedMarket + InstallerAbortsTerminal: true + InstallLocationRequired: true + RequireExplicitUpgrade: true + UnsupportedOSArchitectures: + - arm64 + AppsAndFeaturesEntries: + - DisplayName: testName + Publisher: testPublisher + DisplayVersion: testVersion + UpgradeCode: fakeProductCode + ElevationRequirement: elevationRequired + ReleaseDate: 1-1-2022 + DisplayInstallWarnings: true + UnsupportedArguments: + - log + - location + NestedInstallerFiles: + - RelativeFilePath: RelativeFilePath + PortableCommandAlias: PortableCommandAlias + InstallationMetadata: + DefaultInstallLocation: "%ProgramFiles%\\TestApp" + Files: + - RelativeFilePath: "main.exe" + FileSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82 + FileType: launch + InvocationParameter: "/arg" + DownloadCommandProhibited: true + RepairBehavior: modify + ArchiveBinariesDependOnPath: true +# `winget validate` fails if this field is used as it requires verified publisher feature +# Uncomment when verified publisher feature is implemented +# Authentication: +# AuthenticationType: microsoftEntraId +# MicrosoftEntraIdAuthenticationInfo: +# Scope: DefaultScope +# Resource: DefaultResource +ManifestType: singleton +ManifestVersion: 1.10.0 \ No newline at end of file diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_6.yaml b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_6.yaml index 9250966d..77a0f82e 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_6.yaml +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_6.yaml @@ -1,4 +1,4 @@ -PackageIdentifier: TestPublisher.FullYamlSingleton1_5 +PackageIdentifier: TestPublisher.FullYamlSingleton1_6 PackageVersion: 0.1.2.3 PackageLocale: en-US DefaultLocale: en-US @@ -7,14 +7,14 @@ PublisherUrl: https://fakeTestUrl.com PublisherSupportUrl: https://fakeTestUrl.com PrivacyUrl: https://fakeTestUrl.com Author: fakeAuthor -PackageName: Full Singleton 1.5 Test +PackageName: Full Singleton 1.6 Test PackageUrl: https://fakeTestUrl.com License: MIT LicenseUrl: https://fakeTestUrl.com Copyright: fakeCopyright CopyrightUrl: https://fakeTestUrl.com -ShortDescription: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated. -Description: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri +ShortDescription: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. +Description: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. Moniker: testMoniker Tags: - testSingleton @@ -93,7 +93,7 @@ Installers: - location NestedInstallerFiles: - RelativeFilePath: RelativeFilePath - PortableCommandAlias: PortableCommandAlias + PortableCommandAlias: PortableCommandAlias InstallationMetadata: DefaultInstallLocation: "%ProgramFiles%\\TestApp" Files: diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_7.yaml b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_7.yaml index b4c4e845..701b3ba6 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_7.yaml +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_7.yaml @@ -1,4 +1,4 @@ -PackageIdentifier: TestPublisher.FullYamlSingleton1_5 +PackageIdentifier: TestPublisher.FullYamlSingleton1_7 PackageVersion: 0.1.2.3 PackageLocale: en-US DefaultLocale: en-US @@ -7,14 +7,14 @@ PublisherUrl: https://fakeTestUrl.com PublisherSupportUrl: https://fakeTestUrl.com PrivacyUrl: https://fakeTestUrl.com Author: fakeAuthor -PackageName: Full Singleton 1.5 Test +PackageName: Full Singleton 1.7 Test PackageUrl: https://fakeTestUrl.com License: MIT LicenseUrl: https://fakeTestUrl.com Copyright: fakeCopyright CopyrightUrl: https://fakeTestUrl.com -ShortDescription: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated. -Description: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri +ShortDescription: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. +Description: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. Moniker: testMoniker Tags: - testSingleton diff --git a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_9.yaml b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_9.yaml index c85c8d18..21f09780 100644 --- a/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_9.yaml +++ b/src/WingetCreateTests/WingetCreateTests/Resources/TestPublisher.FullYamlSingleton1_9.yaml @@ -1,4 +1,4 @@ -PackageIdentifier: TestPublisher.FullYamlSingleton1_5 +PackageIdentifier: TestPublisher.FullYamlSingleton1_9 PackageVersion: 0.1.2.3 PackageLocale: en-US DefaultLocale: en-US @@ -7,14 +7,14 @@ PublisherUrl: https://fakeTestUrl.com PublisherSupportUrl: https://fakeTestUrl.com PrivacyUrl: https://fakeTestUrl.com Author: fakeAuthor -PackageName: Full Singleton 1.5 Test +PackageName: Full Singleton 1.9 Test PackageUrl: https://fakeTestUrl.com License: MIT LicenseUrl: https://fakeTestUrl.com Copyright: fakeCopyright CopyrightUrl: https://fakeTestUrl.com -ShortDescription: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deserialized and updated. -Description: A manifest used to verify that all fields from a full 1.1 singleton manifest can be deseri +ShortDescription: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. +Description: A manifest used to verify that all fields from a full singleton manifest can be deserialized and updated. Moniker: testMoniker Tags: - testSingleton @@ -94,7 +94,7 @@ Installers: - location NestedInstallerFiles: - RelativeFilePath: RelativeFilePath - PortableCommandAlias: PortableCommandAlias + PortableCommandAlias: PortableCommandAlias InstallationMetadata: DefaultInstallLocation: "%ProgramFiles%\\TestApp" Files: diff --git a/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs b/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs index 9f516cf2..d7857d8e 100644 --- a/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs +++ b/src/WingetCreateTests/WingetCreateTests/UnitTests/UpdateCommandTests.cs @@ -979,6 +979,19 @@ public async Task UpdateFullYamlSingletonVersion1_9() ClassicAssert.IsNotNull(updatedManifests, "Command should have succeeded"); } + /// + /// Ensures that all fields from the YAML Singleton v1.10 manifest can be deserialized and updated correctly. + /// + /// A representing the result of the asynchronous operation. + [Test] + public async Task UpdateFullYamlSingletonVersion1_10() + { + TestUtils.InitializeMockDownloads(TestConstants.TestExeInstaller); + (UpdateCommand command, var initialManifestContent) = GetUpdateCommandAndManifestData("TestPublisher.FullYamlSingleton1_10", null, this.tempPath, null); + var updatedManifests = await RunUpdateCommand(command, initialManifestContent); + ClassicAssert.IsNotNull(updatedManifests, "Command should have succeeded"); + } + /// /// Ensures that all fields from the JSON Singleton v1.1 manifest can be deserialized and updated correctly. /// @@ -1070,6 +1083,19 @@ public async Task UpdateFullJsonSingletonVersion1_9() ClassicAssert.IsNotNull(updatedManifests, "Command should have succeeded"); } + /// + /// Ensures that all fields from the Singleton JSON v1.10 manifest can be deserialized and updated correctly. + /// + /// A representing the result of the asynchronous operation. + [Test] + public async Task UpdateFullJsonSingletonVersion1_10() + { + TestUtils.InitializeMockDownloads(TestConstants.TestExeInstaller); + (UpdateCommand command, var initialManifestContent) = GetUpdateCommandAndManifestData("TestPublisher.FullJsonSingleton1_10", null, this.tempPath, null, manifestFormat: ManifestFormat.Json); + var updatedManifests = await RunUpdateCommand(command, initialManifestContent); + ClassicAssert.IsNotNull(updatedManifests, "Command should have succeeded"); + } + /// /// Ensures that version specific fields are reset after an update when using YAML manifests. /// diff --git a/src/WingetCreateTests/WingetCreateTests/WingetCreateTests.csproj b/src/WingetCreateTests/WingetCreateTests/WingetCreateTests.csproj index 80a5e1d6..107fff59 100644 --- a/src/WingetCreateTests/WingetCreateTests/WingetCreateTests.csproj +++ b/src/WingetCreateTests/WingetCreateTests/WingetCreateTests.csproj @@ -63,6 +63,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest From a8df559750ee0e497e674abe9628343d2888bd3a Mon Sep 17 00:00:00 2001 From: Muhammad Danish <88161975+mdanish-kh@users.noreply.github.com> Date: Sat, 29 Mar 2025 03:51:58 +0500 Subject: [PATCH 2/5] update comment --- src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs index 7be668b8..f9d74b04 100644 --- a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs +++ b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs @@ -54,7 +54,7 @@ public void Setup() [TestCase(TestConstants.YamlConstants.TestPortablePackageIdentifier, TestConstants.YamlConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.YamlManifestFormat)] [TestCase(TestConstants.YamlConstants.TestZipPackageIdentifier, TestConstants.YamlConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.YamlManifestFormat)] - // JSON E2E Tests + // JSON E2E Tests. Skipped because of https://github.com/microsoft/winget-cli/issues/5336 [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] From f48d8b7f72402339bbab2fa9bb72d0bba04e4c78 Mon Sep 17 00:00:00 2001 From: Muhammad Danish <88161975+mdanish-kh@users.noreply.github.com> Date: Tue, 1 Apr 2025 20:09:21 +0500 Subject: [PATCH 3/5] skip validation for non-yaml format --- src/WingetCreateCLI/Commands/BaseCommand.cs | 16 ++++++-- src/WingetCreateCLI/Commands/NewCommand.cs | 2 +- .../Commands/NewLocaleCommand.cs | 4 +- src/WingetCreateCLI/Commands/SubmitCommand.cs | 4 +- src/WingetCreateCLI/Commands/UpdateCommand.cs | 10 ++--- .../Commands/UpdateLocaleCommand.cs | 4 +- .../Properties/Resources.Designer.cs | 9 +++++ src/WingetCreateCLI/Properties/Resources.resx | 3 ++ .../WingetCreateTests/E2ETests/E2ETests.cs | 39 ++++++++++++++----- 9 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/WingetCreateCLI/Commands/BaseCommand.cs b/src/WingetCreateCLI/Commands/BaseCommand.cs index 61d3875e..9d99adeb 100644 --- a/src/WingetCreateCLI/Commands/BaseCommand.cs +++ b/src/WingetCreateCLI/Commands/BaseCommand.cs @@ -216,8 +216,9 @@ protected static string SaveManifestDirToLocalPath( /// Saves the manifests to a randomly generated directory in the %TEMP% folder and validates them, printing the results to console. /// /// Manifests object model. + /// Format of the serialized manifest. /// A boolean value indicating whether validation of the manifests was successful. - protected static bool ValidateManifestsInTempDir(Manifests manifests) + protected static bool ValidateManifestsInTempDir(Manifests manifests, ManifestFormat format) { string versionManifestFileName = Manifests.GetFileName(manifests.VersionManifest, Extension); string installerManifestFileName = Manifests.GetFileName(manifests.InstallerManifest, Extension); @@ -236,7 +237,7 @@ protected static bool ValidateManifestsInTempDir(Manifests manifests) File.WriteAllText(Path.Combine(randomDirPath, localeManifestFileName), localeManifest.ToManifestString()); } - bool result = ValidateManifest(randomDirPath); + bool result = ValidateManifest(randomDirPath, format); Directory.Delete(randomDirPath, true); return result; } @@ -382,9 +383,18 @@ protected static async Task DownloadPackageFile(string installerUrl) /// Utilizes WingetUtil to validate a specified manifest. /// /// Path to the manifest file to be validated. + /// Format of the manifest file. " /// Bool indicating the validity of the manifest file. - protected static bool ValidateManifest(string manifestPath) + protected static bool ValidateManifest(string manifestPath, ManifestFormat format) { + bool skipValidation = format != ManifestFormat.Yaml; + + if (skipValidation) + { + Logger.WarnLocalized(nameof(Resources.SkippingManifestValidation_Message)); + return true; + } + (bool success, string message) = WinGetUtil.ValidateManifest(manifestPath); if (success) diff --git a/src/WingetCreateCLI/Commands/NewCommand.cs b/src/WingetCreateCLI/Commands/NewCommand.cs index 06d5dd8d..a696cbdf 100644 --- a/src/WingetCreateCLI/Commands/NewCommand.cs +++ b/src/WingetCreateCLI/Commands/NewCommand.cs @@ -261,7 +261,7 @@ public override async Task Execute() ShiftInstallerFieldsToRootLevel(manifests.InstallerManifest); RemoveEmptyStringAndListFieldsInManifests(manifests); DisplayManifestPreview(manifests); - isManifestValid = ValidateManifestsInTempDir(manifests); + isManifestValid = ValidateManifestsInTempDir(manifests, this.Format); } while (Prompt.Confirm(Resources.ConfirmManifestCreation_Message)); diff --git a/src/WingetCreateCLI/Commands/NewLocaleCommand.cs b/src/WingetCreateCLI/Commands/NewLocaleCommand.cs index 6a25119a..92995a48 100644 --- a/src/WingetCreateCLI/Commands/NewLocaleCommand.cs +++ b/src/WingetCreateCLI/Commands/NewLocaleCommand.cs @@ -224,7 +224,7 @@ public override async Task Execute() { LocaleManifest newlocale = this.GenerateLocaleManifest(originalManifests, referenceLocaleManifest); Console.WriteLine(); - ValidateManifestsInTempDir(originalManifests); + ValidateManifestsInTempDir(originalManifests, this.Format); originalManifests.LocaleManifests.Add(newlocale); newLocales.Add(newlocale); } @@ -241,7 +241,7 @@ public override async Task Execute() string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir); - if (ValidateManifest(manifestDirectoryPath)) + if (ValidateManifest(manifestDirectoryPath, this.Format)) { if (Prompt.Confirm(Resources.ConfirmGitHubSubmitManifest_Message)) { diff --git a/src/WingetCreateCLI/Commands/SubmitCommand.cs b/src/WingetCreateCLI/Commands/SubmitCommand.cs index 58dc3313..b5c6535c 100644 --- a/src/WingetCreateCLI/Commands/SubmitCommand.cs +++ b/src/WingetCreateCLI/Commands/SubmitCommand.cs @@ -112,7 +112,7 @@ private async Task SubmitManifest() string expandedPath = System.Environment.ExpandEnvironmentVariables(this.Path); // TODO: Remove singleton support. - if (File.Exists(expandedPath) && ValidateManifest(expandedPath)) + if (File.Exists(expandedPath) && ValidateManifest(expandedPath, this.Format)) { Manifests manifests = new Manifests(); manifests.SingletonManifest = Serialization.DeserializeFromPath(expandedPath); @@ -124,7 +124,7 @@ private async Task SubmitManifest() return await this.GitHubSubmitManifests(manifests, this.PRTitle, this.Replace, this.ReplaceVersion); } - else if (Directory.Exists(expandedPath) && ValidateManifest(expandedPath)) + else if (Directory.Exists(expandedPath) && ValidateManifest(expandedPath, this.Format)) { List manifestContents = Directory.GetFiles(expandedPath).Select(f => File.ReadAllText(f)).ToList(); Manifests manifests = Serialization.DeserializeManifestContents(manifestContents); diff --git a/src/WingetCreateCLI/Commands/UpdateCommand.cs b/src/WingetCreateCLI/Commands/UpdateCommand.cs index b7e573de..ae0dfab2 100644 --- a/src/WingetCreateCLI/Commands/UpdateCommand.cs +++ b/src/WingetCreateCLI/Commands/UpdateCommand.cs @@ -274,7 +274,7 @@ await this.UpdateManifestsInteractively(initialManifests) : string manifestDirectoryPath = SaveManifestDirToLocalPath(updatedManifests, this.OutputDir); - if (ValidateManifest(manifestDirectoryPath)) + if (ValidateManifest(manifestDirectoryPath, this.Format)) { if (this.SubmitToGitHub) { @@ -687,7 +687,7 @@ private static bool VerifyUpdatedInstallerHash(Manifests oldManifest, InstallerM return newHashes.Except(oldHashes).Any(); } - private static void DisplayManifestsAsMenuSelection(Manifests manifests) + private static void DisplayManifestsAsMenuSelection(Manifests manifests, ManifestFormat format) { Console.Clear(); string versionFileName = Manifests.GetFileName(manifests.VersionManifest, Extension); @@ -709,7 +709,7 @@ private static void DisplayManifestsAsMenuSelection(Manifests manifests) } selectionList.Add(Resources.Done_MenuItem); - ValidateManifestsInTempDir(manifests); + ValidateManifestsInTempDir(manifests, format); var selectedItem = Prompt.Select(Resources.SelectManifestToEdit_Message, selectionList); if (selectedItem == versionManifestMenuItem) @@ -956,13 +956,13 @@ private async Task UpdateManifestsInteractively(Manifests manifests) this.AddVersionSpecificMetadata(manifests); DisplayManifestPreview(manifests); - ValidateManifestsInTempDir(manifests); + ValidateManifestsInTempDir(manifests, this.Format); } while (Prompt.Confirm(Resources.DiscardUpdateAndStartOver_Message)); if (Prompt.Confirm(Resources.EditManifests_Message)) { - DisplayManifestsAsMenuSelection(manifests); + DisplayManifestsAsMenuSelection(manifests, this.Format); } if (!this.SubmitToGitHub) diff --git a/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs b/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs index 4d9a0e8f..e57a47cc 100644 --- a/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs +++ b/src/WingetCreateCLI/Commands/UpdateLocaleCommand.cs @@ -172,7 +172,7 @@ public override async Task Execute() string manifestDirectoryPath = SaveManifestDirToLocalPath(originalManifests, this.OutputDir); - if (ValidateManifest(manifestDirectoryPath)) + if (ValidateManifest(manifestDirectoryPath, this.Format)) { if (Prompt.Confirm(Resources.ConfirmGitHubSubmitManifest_Message)) { @@ -281,7 +281,7 @@ private Tuple> PromptAndUpdateExisti } Console.WriteLine(); - ValidateManifestsInTempDir(manifests); + ValidateManifestsInTempDir(manifests, this.Format); } while (Prompt.Confirm(Resources.UpdateAnotherLocale_Message)); diff --git a/src/WingetCreateCLI/Properties/Resources.Designer.cs b/src/WingetCreateCLI/Properties/Resources.Designer.cs index 17aa4667..ab6f0f9c 100644 --- a/src/WingetCreateCLI/Properties/Resources.Designer.cs +++ b/src/WingetCreateCLI/Properties/Resources.Designer.cs @@ -3149,6 +3149,15 @@ public static string SingletonManifest_Message { } } + /// + /// Looks up a localized string similar to Skipping manifest validation. The CLI can only validate YAML format. Validate output manually before submission.. + /// + public static string SkippingManifestValidation_Message { + get { + return ResourceManager.GetString("SkippingManifestValidation_Message", resourceCulture); + } + } + /// /// Looks up a localized string similar to Skipping pull request submission.... /// diff --git a/src/WingetCreateCLI/Properties/Resources.resx b/src/WingetCreateCLI/Properties/Resources.resx index 7014c6c9..32297fee 100644 --- a/src/WingetCreateCLI/Properties/Resources.resx +++ b/src/WingetCreateCLI/Properties/Resources.resx @@ -1418,4 +1418,7 @@ Warning: Using this argument may result in the token being logged. Consider an a Authentication information for Entra Id secured private sources + + Skipping manifest validation. The CLI can only validate YAML format. Validate output manually before submission. + \ No newline at end of file diff --git a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs index f9d74b04..4cc4d8eb 100644 --- a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs +++ b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs @@ -9,6 +9,7 @@ namespace Microsoft.WingetCreateE2ETests using Microsoft.WingetCreateCLI.Commands; using Microsoft.WingetCreateCLI.Logging; using Microsoft.WingetCreateCLI.Models.Settings; + using Microsoft.WingetCreateCLI.Properties; using Microsoft.WingetCreateCore; using Microsoft.WingetCreateCore.Common; using Microsoft.WingetCreateTests; @@ -27,6 +28,7 @@ public class E2ETests : GitHubTestsBase { private const string PackageVersion = "1.2.3.4"; private GitHub gitHub; + private StringWriter sw; /// /// One-time function that runs at the beginning of this test class. @@ -37,6 +39,8 @@ public void Setup() Logger.Initialize(); this.gitHub = new GitHub(this.GitHubApiKey, this.WingetPkgsTestRepoOwner, this.WingetPkgsTestRepo); TestUtils.InitializeMockDownload(); + this.sw = new StringWriter(); + Console.SetOut(this.sw); } /// @@ -54,12 +58,12 @@ public void Setup() [TestCase(TestConstants.YamlConstants.TestPortablePackageIdentifier, TestConstants.YamlConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.YamlManifestFormat)] [TestCase(TestConstants.YamlConstants.TestZipPackageIdentifier, TestConstants.YamlConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.YamlManifestFormat)] - // JSON E2E Tests. Skipped because of https://github.com/microsoft/winget-cli/issues/5336 - [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] - [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] - [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] - [TestCase(TestConstants.JsonConstants.TestPortablePackageIdentifier, TestConstants.JsonConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] - [TestCase(TestConstants.JsonConstants.TestZipPackageIdentifier, TestConstants.JsonConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.JsonManifestFormat, Ignore = "Fails WinGetUtil.WinGetValidateManifest in schema version 1.10.0+")] + // JSON E2E Tests + [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] + [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat)] + [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat)] + [TestCase(TestConstants.JsonConstants.TestPortablePackageIdentifier, TestConstants.JsonConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] + [TestCase(TestConstants.JsonConstants.TestZipPackageIdentifier, TestConstants.JsonConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.JsonManifestFormat)] public async Task SubmitAndUpdateInstaller(string packageId, string manifestName, string installerName, ManifestFormat format) { @@ -86,6 +90,10 @@ private async Task RunSubmitAndUpdateFlow(string packageId, string manifestPath, OpenPRInBrowser = false, }; ClassicAssert.IsTrue(await submitCommand.Execute(), "Command should have succeeded"); + this.AssertValidationOutput(format); + + // Clear output for the next command + this.sw.GetStringBuilder().Clear(); var mergeRetryPolicy = Policy .Handle() @@ -115,11 +123,22 @@ await mergeRetryPolicy.ExecuteAsync(async () => ClassicAssert.IsTrue(await updateCommand.LoadGitHubClient(), "Failed to create GitHub client"); ClassicAssert.IsTrue(await updateCommand.Execute(), "Command should execute successfully"); - string pathToValidate = Path.Combine(Directory.GetCurrentDirectory(), Utils.GetAppManifestDirPath(packageId, PackageVersion)); - (bool success, string message) = WinGetUtil.ValidateManifest(pathToValidate); - ClassicAssert.IsTrue(success, message); - + // Since SubmitToGitHub is true, the command will first validate the manifest & then submit the PR + this.AssertValidationOutput(format); await this.gitHub.ClosePullRequest(updateCommand.PullRequestNumber); } + + private void AssertValidationOutput(ManifestFormat format) + { + string output = this.sw.ToString(); + if (format == ManifestFormat.Yaml) + { + Assert.That(output, Does.Contain(string.Format(Resources.ManifestValidationSucceeded_Message, true)), "Manifest validation success message should be shown"); + } + else + { + Assert.That(output, Does.Contain(Resources.SkippingManifestValidation_Message), "Skipping manifest validation message should be shown"); + } + } } } From 99b76d7370ae6c94e6a63212192b0e7e366d5813 Mon Sep 17 00:00:00 2001 From: Muhammad Danish <88161975+mdanish-kh@users.noreply.github.com> Date: Tue, 1 Apr 2025 21:30:46 +0500 Subject: [PATCH 4/5] add a comment --- src/WingetCreateCLI/Commands/BaseCommand.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WingetCreateCLI/Commands/BaseCommand.cs b/src/WingetCreateCLI/Commands/BaseCommand.cs index 9d99adeb..4fd1e832 100644 --- a/src/WingetCreateCLI/Commands/BaseCommand.cs +++ b/src/WingetCreateCLI/Commands/BaseCommand.cs @@ -389,6 +389,8 @@ protected static bool ValidateManifest(string manifestPath, ManifestFormat forma { bool skipValidation = format != ManifestFormat.Yaml; + // Skip validation because of https://github.com/microsoft/winget-cli/issues/5336 + // More discussion in the PR https://github.com/microsoft/winget-create/pull/593 if (skipValidation) { Logger.WarnLocalized(nameof(Resources.SkippingManifestValidation_Message)); From e7a5a68c090f0bf9fe3d8a64ca0bcc8a5f778172 Mon Sep 17 00:00:00 2001 From: Muhammad Danish <88161975+mdanish-kh@users.noreply.github.com> Date: Tue, 24 Jun 2025 05:52:45 +0500 Subject: [PATCH 5/5] address comments --- src/WingetCreateCLI/PromptHelper.cs | 15 ++++++++++++++- .../Properties/Resources.Designer.cs | 15 ++++++++++++--- src/WingetCreateCLI/Properties/Resources.resx | 9 ++++++--- src/WingetCreateCore/Common/GitHub.cs | 7 +++---- .../WingetCreateTests/E2ETests/E2ETests.cs | 7 ------- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/WingetCreateCLI/PromptHelper.cs b/src/WingetCreateCLI/PromptHelper.cs index 40ebb5bf..6b221969 100644 --- a/src/WingetCreateCLI/PromptHelper.cs +++ b/src/WingetCreateCLI/PromptHelper.cs @@ -240,7 +240,20 @@ public static void PromptPropertyAndSetValue(object model, string memberName, { Type instanceType = typeof(T); string message = string.Format(Resources.FieldValueIs_Message, memberName); - Console.WriteLine(Resources.ResourceManager.GetString($"{memberName}_KeywordDescription")); + + // TODO: Remove when updating the code to handle property name collisions. + // The proper way to handle this may be to append the model information + // something like "{modelName}_{propertyName}_KeywordDescription" e.g. "Installers_Scope_KeywordDescription" & + // "Installers_Authentication_MicrosoftEntraIdAuthenticationInfo_Scope_KeywordDescription" and updating all resource + // strings to follow this convention. + if (model.GetType() == typeof(MicrosoftEntraIdAuthenticationInfo) && memberName == "Scope") + { + Console.WriteLine(Resources.MicrosoftEntraIdAuthenticationInfo_Scope_KeywordDescription); + } + else + { + Console.WriteLine(Resources.ResourceManager.GetString($"{memberName}_KeywordDescription")); + } if (instanceType == typeof(object)) { diff --git a/src/WingetCreateCLI/Properties/Resources.Designer.cs b/src/WingetCreateCLI/Properties/Resources.Designer.cs index ab6f0f9c..499f6f91 100644 --- a/src/WingetCreateCLI/Properties/Resources.Designer.cs +++ b/src/WingetCreateCLI/Properties/Resources.Designer.cs @@ -241,7 +241,7 @@ public static string ArgumentLimitExceeded_Error { } /// - /// Looks up a localized string similar to Authentication information for Entra Id secured private sources. + /// Looks up a localized string similar to Authentication information for secured private sources. /// public static string Authentication_KeywordDescription { get { @@ -250,7 +250,7 @@ public static string Authentication_KeywordDescription { } /// - /// Looks up a localized string similar to The type of authentication to use for Entra Id authentication. + /// Looks up a localized string similar to The type of authentication to use. /// public static string AuthenticationType_KeywordDescription { get { @@ -1845,7 +1845,7 @@ public static string Markets_KeywordDescription { } /// - /// Looks up a localized string similar to Information required for Entra Id authentication in private sources. + /// Looks up a localized string similar to Information required for Microsoft Entra Id authentication. /// public static string MicrosoftEntraIdAuthenticationInfo_KeywordDescription { get { @@ -1853,6 +1853,15 @@ public static string MicrosoftEntraIdAuthenticationInfo_KeywordDescription { } } + /// + /// Looks up a localized string similar to The scope value for Microsoft Entra Id authentication. + /// + public static string MicrosoftEntraIdAuthenticationInfo_Scope_KeywordDescription { + get { + return ResourceManager.GetString("MicrosoftEntraIdAuthenticationInfo_Scope_KeywordDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to The installer minimum operating system version. /// diff --git a/src/WingetCreateCLI/Properties/Resources.resx b/src/WingetCreateCLI/Properties/Resources.resx index 32297fee..ee626cb7 100644 --- a/src/WingetCreateCLI/Properties/Resources.resx +++ b/src/WingetCreateCLI/Properties/Resources.resx @@ -1407,18 +1407,21 @@ Warning: Using this argument may result in the token being logged. Consider an a The forked repository could not be synced with the upstream commits due to a merge conflict. Resolve conflicts manually and try again. - The type of authentication to use for Entra Id authentication + The type of authentication to use The resource to use for Microsoft Entra Id authentication - Information required for Entra Id authentication in private sources + Information required for Microsoft Entra Id authentication - Authentication information for Entra Id secured private sources + Authentication information for secured private sources Skipping manifest validation. The CLI can only validate YAML format. Validate output manually before submission. + + The scope value for Microsoft Entra Id authentication + \ No newline at end of file diff --git a/src/WingetCreateCore/Common/GitHub.cs b/src/WingetCreateCore/Common/GitHub.cs index 1321750c..d6b46aad 100644 --- a/src/WingetCreateCore/Common/GitHub.cs +++ b/src/WingetCreateCore/Common/GitHub.cs @@ -19,7 +19,6 @@ namespace Microsoft.WingetCreateCore.Common using Microsoft.WingetCreateCore.Models.Installer; using Octokit; using Polly; - using AuthenticationType = Octokit.AuthenticationType; /// /// Provides functionality for interacting a user's GitHub account. @@ -46,7 +45,7 @@ public GitHub(string githubApiToken, string wingetRepoOwner, string wingetRepo) this.github = new GitHubClient(new ProductHeaderValue(UserAgentName)); if (githubApiToken != null) { - this.github.Credentials = new Credentials(githubApiToken, AuthenticationType.Bearer); + this.github.Credentials = new Credentials(githubApiToken, Octokit.AuthenticationType.Bearer); } } @@ -63,7 +62,7 @@ public static async Task GetGitHubAppInstallationAccessToken(string gitH string jwtToken = GetJwtToken(gitHubAppPrivateKeyPem, gitHubAppId); var github = new GitHubClient(new ProductHeaderValue(UserAgentName)); - github.Credentials = new Credentials(jwtToken, AuthenticationType.Bearer); + github.Credentials = new Credentials(jwtToken, Octokit.AuthenticationType.Bearer); var installation = await github.GitHubApps.GetRepositoryInstallationForCurrent(wingetRepoOwner, wingetRepo); var response = await github.GitHubApps.CreateInstallationToken(installation.Id); @@ -244,7 +243,7 @@ public async Task FindPackageId(string packageId) public async Task PopulateGitHubMetadata(Manifests manifests, string serializerFormat) { // Only populate metadata if we have a valid GitHub token. - if (this.github.Credentials.AuthenticationType != AuthenticationType.Anonymous) + if (this.github.Credentials.AuthenticationType != Octokit.AuthenticationType.Anonymous) { return await GitHubManifestMetadata.PopulateManifestMetadata(manifests, serializerFormat, this.github); } diff --git a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs index 4cc4d8eb..933b5b8f 100644 --- a/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs +++ b/src/WingetCreateTests/WingetCreateTests/E2ETests/E2ETests.cs @@ -58,13 +58,6 @@ public void Setup() [TestCase(TestConstants.YamlConstants.TestPortablePackageIdentifier, TestConstants.YamlConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.YamlManifestFormat)] [TestCase(TestConstants.YamlConstants.TestZipPackageIdentifier, TestConstants.YamlConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.YamlManifestFormat)] - // JSON E2E Tests - [TestCase(TestConstants.JsonConstants.TestExePackageIdentifier, TestConstants.JsonConstants.TestExeManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestMsiPackageIdentifier, TestConstants.JsonConstants.TestMsiManifest, TestConstants.TestMsiInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestMultifileMsixPackageIdentifier, TestConstants.JsonConstants.TestMultifileMsixManifestDir, TestConstants.TestMsixInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestPortablePackageIdentifier, TestConstants.JsonConstants.TestPortableManifest, TestConstants.TestExeInstaller, TestConstants.JsonManifestFormat)] - [TestCase(TestConstants.JsonConstants.TestZipPackageIdentifier, TestConstants.JsonConstants.TestZipManifest, TestConstants.TestZipInstaller, TestConstants.JsonManifestFormat)] - public async Task SubmitAndUpdateInstaller(string packageId, string manifestName, string installerName, ManifestFormat format) { await this.RunSubmitAndUpdateFlow(packageId, TestUtils.GetTestFile(manifestName), installerName, format);