Skip to content

Commit

Permalink
fix: support BuildablePackages on data packages
Browse files Browse the repository at this point in the history
closes #66
  • Loading branch information
joaoopereira committed Oct 25, 2022
1 parent f847bc5 commit c1fa141
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 143 deletions.
41 changes: 15 additions & 26 deletions cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
}

/// <summary>
Expand Down
28 changes: 25 additions & 3 deletions core/Objects/CmfPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -248,7 +251,7 @@ public class CmfPackage : IEquatable<CmfPackage>
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty(Order = 20)]
public PackageType? DFPackageType { get; set; }

/// <summary>
/// Gets or sets the build steps.
/// </summary>
Expand All @@ -258,6 +261,16 @@ public class CmfPackage : IEquatable<CmfPackage>
[JsonProperty(Order = 21)]
public List<ProcessBuildStep> BuildSteps { get; set; }

/// <summary>
/// Gets or sets the build packages.
/// </summary>
/// <value>
/// Packages that should be build before the context package
/// </value>
[JsonProperty(Order = 22)]
[JsonConverter(typeof(ListAbstractionsDirectoryConverter))]
public List<IDirectoryInfo> BuildablePackages { get; set; }

#endregion Public Properties

#region Private Methods
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -589,6 +602,15 @@ public bool ShouldSerializeDFPackageType()
return DFPackageType != null && PackageType == PackageType.Generic;
}

/// <summary>
/// Shoulds the serialize Buildable Packages
/// </summary>
/// <returns>returns false if Buildable Packages is null or empty</returns>
public bool ShouldSerializeBuildablePackages()
{
return BuildablePackages.HasAny();
}

#region Static Methods

/// <summary>
Expand Down Expand Up @@ -802,4 +824,4 @@ public override int GetHashCode()

#endregion Public Methods
}
}
}
29 changes: 1 addition & 28 deletions core/Objects/ProcessBuildStep.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -72,32 +73,4 @@ public override int GetHashCode()
}

#endregion IEquatable
}

/// <summary>
/// Converts a path string to an IDirectoryInfo and vice versa
/// </summary>
public class AbstractionsDirectoryConverter : JsonConverter
{
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((value as IDirectoryInfo).ToString());
}

/// <inheritdoc />
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;
}

/// <inheritdoc />
public override bool CanConvert(Type objectType)
{
Type t = (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>))
? Nullable.GetUnderlyingType(objectType)
: objectType;

return t?.FullName == typeof(ProcessBuildStep).FullName;
}
}
73 changes: 73 additions & 0 deletions core/Utilities/JsonConverters.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Converts a List of path string to an List of IDirectoryInfo and vice versa
/// </summary>
public class ListAbstractionsDirectoryConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
List<IDirectoryInfo> 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<IDirectoryInfo>))
{
writer.WriteValue(directory.ToString());
}
writer.WriteEndArray();
}

public override bool CanConvert(Type objectType)
{
// CanConvert is not called when [JsonConverter] attribute is used
return false;
}
}

/// <summary>
/// Converts a path string to an IDirectoryInfo and vice versa
/// </summary>
public class AbstractionsDirectoryConverter : JsonConverter
{
/// <inheritdoc />
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((value as IDirectoryInfo).ToString());
}

/// <inheritdoc />
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;
}

/// <inheritdoc />
public override bool CanConvert(Type objectType)
{
Type t = (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable<>))
? Nullable.GetUnderlyingType(objectType)
: objectType;

return t?.FullName == typeof(ProcessBuildStep).FullName;
}
}
}
88 changes: 2 additions & 86 deletions tests/Specs/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,6 +19,7 @@
using System.Linq;
using System.Security.Policy;
using Xunit;
using static Microsoft.ApplicationInsights.MetricDimensionNames.TelemetryContext;

namespace tests.Specs;

Expand Down Expand Up @@ -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<string, string> packageRoot = new("Cmf.Custom.Package", "1.1.0");
KeyValuePair<string, string> packageData = new("Cmf.Custom.Data", "1.1.0");

var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
// 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(
@$"<Project Sdk=""Microsoft.NET.Sdk"">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>"));

// 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);
}
}

0 comments on commit c1fa141

Please sign in to comment.