diff --git a/src/Microsoft.NET.Sdk.Functions.Generator/Microsoft.NET.Sdk.Functions.Generator.csproj b/src/Microsoft.NET.Sdk.Functions.Generator/Microsoft.NET.Sdk.Functions.Generator.csproj index a3ef57a..0f56df2 100644 --- a/src/Microsoft.NET.Sdk.Functions.Generator/Microsoft.NET.Sdk.Functions.Generator.csproj +++ b/src/Microsoft.NET.Sdk.Functions.Generator/Microsoft.NET.Sdk.Functions.Generator.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Microsoft.NET.Sdk.Functions.MSBuild/Tasks/ZipDeploymentStatus.cs b/src/Microsoft.NET.Sdk.Functions.MSBuild/Tasks/ZipDeploymentStatus.cs index a7fed3a..36fe67c 100644 --- a/src/Microsoft.NET.Sdk.Functions.MSBuild/Tasks/ZipDeploymentStatus.cs +++ b/src/Microsoft.NET.Sdk.Functions.MSBuild/Tasks/ZipDeploymentStatus.cs @@ -10,6 +10,7 @@ using Microsoft.NET.Sdk.Functions.Http; using Microsoft.NET.Sdk.Functions.MSBuild.Properties; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Task = System.Threading.Tasks.Task; namespace Microsoft.NET.Sdk.Functions.MSBuild.Tasks @@ -65,14 +66,10 @@ public async Task PollDeploymentStatusAsync(string deploymentUrl, private async Task GetDeploymentStatusAsync(string deploymentUrl, string userName, string password, int retryCount, TimeSpan retryDelay, CancellationTokenSource cts) { - Dictionary json = await InvokeGetRequestWithRetryAsync>(deploymentUrl, userName, password, retryCount, retryDelay, cts); - string statusString = null; - if (json!= null && !json.TryGetValue("status", out statusString)) - { - return DeployStatus.Unknown; - } - - if (Enum.TryParse(statusString, out DeployStatus result)) + var json = await InvokeGetRequestWithRetryAsync(deploymentUrl, userName, password, retryCount, retryDelay, cts); + if (json != null + && json.TryGetValue("status", out JToken statusString) + && Enum.TryParse(statusString.Value(), out DeployStatus result)) { return result; } diff --git a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Microsoft.NET.Sdk.Functions.MSBuild.Tests.csproj b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Microsoft.NET.Sdk.Functions.MSBuild.Tests.csproj index c7fb0c8..3e61587 100644 --- a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Microsoft.NET.Sdk.Functions.MSBuild.Tests.csproj +++ b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Microsoft.NET.Sdk.Functions.MSBuild.Tests.csproj @@ -15,6 +15,21 @@ + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + Always diff --git a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.Designer.cs b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.Designer.cs new file mode 100644 index 0000000..da8308c --- /dev/null +++ b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.Designer.cs @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.NET.Sdk.Functions.MSBuild.Tests.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.NET.Sdk.Functions.MSBuild.Tests.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to { + /// "id": "7010fa61-d5df-46b5-a22e-98cfc81f1637", + /// "status": 3, + /// "status_text": "", + /// "author_email": "N/A", + /// "author": "N/A", + /// "deployer": "Push-Deployer", + /// "message": "Created via a push deployment", + /// "progress": "", + /// "received_time": "2022-05-25T04:40:36.0994691Z", + /// "start_time": "2022-05-25T04:40:37.1272389Z", + /// "end_time": "2022-05-25T04:40:39.4733696Z", + /// "last_success_end_time": null, + /// "complete": true, + /// "active": false, + /// "is_temp": false, + /// [rest of string was truncated]";. + /// + internal static string DeploymentResponse { + get { + return ResourceManager.GetString("DeploymentResponse", resourceCulture); + } + } + } +} diff --git a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.resx b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.resx new file mode 100644 index 0000000..88b1938 --- /dev/null +++ b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/Properties/Resources.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + { + "id": "7010fa61-d5df-46b5-a22e-98cfc81f1637", + "status": 3, + "status_text": "", + "author_email": "N/A", + "author": "N/A", + "deployer": "Push-Deployer", + "message": "Created via a push deployment", + "progress": "", + "received_time": "2022-05-25T04:40:36.0994691Z", + "start_time": "2022-05-25T04:40:37.1272389Z", + "end_time": "2022-05-25T04:40:39.4733696Z", + "last_success_end_time": null, + "complete": true, + "active": false, + "is_temp": false, + "is_readonly": true, + "url": "https://facaval-lc.scm.azurewebsites.net/api/deployments/latest", + "log_url": "https://facaval-lc.scm.azurewebsites.net/api/deployments/latest/log", + "site_name": "facaval-lc", + "build_summary": { + "errors": [], + "warnings": [] + } +} + + \ No newline at end of file diff --git a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/ZipDeploymentStatusTests.cs b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/ZipDeploymentStatusTests.cs index 0ac261a..e06b4bf 100644 --- a/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/ZipDeploymentStatusTests.cs +++ b/test/Microsoft.NET.Sdk.Functions.MSBuild.Tests/ZipDeploymentStatusTests.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.NET.Sdk.Functions.Http; +using Microsoft.NET.Sdk.Functions.MSBuild.Properties; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; using Moq; using Newtonsoft.Json; @@ -97,5 +98,40 @@ public async Task PollDeploymentStatusTest_ForValidResponses(HttpStatusCode resp // Assert verifyStep(client, expectedDeployStatus == actualdeployStatus); } + + [Fact] + public async Task PollDeploymentStatusTest_WithDeploymentSummary_Succeeds() + { + // Arrange + string deployUrl = "https://sitename.scm.azurewebsites.net/DeploymentStatus?Id=knownId"; + Action, DeployStatus> verifyStep = (client, status) => + { + client.Verify(c => c.GetAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, deployUrl, StringComparison.Ordinal)), It.IsAny())); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.Equal(DeployStatus.Failed, status); + }; + + Mock client = new Mock(); + HttpRequestMessage requestMessage = new HttpRequestMessage(); + client.Setup(x => x.DefaultRequestHeaders).Returns(requestMessage.Headers); + client.Setup(c => c.GetAsync(new Uri(deployUrl, UriKind.RelativeOrAbsolute), It.IsAny())).Returns(() => + { + HttpContent httpContent = new StringContent(Properties.Resources.DeploymentResponse, Encoding.UTF8, "application/json"); + HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = httpContent + }; + return Task.FromResult(responseMessage); + }); + + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + + // Act + var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); + + // Assert + verifyStep(client, actualdeployStatus); + } } }