From c1fa141436f61b60319187a5c872d9e3a4f62bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pereira?= Date: Fri, 21 Oct 2022 14:51:31 +0100 Subject: [PATCH] fix: support BuildablePackages on data packages closes #66 --- .../PackageType/DataPackageTypeHandlerV2.cs | 41 ++++----- core/Objects/CmfPackage.cs | 28 +++++- core/Objects/ProcessBuildStep.cs | 29 +----- core/Utilities/JsonConverters.cs | 73 +++++++++++++++ tests/Specs/Build.cs | 88 +------------------ 5 files changed, 116 insertions(+), 143 deletions(-) create mode 100644 core/Utilities/JsonConverters.cs diff --git a/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs b/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs index 26d3cecb..54c4c095 100644 --- a/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs +++ b/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs @@ -10,6 +10,9 @@ using Cmf.CLI.Core.Enums; using Cmf.CLI.Core.Objects; using Cmf.CLI.Utilities; +using Cmf.CLI.Commands.restore; +using Cmf.CLI.Core.Constants; +using Cmf.CLI.Factories; namespace Cmf.CLI.Handlers { @@ -64,40 +67,26 @@ public DataPackageTypeHandlerV2(CmfPackage cmfPackage) : base(cmfPackage) } }; - IFileInfo[] deeActionProjects = cmfPackage.GetFileInfo().Directory.GetFiles("*.csproj", SearchOption.AllDirectories); + cmfPackage.DFPackageType = PackageType.Business; // necessary because we restart the host during installation + } - foreach (IFileInfo project in deeActionProjects) + public override void Build(bool test) + { + foreach (var buildablePackage in CmfPackage.BuildablePackages ?? new()) { - if (project.Exists) + IFileInfo buildablePackageJson = buildablePackage.GetFiles(CoreConstants.CmfPackageFileName).FirstOrDefault(); + if (buildablePackageJson?.Exists ?? false) { - BuildSteps = BuildSteps.Union(new IBuildCommand[] - { - new DotnetCommand() - { - Command = "restore", - DisplayName = $"NuGet restore {project.Name}", - Solution = project, - NuGetConfig = this.fileSystem.FileInfo.FromFileName(Path.Join(FileSystemUtilities.GetProjectRoot(this.fileSystem, throwException: true).FullName, "NuGet.Config")), - WorkingDirectory = cmfPackage.GetFileInfo().Directory - }, - new DotnetCommand() - { - Command = "build", - DisplayName = $"Build {project.Name}", - Solution = project, - Configuration = "Release", - WorkingDirectory = cmfPackage.GetFileInfo().Directory, - Args = new[] { "--no-restore " } - } - }).ToArray(); + var buildPackage = CmfPackage.Load(buildablePackageJson); + var packageTypeHandler = PackageTypeFactory.GetPackageTypeHandler(buildPackage); + packageTypeHandler.Build(test); } else { - Log.Warning(string.Format(CoreMessages.NotFound, project.FullName)); + Log.Warning(string.Format(CoreMessages.NotFound, buildablePackage.FullName)); } } - - cmfPackage.DFPackageType = PackageType.Business; // necessary because we restart the host during installation + base.Build(test); } /// diff --git a/core/Objects/CmfPackage.cs b/core/Objects/CmfPackage.cs index 1246ff71..1081b812 100644 --- a/core/Objects/CmfPackage.cs +++ b/core/Objects/CmfPackage.cs @@ -13,6 +13,9 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; +using Newtonsoft.Json.Linq; +using Cmf.CLI.Core.Objects; +using Cmf.CLI.Core.Utilities; namespace Cmf.CLI.Core.Objects { @@ -248,7 +251,7 @@ public class CmfPackage : IEquatable [JsonConverter(typeof(StringEnumConverter))] [JsonProperty(Order = 20)] public PackageType? DFPackageType { get; set; } - + /// /// Gets or sets the build steps. /// @@ -258,6 +261,16 @@ public class CmfPackage : IEquatable [JsonProperty(Order = 21)] public List BuildSteps { get; set; } + /// + /// Gets or sets the build packages. + /// + /// + /// Packages that should be build before the context package + /// + [JsonProperty(Order = 22)] + [JsonConverter(typeof(ListAbstractionsDirectoryConverter))] + public List BuildablePackages { get; set; } + #endregion Public Properties #region Private Methods @@ -287,7 +300,7 @@ private void ValidatePackage() if (PackageType.Equals(PackageType.Root) && !Dependencies.Contains(Dependency.DefaultDependenciesToIgnore[0]) && !Dependencies.Contains(Dependency.DefaultDependenciesToIgnore[1])) { - throw new CliException(string.Format(CoreMessages.MissingMandatoryDependency, $"{ Dependency.DefaultDependenciesToIgnore[0] } and { Dependency.DefaultDependenciesToIgnore[1] }", string.Empty)); + throw new CliException(string.Format(CoreMessages.MissingMandatoryDependency, $"{Dependency.DefaultDependenciesToIgnore[0]} and {Dependency.DefaultDependenciesToIgnore[1]}", string.Empty)); } // When is fixed by the product team, this can be uncommented @@ -589,6 +602,15 @@ public bool ShouldSerializeDFPackageType() return DFPackageType != null && PackageType == PackageType.Generic; } + /// + /// Shoulds the serialize Buildable Packages + /// + /// returns false if Buildable Packages is null or empty + public bool ShouldSerializeBuildablePackages() + { + return BuildablePackages.HasAny(); + } + #region Static Methods /// @@ -802,4 +824,4 @@ public override int GetHashCode() #endregion Public Methods } -} +} \ No newline at end of file diff --git a/core/Objects/ProcessBuildStep.cs b/core/Objects/ProcessBuildStep.cs index 33fbac55..ebdea483 100644 --- a/core/Objects/ProcessBuildStep.cs +++ b/core/Objects/ProcessBuildStep.cs @@ -1,6 +1,7 @@ using System; using System.IO.Abstractions; using System.Linq; +using Cmf.CLI.Core.Utilities; using Newtonsoft.Json; namespace Cmf.CLI.Core.Objects; @@ -72,32 +73,4 @@ public override int GetHashCode() } #endregion IEquatable -} - -/// -/// Converts a path string to an IDirectoryInfo and vice versa -/// -public class AbstractionsDirectoryConverter : JsonConverter -{ - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteValue((value as IDirectoryInfo).ToString()); - } - - /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return reader.TokenType == JsonToken.String ? ExecutionContext.Instance.FileSystem.DirectoryInfo.FromDirectoryName(reader.Value?.ToString()) : null; - } - - /// - public override bool CanConvert(Type objectType) - { - Type t = (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>)) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - - return t?.FullName == typeof(ProcessBuildStep).FullName; - } } \ No newline at end of file diff --git a/core/Utilities/JsonConverters.cs b/core/Utilities/JsonConverters.cs new file mode 100644 index 00000000..4d22e25b --- /dev/null +++ b/core/Utilities/JsonConverters.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO.Abstractions; +using Cmf.CLI.Core.Objects; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Cmf.CLI.Core.Utilities +{ + /// + /// Converts a List of path string to an List of IDirectoryInfo and vice versa + /// + public class ListAbstractionsDirectoryConverter : JsonConverter + { + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + JToken token = JToken.Load(reader); + List directories = new(); + foreach (var children in token.Children()) + { + if (children.Type == JTokenType.String) + { + directories.Add(ExecutionContext.Instance.FileSystem.DirectoryInfo.FromDirectoryName(children?.ToString())); + } + } + return directories; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteStartArray(); + foreach (var directory in (value as List)) + { + writer.WriteValue(directory.ToString()); + } + writer.WriteEndArray(); + } + + public override bool CanConvert(Type objectType) + { + // CanConvert is not called when [JsonConverter] attribute is used + return false; + } + } + + /// + /// Converts a path string to an IDirectoryInfo and vice versa + /// + public class AbstractionsDirectoryConverter : JsonConverter + { + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue((value as IDirectoryInfo).ToString()); + } + + /// + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return reader.TokenType == JsonToken.String ? ExecutionContext.Instance.FileSystem.DirectoryInfo.FromDirectoryName(reader.Value?.ToString()) : null; + } + + /// + public override bool CanConvert(Type objectType) + { + Type t = (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>)) + ? Nullable.GetUnderlyingType(objectType) + : objectType; + + return t?.FullName == typeof(ProcessBuildStep).FullName; + } + } +} \ No newline at end of file diff --git a/tests/Specs/Build.cs b/tests/Specs/Build.cs index ac3d5bae..d2730887 100644 --- a/tests/Specs/Build.cs +++ b/tests/Specs/Build.cs @@ -2,6 +2,7 @@ using Cmf.CLI.Constants; using Cmf.CLI.Core.Constants; using Cmf.CLI.Core.Objects; +using Cmf.CLI.Core.Utilities; using Cmf.CLI.Factories; using Cmf.CLI.Handlers; using Cmf.CLI.Interfaces; @@ -18,6 +19,7 @@ using System.Linq; using System.Security.Policy; using Xunit; +using static Microsoft.ApplicationInsights.MetricDimensionNames.TelemetryContext; namespace tests.Specs; @@ -457,90 +459,4 @@ public void BusinessBuildWith_TestFromInputFalse_CommandWithTestTrue() businessPackageTypeHandler.Build(false); Assert.DoesNotContain("Executing 'Run Business Unit Tests'", standardOutput.ToString().Trim()); } - - [Theory] - [InlineData(true, true)] - [InlineData(false, false)] - public void DataBuild_DEEActionProjects(bool withProject, bool hasBuildSteps) - { - KeyValuePair packageRoot = new("Cmf.Custom.Package", "1.1.0"); - KeyValuePair packageData = new("Cmf.Custom.Data", "1.1.0"); - - var fileSystem = new MockFileSystem(new Dictionary - { - // project config file - { ".project-config.json", new MockFileData("")}, - - // root cmfpackage file - { $"cmfpackage.json", new MockFileData( - @$"{{ - ""packageId"": ""{packageRoot.Key}"", - ""version"": ""{packageRoot.Value}"", - ""description"": ""This package deploys Critical Manufacturing Customization"", - ""packageType"": ""Root"", - ""isInstallable"": true, - ""isUniqueInstall"": false - }}")}, - - // data cmfpackage file - { $"Cmf.Custom.Data/{CliConstants.CmfPackageFileName}", new MockFileData( - @$"{{ - ""packageId"": ""{packageData.Key}"", - ""version"": ""{packageData.Value}"", - ""description"": ""This package deploys Critical Manufacturing Customization"", - ""packageType"": ""Data"", - ""isInstallable"": true, - ""isUniqueInstall"": true, - ""contentToPack"": [ - {{ - ""source"": ""DEEs/*"", - ""target"": ""DeeRules"", - ""contentType"": ""DEE"" - }}, - ] - }}")}, - }); - - if (withProject) - { - // deeActions csproj - fileSystem.AddFile( - "Cmf.Custom.Data/DEEs/Cmf.Custom.Actions.csproj", new MockFileData( - @$" - - net6.0 - enable - enable - - ")); - - // deeActionfile - fileSystem.AddFile( - "Cmf.Custom.Data/DEEs/TestDEE.cs", new MockFileData( - @$"namespace Cmf.Custom.Actions - {{ - public class Class1 - {{ - }} - }}")); - } - - ExecutionContext.Initialize(fileSystem); - - IFileInfo cmfpackageFile = fileSystem.FileInfo.FromFileName($"Cmf.Custom.Data/{CliConstants.CmfPackageFileName}"); - DataPackageTypeHandlerV2 packageTypeHandler = PackageTypeFactory.GetPackageTypeHandler(cmfpackageFile) as DataPackageTypeHandlerV2; - - packageTypeHandler.BuildSteps - .Any(buildStep => - buildStep is DotnetCommand - && (buildStep as DotnetCommand).Command.Equals("restore") - && (buildStep as DotnetCommand).DisplayName.Equals("NuGet restore Cmf.Custom.Actions.csproj")) - .Should().Be(hasBuildSteps); - packageTypeHandler.BuildSteps - .Any(buildStep => - buildStep is DotnetCommand - && (buildStep as DotnetCommand).Command.Equals("build") - && (buildStep as DotnetCommand).DisplayName.Equals("Build Cmf.Custom.Actions.csproj")) - .Should().Be(hasBuildSteps); - } } \ No newline at end of file