diff --git a/PlatformTools/Build.MatchVerisons.cs b/PlatformTools/Build.MatchVerisons.cs new file mode 100644 index 0000000..17657d5 --- /dev/null +++ b/PlatformTools/Build.MatchVerisons.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Nuke.Common; +using Nuke.Common.ProjectModel; +using Nuke.Common.Utilities; +using PlatformTools; +using VirtoCommerce.Platform.Core.Common; +using VirtoCommerce.Platform.Core.Modularity; + +namespace VirtoCommerce.Build +{ + internal partial class Build + { + private Regex _moduleNameRegEx = new Regex(@"(VirtoCommerce.+)Module", RegexOptions.Compiled); + + public Target MatchVersions => _ => _ + .Executes(() => + { + var allPackages = new List(); + var allProjects = Solution.GetProjects("*"); + + foreach (var project in allProjects) + { + var packagesInfo = GetProjectPackages(project); + allPackages.AddRange(packagesInfo); + } + + var errors = new List(); + + var platformErrors = ValdatePlatformVersion(allPackages); + errors.AddRange(platformErrors); + + var dependencyVerionErrors = ValidateModuleDependenciesVersions(allPackages); + errors.AddRange(dependencyVerionErrors); + + var missedDependenciesErrors = ValidateForMissedDependencies(allPackages); + errors.AddRange(missedDependenciesErrors); + + if (errors.Any()) + { + ControlFlow.Fail(errors.Join(Environment.NewLine)); + } + }); + + /// + /// Get list of VirtoCommerce packages (platform and module) + /// + private IEnumerable GetProjectPackages(Project project) + { + var msBuildProject = project.GetMSBuildProject(); + + // find all VirtoCommerce references + return msBuildProject.Items + .Where(x => x.ItemType == "PackageReference" + && (x.EvaluatedInclude.StartsWith("VirtoCommerce.Platform.") || _moduleNameRegEx.IsMatch(x.EvaluatedInclude))) + .Select(x => + { + var versionMetadata = x.Metadata.FirstOrDefault(x => x.Name == "Version"); + if (versionMetadata == null) + { + return null; + } + + var name = x.EvaluatedInclude; + + return new PackageItem + { + Name = name, + Version = versionMetadata.EvaluatedValue, + ProjectName = project.Name, + IsPlatformPackage = name.StartsWith("VirtoCommerce.Platform.") + }; + }) + .Where(x => x != null); + } + + /// + /// Check match between manifest platform version and platform packages + /// + private IEnumerable ValdatePlatformVersion(IEnumerable packages) + { + return packages + .Where(package => package.IsPlatformPackage && SemanticVersion.Parse(package.Version) != SemanticVersion.Parse(ModuleManifest.PlatformVersion)) + .Select(x => + $"Mismatched platform dependency version found. Platform version: {ModuleManifest.PlatformVersion}, Platform package name: {x.Name}, platform package version: {x.Version}, project name: {x.ProjectName}"); + } + + /// + /// Check dependencies for module packages versions mismatch + /// + private IEnumerable ValidateModuleDependenciesVersions(IEnumerable packages) + { + var result = new List(); + + if (ModuleManifest.Dependencies.IsNullOrEmpty()) + { + return result; + } + + foreach (var dependency in ModuleManifest.Dependencies) + { + var errors = packages + .Where(package => !package.IsPlatformPackage + && HasNameMatch(package.Name, dependency.Id) + && SemanticVersion.Parse(package.Version) != SemanticVersion.Parse(dependency.Version)) + .Select(package => + $"Mismatched dependency version found. Dependency: {dependency.Id}, version: {dependency.Version}, Project package version: {package.Version}, project name: {package.ProjectName}"); + + result.AddRange(errors); + } + + return result; + } + + /// + /// Check project packages for missed dependency in manifest + /// + private IEnumerable ValidateForMissedDependencies(IEnumerable packages) + { + var result = new List(); + + if (ModuleManifest.Dependencies.IsNullOrEmpty()) + { + return result; + } + + foreach (var packageGroup in packages.Where(x => !x.IsPlatformPackage).GroupBy(x => x.Name)) + { + if (!ModuleManifest.Dependencies.Any(dependency => HasNameMatch(packageGroup.Key, dependency.Id))) + { + result.Add($"Dependency in module.manifest is missing. Package name: {packageGroup.Key}"); + } + } + + return result; + } + + private bool HasNameMatch(string packageName, string dependencyName) + { + var match = _moduleNameRegEx.Match(packageName); + return match.Groups.Values.Any(x => x.Value == dependencyName); + } + } +} diff --git a/PlatformTools/PackageItem.cs b/PlatformTools/PackageItem.cs new file mode 100644 index 0000000..ca90b41 --- /dev/null +++ b/PlatformTools/PackageItem.cs @@ -0,0 +1,16 @@ +namespace PlatformTools +{ + internal class PackageItem + { + public string Name { get; set; } + + public string ProjectName { get; set; } + + public string Version { get; set; } + + /// + /// Whether or not the package is a module package or a platfrom package + /// + public bool IsPlatformPackage { get; set; } + } +}