From 8c034220626addcfbdad1b1904373ff550567505 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Fri, 8 Oct 2021 20:38:46 -0700 Subject: [PATCH 1/7] fix: Regen server mode client for missing changes in last release --- src/AWS.Deploy.ServerMode.Client/RestAPI.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AWS.Deploy.ServerMode.Client/RestAPI.cs b/src/AWS.Deploy.ServerMode.Client/RestAPI.cs index 9f74d9834..22fab6e35 100644 --- a/src/AWS.Deploy.ServerMode.Client/RestAPI.cs +++ b/src/AWS.Deploy.ServerMode.Client/RestAPI.cs @@ -1518,8 +1518,11 @@ public partial class OptionSettingItemSummary [Newtonsoft.Json.JsonProperty("advanced", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public bool Advanced { get; set; } - [Newtonsoft.Json.JsonProperty("updatable", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public bool Updatable { get; set; } + [Newtonsoft.Json.JsonProperty("readOnly", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool ReadOnly { get; set; } + + [Newtonsoft.Json.JsonProperty("visible", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public bool Visible { get; set; } [Newtonsoft.Json.JsonProperty("allowedValues", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.Collections.Generic.ICollection AllowedValues { get; set; } From d9697b4c479dbdbab70c8be7e9c6b36dc362087a Mon Sep 17 00:00:00 2001 From: aws-sdk-dotnet-automation Date: Fri, 8 Oct 2021 18:52:48 +0000 Subject: [PATCH 2/7] build: version bump to 0.23 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 68ecae5f4..2d9c47969 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.22", + "version": "0.23", "publicReleaseRefSpec": [ ".*" ], From ade116b1f776a8c676b97909accf67d5775c0b59 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Mon, 11 Oct 2021 22:07:57 -0700 Subject: [PATCH 3/7] fix: Fixed performance issue determining if a directory is under source control --- .../CustomRecipeLocator.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/AWS.Deploy.Orchestration/CustomRecipeLocator.cs b/src/AWS.Deploy.Orchestration/CustomRecipeLocator.cs index 7d348364d..f82053caf 100644 --- a/src/AWS.Deploy.Orchestration/CustomRecipeLocator.cs +++ b/src/AWS.Deploy.Orchestration/CustomRecipeLocator.cs @@ -58,7 +58,7 @@ public async Task> LocateCustomRecipePaths(string targetApplicat customRecipePaths.Add(recipePath); } - foreach (var recipePath in await LocateAlternateRecipePaths(targetApplicationFullPath, solutionDirectoryPath)) + foreach (var recipePath in LocateAlternateRecipePaths(targetApplicationFullPath, solutionDirectoryPath)) { if (ContainsRecipeFile(recipePath)) customRecipePaths.Add(recipePath); @@ -95,14 +95,14 @@ private async Task> LocateRecipePathsFromManifestFile(string target /// The absolute path to the target application csproj or fsproj file /// The absolute path of the directory which contains the solution file for the target application /// A list of recipe definition paths. - private async Task> LocateAlternateRecipePaths(string targetApplicationFullPath, string solutionDirectoryPath ) + private List LocateAlternateRecipePaths(string targetApplicationFullPath, string solutionDirectoryPath ) { var targetApplicationDirectoryPath = _directoryManager.GetDirectoryInfo(targetApplicationFullPath).Parent.FullName; string? rootDirectoryPath; - if (await IsDirectoryUnderSourceControl(targetApplicationDirectoryPath)) + if (IsDirectoryUnderSourceControl(targetApplicationDirectoryPath)) { - rootDirectoryPath = await GetSourceControlRootDirectory(targetApplicationDirectoryPath); + rootDirectoryPath = GetSourceControlRootDirectory(targetApplicationDirectoryPath); } else { @@ -138,10 +138,10 @@ private List GetRecipePathsFromRootDirectory(string? rootDirectoryPath) /// /// The absolute path of the current directory /// The source control root directory absolute path. - private async Task GetSourceControlRootDirectory(string currentDirectoryPath) + private string? GetSourceControlRootDirectory(string currentDirectoryPath) { var possibleRootDirectoryPath = currentDirectoryPath; - while (await IsDirectoryUnderSourceControl(currentDirectoryPath)) + while (IsDirectoryUnderSourceControl(currentDirectoryPath)) { possibleRootDirectoryPath = currentDirectoryPath; var currentDirectoryInfo = _directoryManager.GetDirectoryInfo(currentDirectoryPath); @@ -159,14 +159,19 @@ private List GetRecipePathsFromRootDirectory(string? rootDirectoryPath) /// /// An absolute directory path. /// - private async Task IsDirectoryUnderSourceControl(string? directoryPath) + private bool IsDirectoryUnderSourceControl(string? directoryPath) { - if (!string.IsNullOrEmpty(directoryPath)) + var currentDir = directoryPath; + while(currentDir != null) { - var gitStatusResult = await _commandLineWrapper.TryRunWithResult(GIT_STATUS_COMMAND, directoryPath); - var svnStatusResult = await _commandLineWrapper.TryRunWithResult(SVN_STATUS_COMMAND, directoryPath); - return gitStatusResult.Success || svnStatusResult.Success; + if(_directoryManager.GetDirectories(currentDir, ".git").Any()) + { + return true; + } + + currentDir = _directoryManager.GetDirectoryInfo(currentDir).Parent?.FullName; } + return false; } From f64b574f1e0bc904532d467a82fec2e021d610e4 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Mon, 11 Oct 2021 22:09:53 -0700 Subject: [PATCH 4/7] fix: Fixed incorrectly checking nullable int parent pid field when starting server mode --- src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs index b06e36ce5..960734b83 100644 --- a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs +++ b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs @@ -54,7 +54,7 @@ public ServerModeCommand(IToolInteractiveService interactiveService, int port, i var host = builder.Build(); - if (_parentPid == null) + if (_parentPid.HasValue && _parentPid.Value != 0) { await host.RunAsync(cancellationToken); } @@ -62,7 +62,7 @@ public ServerModeCommand(IToolInteractiveService interactiveService, int port, i { try { - var process = Process.GetProcessById((int)_parentPid); + var process = Process.GetProcessById(_parentPid.GetValueOrDefault()); process.EnableRaisingEvents = true; process.Exited += async (sender, args) => { await ShutDownHost(host, cancellationToken); }; } From f871576aad98636b3fa3a0ad036ff445e45bbb63 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Mon, 11 Oct 2021 22:12:26 -0700 Subject: [PATCH 5/7] docs: Reword server mode description --- src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs index 960734b83..2e142fb4e 100644 --- a/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs +++ b/src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs @@ -34,7 +34,7 @@ public ServerModeCommand(IToolInteractiveService interactiveService, int port, i public async Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken)) { - _interactiveService.WriteLine("Server mode is an experimental feature being developed to allow communication between this CLI and the AWS Toolkit for Visual Studio. Expect behavior changes and API changes as server mode is being developed."); + _interactiveService.WriteLine("Server mode allows communication between this CLI and the AWS Toolkit for Visual Studio."); IEncryptionProvider encryptionProvider = CreateEncryptionProvider(); From 039915922b618be0a932f3f31a03cb5c2e1db57f Mon Sep 17 00:00:00 2001 From: Ganesh Jangir Date: Fri, 8 Oct 2021 16:54:56 -0700 Subject: [PATCH 6/7] test: add logging on cdk installation and moved semaphore to CDKManager --- .../CDK/CDKManager.cs | 50 +++++++++++++------ .../CDK/NPMPackageInitializer.cs | 9 +++- src/AWS.Deploy.Orchestration/Orchestrator.cs | 15 +----- .../CDK/CDKManagerTests.cs | 4 +- .../CDK/NPMPackageInitializerTests.cs | 6 ++- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/AWS.Deploy.Orchestration/CDK/CDKManager.cs b/src/AWS.Deploy.Orchestration/CDK/CDKManager.cs index 0c306f805..18c403d29 100644 --- a/src/AWS.Deploy.Orchestration/CDK/CDKManager.cs +++ b/src/AWS.Deploy.Orchestration/CDK/CDKManager.cs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 using System; +using System.Diagnostics; +using System.Threading; using System.Threading.Tasks; +using AWS.Deploy.Orchestration.Utilities; namespace AWS.Deploy.Orchestration.CDK { @@ -25,37 +28,52 @@ public interface ICDKManager public class CDKManager : ICDKManager { + private static readonly SemaphoreSlim s_cdkManagerSemaphoreSlim = new(1,1); + private readonly ICDKInstaller _cdkInstaller; private readonly INPMPackageInitializer _npmPackageInitializer; + private readonly IOrchestratorInteractiveService _interactiveService; - public CDKManager(ICDKInstaller cdkInstaller, INPMPackageInitializer npmPackageInitializer) + public CDKManager(ICDKInstaller cdkInstaller, INPMPackageInitializer npmPackageInitializer, IOrchestratorInteractiveService interactiveService) { _cdkInstaller = cdkInstaller; _npmPackageInitializer = npmPackageInitializer; + _interactiveService = interactiveService; } public async Task EnsureCompatibleCDKExists(string workingDirectory, Version cdkVersion) { - var globalCDKVersionResult = await _cdkInstaller.GetGlobalVersion(); - if (globalCDKVersionResult.Success && globalCDKVersionResult.Result?.CompareTo(cdkVersion) >= 0) - { - return; - } + await s_cdkManagerSemaphoreSlim.WaitAsync(); - var isNPMPackageInitialized = _npmPackageInitializer.IsInitialized(workingDirectory); - if (!isNPMPackageInitialized) + try { - await _npmPackageInitializer.Initialize(workingDirectory, cdkVersion); - return; // There is no need to install CDK CLI explicitly, npm install takes care of first time bootstrap. - } + var globalCdkVerion = await _cdkInstaller.GetGlobalVersion(); + if (globalCdkVerion.Success && globalCdkVerion.Result?.CompareTo(cdkVersion) >= 0) + { + _interactiveService.LogDebugLine($"CDK version {globalCdkVerion.Result} found in global node_modules."); + return; + } - var localCDKVersionResult = await _cdkInstaller.GetLocalVersion(workingDirectory); - if (localCDKVersionResult.Success && localCDKVersionResult.Result?.CompareTo(cdkVersion) >= 0) + var isNPMPackageInitialized = _npmPackageInitializer.IsInitialized(workingDirectory); + if (!isNPMPackageInitialized) + { + await _npmPackageInitializer.Initialize(workingDirectory, cdkVersion); + return; // There is no need to install CDK CLI explicitly, npm install takes care of first time bootstrap. + } + + var localCdkVersion = await _cdkInstaller.GetLocalVersion(workingDirectory); + if (localCdkVersion.Success && localCdkVersion.Result?.CompareTo(cdkVersion) >= 0) + { + _interactiveService.LogDebugLine($"CDK version {localCdkVersion.Result} found in local node_modules at {workingDirectory}."); + return; + } + + await _cdkInstaller.Install(workingDirectory, cdkVersion); + } + finally { - return; + s_cdkManagerSemaphoreSlim.Release(); } - - await _cdkInstaller.Install(workingDirectory, cdkVersion); } } } diff --git a/src/AWS.Deploy.Orchestration/CDK/NPMPackageInitializer.cs b/src/AWS.Deploy.Orchestration/CDK/NPMPackageInitializer.cs index 9f0633450..c5759a294 100644 --- a/src/AWS.Deploy.Orchestration/CDK/NPMPackageInitializer.cs +++ b/src/AWS.Deploy.Orchestration/CDK/NPMPackageInitializer.cs @@ -46,14 +46,20 @@ public class NPMPackageInitializer : INPMPackageInitializer private readonly IPackageJsonGenerator _packageJsonGenerator; private readonly IFileManager _fileManager; private readonly IDirectoryManager _directoryManager; + private readonly IOrchestratorInteractiveService _interactiveService; private const string _packageJsonFileName = "package.json"; - public NPMPackageInitializer(ICommandLineWrapper commandLineWrapper, IPackageJsonGenerator packageJsonGenerator, IFileManager fileManager, IDirectoryManager directoryManager) + public NPMPackageInitializer(ICommandLineWrapper commandLineWrapper, + IPackageJsonGenerator packageJsonGenerator, + IFileManager fileManager, + IDirectoryManager directoryManager, + IOrchestratorInteractiveService interactiveService) { _commandLineWrapper = commandLineWrapper; _packageJsonGenerator = packageJsonGenerator; _fileManager = fileManager; _directoryManager = directoryManager; + _interactiveService = interactiveService; } public bool IsInitialized(string workingDirectory) @@ -64,6 +70,7 @@ public bool IsInitialized(string workingDirectory) public async Task Initialize(string workingDirectory, Version cdkVersion) { + _interactiveService.LogDebugLine($"Creating package.json at {workingDirectory}."); var packageJsonFileContent = _packageJsonGenerator.Generate(cdkVersion); var packageJsonFilePath = Path.Combine(workingDirectory, _packageJsonFileName); diff --git a/src/AWS.Deploy.Orchestration/Orchestrator.cs b/src/AWS.Deploy.Orchestration/Orchestrator.cs index 987446c7f..b24fe7cd0 100644 --- a/src/AWS.Deploy.Orchestration/Orchestrator.cs +++ b/src/AWS.Deploy.Orchestration/Orchestrator.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading; using System.Threading.Tasks; using AWS.Deploy.Common; using AWS.Deploy.Common.IO; @@ -14,8 +13,6 @@ using AWS.Deploy.Orchestration.CDK; using AWS.Deploy.Orchestration.Data; using AWS.Deploy.Orchestration.LocalUserSettings; -using AWS.Deploy.Recipes; -using Newtonsoft.Json; namespace AWS.Deploy.Orchestration { @@ -26,7 +23,6 @@ namespace AWS.Deploy.Orchestration /// public class Orchestrator { - private static readonly SemaphoreSlim s_cdkManagerSemaphoreSlim = new(1,1); private const string REPLACE_TOKEN_LATEST_DOTNET_BEANSTALK_PLATFORM_ARN = "{LatestDotnetBeanstalkPlatformArn}"; private readonly ICdkProjectHandler? _cdkProjectHandler; @@ -166,16 +162,7 @@ public async Task DeployRecommendation(CloudApplication cloudApplication, Recomm var projFiles = _directoryManager.GetProjFiles(cdkProject); var cdkVersion = _cdkVersionDetector.Detect(projFiles); - await s_cdkManagerSemaphoreSlim.WaitAsync(); - - try - { - await _cdkManager.EnsureCompatibleCDKExists(Constants.CDK.DeployToolWorkspaceDirectoryRoot, cdkVersion); - } - finally - { - s_cdkManagerSemaphoreSlim.Release(); - } + await _cdkManager.EnsureCompatibleCDKExists(Constants.CDK.DeployToolWorkspaceDirectoryRoot, cdkVersion); try { diff --git a/test/AWS.Deploy.Orchestration.UnitTests/CDK/CDKManagerTests.cs b/test/AWS.Deploy.Orchestration.UnitTests/CDK/CDKManagerTests.cs index 6322b70d5..7ff064b03 100644 --- a/test/AWS.Deploy.Orchestration.UnitTests/CDK/CDKManagerTests.cs +++ b/test/AWS.Deploy.Orchestration.UnitTests/CDK/CDKManagerTests.cs @@ -13,6 +13,7 @@ public class CDKManagerTests { private readonly Mock _mockCdkManager; private readonly Mock _mockNodeInitializer; + private readonly Mock _mockInteractiveService; private readonly CDKManager _cdkManager; private const string _workingDirectory = @"c:\fake\path"; @@ -20,7 +21,8 @@ public CDKManagerTests() { _mockCdkManager = new Mock(); _mockNodeInitializer = new Mock(); - _cdkManager = new CDKManager(_mockCdkManager.Object, _mockNodeInitializer.Object); + _mockInteractiveService = new Mock(); + _cdkManager = new CDKManager(_mockCdkManager.Object, _mockNodeInitializer.Object, _mockInteractiveService.Object); } [Theory] diff --git a/test/AWS.Deploy.Orchestration.UnitTests/CDK/NPMPackageInitializerTests.cs b/test/AWS.Deploy.Orchestration.UnitTests/CDK/NPMPackageInitializerTests.cs index c3d4bdc5d..f05eaacc2 100644 --- a/test/AWS.Deploy.Orchestration.UnitTests/CDK/NPMPackageInitializerTests.cs +++ b/test/AWS.Deploy.Orchestration.UnitTests/CDK/NPMPackageInitializerTests.cs @@ -4,8 +4,10 @@ using System; using System.IO; using System.Threading.Tasks; +using AWS.Deploy.CLI; using AWS.Deploy.CLI.Common.UnitTests.IO; using AWS.Deploy.Orchestration.CDK; +using Moq; using Xunit; namespace AWS.Deploy.Orchestration.UnitTests.CDK @@ -16,6 +18,7 @@ public class NPMPackageInitializerTests private readonly INPMPackageInitializer _npmPackageInitializer; private readonly TestFileManager _fileManager; private readonly TestDirectoryManager _directoryManager; + private readonly Mock _mockInteractiveService; private const string _workingDirectory = @"c:\fake\path"; private const string _packageJsonContent = @@ -44,11 +47,12 @@ public class NPMPackageInitializerTests public NPMPackageInitializerTests() { + _mockInteractiveService = new Mock(); _fileManager = new TestFileManager(); _directoryManager = new TestDirectoryManager(); _testCommandLineWrapper = new TestCommandLineWrapper(); var packageJsonGenerator = new PackageJsonGenerator(_packageJsonTemplate); - _npmPackageInitializer = new NPMPackageInitializer(_testCommandLineWrapper, packageJsonGenerator, _fileManager, _directoryManager); + _npmPackageInitializer = new NPMPackageInitializer(_testCommandLineWrapper, packageJsonGenerator, _fileManager, _directoryManager, _mockInteractiveService.Object); } [Fact] From 39e09aa9665b85aeacf84d49bd6abab2f25d2e07 Mon Sep 17 00:00:00 2001 From: Philippe El Asmar Date: Tue, 12 Oct 2021 14:29:17 -0400 Subject: [PATCH 7/7] fix: publish continues after a Docker failure --- .../ServerMode/Tasks/DeployRecommendationTask.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AWS.Deploy.CLI/ServerMode/Tasks/DeployRecommendationTask.cs b/src/AWS.Deploy.CLI/ServerMode/Tasks/DeployRecommendationTask.cs index a5b0aff7f..3df0db311 100644 --- a/src/AWS.Deploy.CLI/ServerMode/Tasks/DeployRecommendationTask.cs +++ b/src/AWS.Deploy.CLI/ServerMode/Tasks/DeployRecommendationTask.cs @@ -34,7 +34,9 @@ private async Task CreateDeploymentBundle() { if (_selectedRecommendation.Recipe.DeploymentBundle == DeploymentBundleTypes.Container) { - await _orchestrator.CreateContainerDeploymentBundle(_cloudApplication, _selectedRecommendation); + var dockerBuildDeploymentBundleResult = await _orchestrator.CreateContainerDeploymentBundle(_cloudApplication, _selectedRecommendation); + if (!dockerBuildDeploymentBundleResult) + throw new FailedToCreateDeploymentBundleException("Failed to create a deployment bundle"); } else if (_selectedRecommendation.Recipe.DeploymentBundle == DeploymentBundleTypes.DotnetPublishZipFile) {