diff --git a/cmf-cli/Commands/new/iot/GenerateTaskCommand.cs b/cmf-cli/Commands/new/iot/GenerateTaskCommand.cs index c1cef1de2..65885d597 100644 --- a/cmf-cli/Commands/new/iot/GenerateTaskCommand.cs +++ b/cmf-cli/Commands/new/iot/GenerateTaskCommand.cs @@ -150,17 +150,23 @@ private TaskValues HandleTask(TaskValues task) string[] taskLibraryDependsOnProtocols = taskLibraryPkgJson.criticalManufacturing.tasksLibrary.dependsOnProtocol.ToObject(); string[] taskLibraryDependsOnScope = taskLibraryPkgJson.criticalManufacturing.tasksLibrary.dependsOnScope.ToObject(); - task.DependsOnProtocol = AnsiConsole.Prompt( - new MultiSelectionPrompt() - .Title("Is this task specific for any protocol?") - .NotRequired() - .AddChoices(taskLibraryDependsOnProtocols)); - - task.DependsOnScope = AnsiConsole.Prompt( - new MultiSelectionPrompt() - .Title("On which scopes this library can be used") - .NotRequired() - .AddChoices(taskLibraryDependsOnScope)); + if (taskLibraryDependsOnProtocols.Length > 0) + { + task.DependsOnProtocol = AnsiConsole.Prompt( + new MultiSelectionPrompt() + .Title("Is this task specific for any protocol?") + .NotRequired() + .AddChoices(taskLibraryDependsOnProtocols)); + } + + if (taskLibraryDependsOnScope.Length > 0) + { + task.DependsOnScope = AnsiConsole.Prompt( + new MultiSelectionPrompt() + .Title("On which scopes this library can be used") + .NotRequired() + .AddChoices(taskLibraryDependsOnScope)); + } if (ExecutionContext.Instance.ProjectConfig.MESVersion.Major >= 12) { diff --git a/cmf-cli/Commands/upgrade/UpgradeBaseCommand.cs b/cmf-cli/Commands/upgrade/UpgradeBaseCommand.cs index eff96cb4c..81f3e9925 100644 --- a/cmf-cli/Commands/upgrade/UpgradeBaseCommand.cs +++ b/cmf-cli/Commands/upgrade/UpgradeBaseCommand.cs @@ -57,28 +57,20 @@ public override void Configure(Command cmd) }; cmd.Add(baseVersionArgument); - var iotVersionOption = new Option("--iotVersion", "-iot") + var manifestOption = new Option("--manifest", "-m") { - Description = "New MES version for the IoT workflows & masterdatas." + Description = "The manifest file to use for the upgrade." }; - cmd.Add(iotVersionOption); - - var iotPackagesToIgnoreOption = new Option>("--iotPackagesToIgnore", "-ignore") - { - Description = "IoT packages to ignore when updating the MES version of the tasks in IoT workflows", - AllowMultipleArgumentsPerToken = true - }; - cmd.Add(iotPackagesToIgnoreOption); + cmd.Add(manifestOption); // Add the handler cmd.SetAction((parseResult, cancellationToken) => { var packagePath = parseResult.GetValue(packagePathArgument); var baseVersion = parseResult.GetValue(baseVersionArgument); - var iotVersion = parseResult.GetValue(iotVersionOption); - var iotPackagesToIgnore = parseResult.GetValue(iotPackagesToIgnoreOption); + var manifest = parseResult.GetValue(manifestOption); - Execute(packagePath, baseVersion, iotVersion, iotPackagesToIgnore); + Execute(packagePath, baseVersion, manifest); return Task.FromResult(0); }); } @@ -88,10 +80,8 @@ public override void Configure(Command cmd) /// /// The package path. /// The new Base version. - /// New MES version for the IoT workflows & masterdata - /// IoT packages to ignore when updating the MES version of the tasks in IoT workflows - /// - public void Execute(IDirectoryInfo packagePath, string baseVersion, string iotVersion, List iotPackagesToIgnore) + /// The manifest file to use for the upgrade. + public void Execute(IDirectoryInfo packagePath, string baseVersion, string manifest = null) { using var activity = ExecutionContext.ServiceProvider?.GetService()?.StartExtendedActivity(this.GetType().Name); @@ -100,29 +90,13 @@ public void Execute(IDirectoryInfo packagePath, string baseVersion, string iotVe foreach (IFileInfo path in cmfPackagePaths) { Log.Debug($"Processing {path.FullName}"); - Execute(CmfPackage.Load(path), baseVersion, iotVersion, iotPackagesToIgnore); + new UpgradeCommand(this.fileSystem).Execute(path.Directory, baseVersion, manifest); } UpdateProjectConfig(packagePath, baseVersion); Log.Warning("Don't forget to update pipeline files"); } - /// - /// Executes the specified CMF package. - /// - /// The CMF package. - /// The version. - /// New MES version for the IoT workflows & masterdata - /// IoT packages to ignore when updating the MES version of the tasks in IoT workflows - /// - public void Execute(CmfPackage cmfPackage, string version, string iotVersion, List iotPackagesToIgnore) - { - IDirectoryInfo packageDirectory = cmfPackage.GetFileInfo().Directory; - IPackageTypeHandler packageTypeHandler = PackageTypeFactory.GetPackageTypeHandler(cmfPackage); - - packageTypeHandler.UpgradeBase(version, iotVersion, iotPackagesToIgnore); - } - #region Utilities /// diff --git a/cmf-cli/Commands/upgrade/UpgradeCommand.cs b/cmf-cli/Commands/upgrade/UpgradeCommand.cs new file mode 100644 index 000000000..b2d754f5b --- /dev/null +++ b/cmf-cli/Commands/upgrade/UpgradeCommand.cs @@ -0,0 +1,84 @@ +using Cmf.CLI.Constants; +using Cmf.CLI.Core.Attributes; +using Cmf.CLI.Core.Interfaces; +using Cmf.CLI.Factories; +using System.CommandLine; +using System.IO.Abstractions; +using System.Threading.Tasks; + +namespace Cmf.CLI.Commands +{ + /// + /// Performs an upgrade of the current package + /// + /// + [CmfCommand("upgrade", Id = "upgrade", Description = "Project upgrade utilities")] + public class UpgradeCommand : BaseCommand + { + + /// + /// constructor for System.IO filesystem + /// + public UpgradeCommand() : base() + { + } + + /// + /// constructor + /// + /// + public UpgradeCommand(IFileSystem fileSystem) : base(fileSystem) + { + } + + /// + /// Configure command + /// + /// + public override void Configure(Command cmd) + { + var packagePathArgument = new Argument("packagePath") + { + Description = "Package path", + CustomParser = argResult => Parse(argResult, ".") + }; + cmd.Add(packagePathArgument); + + var baseVersionArgument = new Argument("BaseVersion") + { + Description = "New framework/MES Version" + }; + cmd.Add(baseVersionArgument); + + var manifestOption = new Option("--manifest", "-m") + { + Description = "The manifest file to use for the upgrade." + }; + cmd.Add(manifestOption); + + cmd.SetAction((parseResult) => + { + var packagePath = parseResult.GetValue(packagePathArgument); + var baseVersion = parseResult.GetValue(baseVersionArgument); + var manifest = parseResult.GetValue(manifestOption); + + Execute(packagePath, baseVersion, manifest); + return Task.FromResult(0); + }); + } + + /// + /// Executes the specified package path. + /// + /// The package path. + /// The new framework/MES version. + /// The manifest file to use for the upgrade. + public void Execute(IDirectoryInfo packagePath, string version, string manifest = null) + { + IFileInfo cmfpackageFile = this.fileSystem.FileInfo.New(this.fileSystem.Path.Combine(packagePath.FullName, CliConstants.CmfPackageFileName)); + + IPackageTypeHandler packageTypeHandler = PackageTypeFactory.GetPackageTypeHandler(cmfpackageFile); + packageTypeHandler.Upgrade(version, manifest); + } + } +} \ No newline at end of file diff --git a/cmf-cli/Handlers/PackageType/BusinessPackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/BusinessPackageTypeHandler.cs index 25ab448c6..2b24612b2 100644 --- a/cmf-cli/Handlers/PackageType/BusinessPackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/BusinessPackageTypeHandler.cs @@ -116,13 +116,10 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateCSharpProject(this.fileSystem, this.CmfPackage, version, true); } } diff --git a/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs b/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs index e12b3ab93..3e649930b 100644 --- a/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs +++ b/cmf-cli/Handlers/PackageType/DataPackageTypeHandlerV2.cs @@ -17,7 +17,7 @@ namespace Cmf.CLI.Handlers public class DataPackageTypeHandlerV2 : PackageTypeHandler { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The CMF package. public DataPackageTypeHandlerV2(CmfPackage cmfPackage) : base(cmfPackage) @@ -52,8 +52,8 @@ public DataPackageTypeHandlerV2(CmfPackage cmfPackage) : base(cmfPackage) } }); - BuildSteps = new IBuildCommand[] - { + BuildSteps = + [ new JSONValidatorCommand() { DisplayName = "JSON Validator Command", @@ -64,7 +64,7 @@ public DataPackageTypeHandlerV2(CmfPackage cmfPackage) : base(cmfPackage) DisplayName = "DEE Validator Command", FilesToValidate = GetContentToPack(this.fileSystem.DirectoryInfo.New(".")) } - }; + ]; cmfPackage.DFPackageType = PackageType.Business; // necessary because we restart the host during installation @@ -91,21 +91,13 @@ public override void Pack(IDirectoryInfo packageOutputDir, IDirectoryInfo output base.Pack(packageOutputDir, outputDir, dryRun); } - /// - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateCSharpProject(this.fileSystem, this.CmfPackage, version, true); - if (iotVersion == null) - { - return; - } - - UpgradeBaseUtilities.UpdateIoTMasterdatasAndWorkflows(this.fileSystem, this.CmfPackage, iotVersion, iotPackagesToIgnore); + UpgradeBaseUtilities.UpdateIoTMasterdataFiles(this.fileSystem, this.CmfPackage, version, manifest); } /// diff --git a/cmf-cli/Handlers/PackageType/HelpNgCliPackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/HelpNgCliPackageTypeHandler.cs index 4063009d8..b372bd857 100644 --- a/cmf-cli/Handlers/PackageType/HelpNgCliPackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/HelpNgCliPackageTypeHandler.cs @@ -191,13 +191,10 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateNPMProject(this.fileSystem, this.CmfPackage, version); // Update the version in the config.json file diff --git a/cmf-cli/Handlers/PackageType/HtmlNgCliPackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/HtmlNgCliPackageTypeHandler.cs index 137570eed..65f256e43 100644 --- a/cmf-cli/Handlers/PackageType/HtmlNgCliPackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/HtmlNgCliPackageTypeHandler.cs @@ -57,7 +57,7 @@ public HtmlNgCliPackageTypeHandler(CmfPackage cmfPackage) : base(cmfPackage) { new Step(StepType.DeployFiles) { - ContentPath = "**" // TODO: remove assets/config.json from the deployed files, should only apply transform + ContentPath = "**" }, new Step(StepType.TaggedFile) { @@ -69,14 +69,18 @@ public HtmlNgCliPackageTypeHandler(CmfPackage cmfPackage) : base(cmfPackage) ContentPath = "ngsw.json", TagFile = true }, - new Step(StepType.TaggedFile) + new Step(StepType.TransformFile) { - ContentPath = "assets/config.json", - TagFile = true + File = "config.json", + TagFile = true, + RelativePath = "assets", } } ); + // Exclude built assets/config.json from copied content + DefaultContentToIgnore.Add(CliConstants.CmfPackagePresentationConfig); + var projectRoot = FileSystemUtilities.GetProjectRoot(this.fileSystem); var tsLBOsPath = this.fileSystem.Path.Join(projectRoot.FullName, "Libs", "LBOs", "TypeScript"); var tsLBOsDir = this.fileSystem.DirectoryInfo.New(tsLBOsPath); @@ -176,13 +180,10 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateNPMProject(this.fileSystem, this.CmfPackage, version); IFileInfo projectConfig = this.fileSystem.FileInfo.New(Path.Join(this.CmfPackage.GetFileInfo().DirectoryName, "src", "assets", "config.json")); @@ -203,40 +204,53 @@ public override void UpgradeBase(string version, string iotVersion, List } } - // TODO: enable this when we can transform config.json - // public override void Pack(IDirectoryInfo packageOutputDir, IDirectoryInfo outputDir) - // { - // var filesToPack = GetContentToPack(packageOutputDir); - // if (CmfPackage.ContentToPack.HasAny() && !filesToPack.HasAny()) - // { - // throw new CliException(string.Format(CoreMessages.ContentToPackNotFound, CmfPackage.PackageId, CmfPackage.Version)); - // } - // - // if (filesToPack != null) - // { - // FilesToPack.AddRange(filesToPack); - // - // FilesToPack.ForEach(fileToPack => - // { - // Log.Debug($"Packing '{fileToPack.Source.FullName} to {fileToPack.Target.FullName} by contentToPack rule (Action: {fileToPack.ContentToPack.Action.ToString()}, Source: {fileToPack.ContentToPack.Source}, Target: {fileToPack.ContentToPack.Target})"); - // IDirectoryInfo _targetFolder = this.fileSystem.DirectoryInfo.New(fileToPack.Target.Directory.FullName); - // if (!_targetFolder.Exists) - // { - // _targetFolder.Create(); - // } - // }); - // } - // - // // TODO: replace this with an ignore entry in the ContentToPack of the template cmfpackage.json - // FilesToPack = FilesToPack.Where(ftp => !ftp.Source.FullName.EndsWith($"assets{this.fileSystem.Path.DirectorySeparatorChar}config.json")).ToList(); - // GeneratePresentationConfigFile(packageOutputDir); - // - // GenerateDeploymentFrameworkManifest(packageOutputDir); - // - // FinalArchive(packageOutputDir, outputDir); - // - // Log.Information($"{outputDir.FullName}/{CmfPackage.ZipPackageName} created"); - // - // } + /// + /// This function will pack the html package. It will also generate the config.json file in the root of the zip. + /// + public override void Pack(IDirectoryInfo packageOutputDir, IDirectoryInfo outputDir, bool dryRun = false) + { + if (!dryRun) + { + GeneratePresentationConfigFile(packageOutputDir); + } + base.Pack(packageOutputDir, outputDir, dryRun); + } + + /// + /// This function will generated the config.json using the html template. + /// This file is packed and included in the root of the zip file, which will then be applied transformation within the target environment config.json (located at /assets/config.json). + /// + private void GeneratePresentationConfigFile(IDirectoryInfo packageOutputDir) + { + Log.Debug("Generating Presentation config.json"); + + string path = this.fileSystem.Path.Join(packageOutputDir.FullName, CliConstants.CmfPackagePresentationConfig); + string fileContent = ResourceUtilities.GetEmbeddedResourceContent($"{CliConstants.FolderTemplates}/{CmfPackage.PackageType}/config.ng.json"); + + IDirectoryInfo cmfPackageDirectory = CmfPackage.GetFileInfo().Directory; + List transformInjections = new(); + + foreach (ContentToPack contentToPack in CmfPackage.ContentToPack) + { + if (contentToPack.Action == PackAction.Transform) + { + transformInjections.Add(contentToPack.Source); + } + } + + fileContent = fileContent.Replace(CliConstants.TokenVersion, CmfPackage.Version); + + string injection = string.Empty; + if (transformInjections.HasAny()) + { + // Trailing commas are required because the injection token is not the last property. + var injections = transformInjections.Select(injection => this.fileSystem.File.ReadAllText($"{cmfPackageDirectory}/{injection}") + ","); + injection = string.Join(System.Environment.NewLine, injections); + } + + fileContent = fileContent.Replace(CliConstants.TokenJDTInjection, injection); + + this.fileSystem.File.WriteAllText(path, fileContent); + } } } \ No newline at end of file diff --git a/cmf-cli/Handlers/PackageType/IoTDataPackageTypeHandlerV2.cs b/cmf-cli/Handlers/PackageType/IoTDataPackageTypeHandlerV2.cs index 1998d95ff..ae210c36f 100644 --- a/cmf-cli/Handlers/PackageType/IoTDataPackageTypeHandlerV2.cs +++ b/cmf-cli/Handlers/PackageType/IoTDataPackageTypeHandlerV2.cs @@ -4,14 +4,11 @@ using Cmf.CLI.Core.Objects; using Cmf.CLI.Utilities; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.IO.Abstractions; using System.Linq; -using System.Text.RegularExpressions; namespace Cmf.CLI.Handlers { @@ -90,23 +87,6 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) - { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); - UpgradeBaseUtilities.UpdateCSharpProject(this.fileSystem, this.CmfPackage, version, true); - - if (iotVersion == null) - { - return; - } - - UpgradeBaseUtilities.UpdateIoTMasterdatasAndWorkflows(this.fileSystem, this.CmfPackage, iotVersion, iotPackagesToIgnore); - } - /// /// Retrieves all custom iot package names /// diff --git a/cmf-cli/Handlers/PackageType/IoTPackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/IoTPackageTypeHandler.cs index 640ece42e..4bed2a8d9 100644 --- a/cmf-cli/Handlers/PackageType/IoTPackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/IoTPackageTypeHandler.cs @@ -239,13 +239,10 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateNPMProject(this.fileSystem, this.CmfPackage, version); } diff --git a/cmf-cli/Handlers/PackageType/PackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/PackageTypeHandler.cs index 099a872dd..962a8f604 100644 --- a/cmf-cli/Handlers/PackageType/PackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/PackageTypeHandler.cs @@ -498,11 +498,9 @@ public virtual void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public virtual void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) { + /// + public virtual void Upgrade(string version, string manifest = null) + { Log.Information($"Will bump {CmfPackage.PackageId}"); // Read and parse the JSON diff --git a/cmf-cli/Handlers/PackageType/TestPackageTypeHandler.cs b/cmf-cli/Handlers/PackageType/TestPackageTypeHandler.cs index a0ad3c524..cc21abcca 100644 --- a/cmf-cli/Handlers/PackageType/TestPackageTypeHandler.cs +++ b/cmf-cli/Handlers/PackageType/TestPackageTypeHandler.cs @@ -127,13 +127,10 @@ public override void Bump(string version, string versionSuffix, Dictionary - /// Bumps the Base version of the package - /// - /// The new Base version. - public override void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore) + /// + public override void Upgrade(string version, string manifest = null) { - base.UpgradeBase(version, iotVersion, iotPackagesToIgnore); + base.Upgrade(version, manifest); UpgradeBaseUtilities.UpdateCSharpProject(this.fileSystem, this.CmfPackage, version, false); } diff --git a/cmf-cli/Utilities/UpgradeBaseUtilities.cs b/cmf-cli/Utilities/UpgradeBaseUtilities.cs index 41838a2af..a5cb30bc5 100644 --- a/cmf-cli/Utilities/UpgradeBaseUtilities.cs +++ b/cmf-cli/Utilities/UpgradeBaseUtilities.cs @@ -2,15 +2,15 @@ using System.IO; using System.IO.Abstractions; using System.Linq; -using System.Reflection; using System.Text.RegularExpressions; using Cmf.CLI.Core; using Cmf.CLI.Core.Objects; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using Cmf.CLI.Core.Enums; -using System.Text.Json.Nodes; using System.Runtime.CompilerServices; +using Cmf.CLI.Builders; +using System; [assembly: InternalsVisibleTo("tests")] namespace Cmf.CLI.Utilities @@ -112,38 +112,16 @@ public static void UpdateCSharpProject(IFileSystem fileSystem, CmfPackage cmfPac } /// - /// Updates version references in IoT master data and automation workflow files - /// within a given package, skipping specific packages if configured. + /// Updates IoT Masterdata and Automation Workflows files executing the appropriate migration scripts. /// /// The file system abstraction used to access files. /// The CMF package being processed. /// The new Base version. - /// List of package names to ignore during the update (e.g., custom tasks). - public static void UpdateIoTMasterdatasAndWorkflows(IFileSystem fileSystem, CmfPackage cmfPackage, string version, List iotPackagesToIgnore) - { - /// You might be wondering why the ignorePackages starts with these three packages by default: - /// - /// When I was testing this command on a bunch of projects, - /// I noticed that the version of these template packages were being inadvertently changed on a lot of projects. - /// - /// While one is able to use the --iotPackagesToIgnore flag to ignore these packages, - /// by adding these packages to the ignore list by default we make the usage of this command more ergonomic. - - List ignorePackages = new List() - { - "@criticalmanufacturing/connect-iot-controller-engine-custom-utilities-tasks", // SMT Template - "@criticalmanufacturing/connect-iot-controller-engine-custom-smt-utilities-tasks", // SMT Template - "@criticalmanufacturing/connect-iot-utilities-semi-tasks", // Semi Template - }; - ignorePackages.AddRange(iotPackagesToIgnore ?? []); - - // Useful debug info - Log.Debug("Packages that will be ignored:"); - ignorePackages.ForEach(pkg => Log.Debug($" - {pkg}")); - - List mdlFiles = new List(); - List workflowFiles = new List(); - + /// Optional manifest file path for the migration tool. + public static void UpdateIoTMasterdataFiles(IFileSystem fileSystem, CmfPackage cmfPackage, string version, string manifest = null) + { + List args = []; + string workflowsFolder = null; foreach (ContentToPack contentToPack in cmfPackage.ContentToPack ?? []) { if (contentToPack.Source?.Contains(@"$(version)") ?? false) @@ -154,190 +132,45 @@ public static void UpdateIoTMasterdatasAndWorkflows(IFileSystem fileSystem, CmfP if (contentToPack.ContentType == ContentType.MasterData) { - mdlFiles.AddRange(fileSystem.Directory.GetFiles( - cmfPackage.GetFileInfo().DirectoryName, - contentToPack.Source, - SearchOption.AllDirectories - )); - } - else if (contentToPack.ContentType == ContentType.AutomationWorkFlows) + var mdFilePath = fileSystem.Path.GetFullPath(fileSystem.Path.Combine(cmfPackage.GetFileInfo().DirectoryName, contentToPack.Source)).Replace("*", ""); + args.Add(mdFilePath); + } else if (contentToPack.ContentType == ContentType.AutomationWorkFlows) { - workflowFiles.AddRange(fileSystem.Directory.GetFiles( - cmfPackage.GetFileInfo().DirectoryName, - contentToPack.Source, - SearchOption.AllDirectories - )); + workflowsFolder = fileSystem.Path.GetFullPath(fileSystem.Path.Combine(cmfPackage.GetFileInfo().DirectoryName, contentToPack.Source)).Replace("*", ""); } } - if (mdlFiles.Where(mdl => !mdl.EndsWith(".json")).Any()) - { - Log.Warning("Only .json masterdata files will be updated"); - } - - // Update the MES references that might be present in the mdl files - foreach (string mdlPath in mdlFiles.Where(mdl => mdl.EndsWith(".json"))) - { - UpdateIoTMasterdata(mdlPath, fileSystem, cmfPackage, version, ignorePackages); - } - - Log.Debug("Processing workflows..."); - // Update the IoT workflows - foreach (string wflPath in workflowFiles.Where(path => path.EndsWith(".json"))) - { - UpdateIoTWorkflow(wflPath, fileSystem, cmfPackage, version, ignorePackages); - } - } - - /// - /// Updates version values in a given IoT master data (.json) file. - /// - /// Path to the master data file. - /// The file system abstraction used to access files. - /// The CMF package that owns the master data. - /// The new Base version. - /// List of task package names to ignore. - private static void UpdateIoTMasterdata(string mdlPath, IFileSystem fileSystem, CmfPackage cmfPackage, string version, List ignorePackages) - { - // Update some versions in several places in the masterdata - string text = fileSystem.File.ReadAllText(mdlPath); - foreach (string key in new string[] { "PackageVersion", "ControllerPackageVersion", "MonitorPackageVersion", "ManagerPackageVersion" }) - { - text = UpgradeBaseUtilities.UpdateJsonValue(text, key, version); - } - - // Updating the versions in AutomationController requires special handling - JObject packageJsonObject = JsonConvert.DeserializeObject(text); - - if (packageJsonObject.ContainsKey("AutomationController")) + if (!string.IsNullOrEmpty(workflowsFolder)) { - JObject automationControllers = packageJsonObject["AutomationController"] as JObject; - - foreach (JProperty prop in automationControllers.Properties()) - { - UpdateTaskLibraryPackageJson(prop, version, ignorePackages); - } + args.AddRange(["--workflowsFolder", workflowsFolder]); } - SerializeWithOriginalIndentation(mdlPath, text, packageJsonObject, fileSystem); - } - - /// - /// Updates the version of package strings listed in the "TasksLibraryPackages" field of a given AutomationController JSON property. - /// - /// The JSON property representing a controller entry within the "AutomationController" object. - /// The new version string to apply to all eligible package entries. - /// A list of package name substrings to exclude from version updates. - /// Any package string that contains a substring from this list will be skipped. - /// - /// - /// The "TasksLibraryPackages" field may be stored either as a JSON array or as a stringified JSON array. - /// This method detects the format and updates the version suffix (e.g., "@11.1.3") for each package string, - /// while preserving the original format of the field (string or array). I have no idea why are two different - /// formats are allowed in this field, but now we're stuck supporting them both - /// - private static void UpdateTaskLibraryPackageJson(JProperty prop, string version, List ignorePackages) - { - JObject controller = (JObject)prop.Value; - JToken tasksLibraryPackagesToken = controller["TasksLibraryPackages"]; - - if (tasksLibraryPackagesToken == null || tasksLibraryPackagesToken.Type == JTokenType.Null) + if (!string.IsNullOrEmpty(manifest)) { - return; + args.AddRange(["--manifest", manifest]); } - JArray tasksLibraryPackages = null; - bool wasStringFormat = false; + args.AddRange(["--registry", ExecutionContext.Instance.ProjectConfig.NPMRegistry.ToString()]); + args.AddRange(["--version", version]); - if (tasksLibraryPackagesToken.Type == JTokenType.String) + var npxCommand = new NPXCommand { - string rawString = tasksLibraryPackagesToken.ToString(); - if (!string.IsNullOrWhiteSpace(rawString)) - { - tasksLibraryPackages = JsonConvert.DeserializeObject(rawString); - wasStringFormat = true; - } - } - else if (tasksLibraryPackagesToken.Type == JTokenType.Array) - { - tasksLibraryPackages = (JArray)tasksLibraryPackagesToken; - } - - if (tasksLibraryPackages == null) - { - return; - } - - for (int i = 0; i < tasksLibraryPackages.Count; i++) - { - string packageStr = tasksLibraryPackages[i]?.ToString(); - - if (string.IsNullOrEmpty(packageStr) || ignorePackages.Any(ignore => packageStr.Contains(ignore))) - { - continue; - } - tasksLibraryPackages[i] = Regex.Replace(packageStr, @"@\d+.*$", $"@{version}"); - } - - if (wasStringFormat) - { - // Write back as a compact JSON string - controller["TasksLibraryPackages"] = JsonConvert.SerializeObject(tasksLibraryPackages, Formatting.None); - } - else - { - // Preserve original JArray structure - controller["TasksLibraryPackages"] = tasksLibraryPackages; - } - } - - /// - /// Updates the package version references in an IoT automation workflow file, - /// skipping any package names included in the ignore list. - /// - /// Path to the workflow .json file. - /// The file system abstraction used to access files. - /// The CMF package that owns the workflow. - /// The new Base version. - /// List of task package names to skip when applying the version update. - private static void UpdateIoTWorkflow(string wflPath, IFileSystem fileSystem, CmfPackage cmfPackage, string version, List ignorePackages) - { - Log.Debug($" - {wflPath}"); - string packageJson = fileSystem.File.ReadAllText(wflPath); - dynamic packageJsonObject = JsonConvert.DeserializeObject(packageJson); - - if (!packageJsonObject.ContainsKey("tasks")) - { - throw new CliException(string.Format(CoreMessages.MissingMandatoryPropertyInFile, "tasks", wflPath)); - } - if (!packageJsonObject.ContainsKey("converters")) - { - throw new CliException(string.Format(CoreMessages.MissingMandatoryPropertyInFile, "converters", wflPath)); - } + Command = "workflow-migration-tool", + Args = [.. args], + ForceColorOutput = true, + DisplayName = "Workflow Migration Tool", + WorkingDirectory = fileSystem.Directory.GetParent(cmfPackage.GetFileInfo().FullName) + }; - foreach (var task in packageJsonObject?["tasks"]) + try { - string name = (string)task["reference"]["package"]["name"]; - if (ignorePackages.Any(ignore => name.Contains(ignore))) - { - continue; // If there's a match with a package in the ignorePackages, skip the version bump - } - - task["reference"]["package"]["version"] = version; + npxCommand.Exec(); + Log.Information("Migration complete."); } - - foreach (var converter in packageJsonObject?["converters"]) + catch (Exception ex) { - string name = (string)converter["reference"]["package"]["name"]; - if (ignorePackages.Any(ignore => name.Contains(ignore))) - { - continue; // If there's a match with a package in the ignorePackages, skip the version bump - } - - converter["reference"]["package"]["version"] = version; + throw new CliException($"Workflow migration failed: {ex.Message}"); } - - SerializeWithOriginalIndentation(wflPath, packageJson, packageJsonObject, fileSystem); } /// diff --git a/cmf-cli/resources/templateFiles/HTML/config.ng.json b/cmf-cli/resources/templateFiles/HTML/config.ng.json index 0e2c2421c..2e48c085f 100644 --- a/cmf-cli/resources/templateFiles/HTML/config.ng.json +++ b/cmf-cli/resources/templateFiles/HTML/config.ng.json @@ -1,5 +1,4 @@ { $(JDTInjection) - "cacheId": "$(cacheId)", "customizationVersion": "$(version)" } \ No newline at end of file diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.eslintrc.json b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.eslintrc.json new file mode 100644 index 000000000..b67fe06cb --- /dev/null +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": [ + "../../.eslintrc.json" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "parserOptions": { + "project": [ + "tsconfig.json", + "test/unit/tsconfig.json" + ], + "createDefaultProgram": false + } + } + ] +} diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.gitignore b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.gitignore index 21ef0acd4..42344e5cf 100644 --- a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.gitignore +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/.gitignore @@ -49,4 +49,5 @@ test/e2e/obj/ test/**/bin !font/**/*.css -!font/svg/font.js \ No newline at end of file +!font/svg/font.js +__TEMP__ \ No newline at end of file diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/package.json b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/package.json index 1ac3d2238..2acd473a9 100644 --- a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/package.json +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/package.json @@ -35,7 +35,9 @@ "mocha-lcov-reporter": "1.3.0", "mocha-multi-reporters": "1.5.1", "tslint": "6.1.3", - "typescript": "5.2.2" + "typescript": "5.2.2", + "cmf-lbos": "<%= $CLI_PARAM_TargetSystemVersionProcessed %>", + "cmf-core-chatbot": "<%= $CLI_PARAM_TargetSystemVersionProcessed %>" }, "dependencies": { "inversify": "6.0.2", diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/scripts/dummy.ts b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/scripts/dummy.ts new file mode 100644 index 000000000..02f04ed4c --- /dev/null +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/scripts/dummy.ts @@ -0,0 +1,14 @@ +import { ScriptScopeBase } from "../types/globals"; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +class DummyWrapper extends ScriptScopeBase { + [key: string]: any; + + private dummy() { + // PackagePacker: Start of Script + (async () => { + })(); + // PackagePacker: End of Script + } +} + diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/types/globals.ts b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/types/globals.ts new file mode 100644 index 000000000..1b578df56 --- /dev/null +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/scenarios/types/globals.ts @@ -0,0 +1,42 @@ +// --------------------------------------------------------------------------- +// ScriptScopeBase — extend this in every wrapper class +// --------------------------------------------------------------------------- + +import { ScriptScopeLboUtilities } from "cmf-core-chatbot/lib/side-bar-bot/script-executer/scope.lbo.utilities"; +import { ScriptScopeIoTUtilities } from "cmf-core-chatbot/lib/side-bar-bot/script-executer/scope.iot.utilities"; +import { MasterdataDirector } from "cmf-core-chatbot/lib/side-bar-bot/script-executer/scope.masterdata.utilities"; +import { ControlFlowBuilder, WorkflowBuilder } from "cmf-core-chatbot/lib/side-bar-bot/script-executer/scope.workflow-builder.utilities"; +import { Cmf } from "cmf-lbos"; +import { DataType } from "cmf-core-chatbot/lib/side-bar-bot/script-executer/utils"; +/** + * Base class that provides typed access to all runtime-injected utilities. + * + * Usage: + * ```ts + * class MyScriptWrapper extends ScriptScopeBase { + * [key: string]: any; + * private myScript() { ... } + * } + * ``` + */ +declare class ScriptScopeBase { + /** Orchestrates creation of protocols, driver definitions, and controllers. */ + masterdataDirector: MasterdataDirector; + + /** Builds and manages automation workflows composed of tasks. */ + workflowBuilder: ControlFlowBuilder; + + /** Utilities for IoT entities, events, properties, and commands. */ + iotUtilities: ScriptScopeIoTUtilities; + + /** Utilities for LBO data, state models, and master data. */ + lboUtilities: ScriptScopeLboUtilities; + + /** Answers collected from the user during the business scenario wizard. */ + answers: Record; + + /** Low-level system call accessor (CMF service layer). */ + System: any; +} + +export { ScriptScopeBase }; \ No newline at end of file diff --git a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/tsconfig.json b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/tsconfig.json index b8790b1b4..cf4e4a81a 100644 --- a/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/tsconfig.json +++ b/cmf-cli/resources/template_feed/iot/businessScenarios/src/%directoryname%/tsconfig.json @@ -1,32 +1,35 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "lib": [ - "es2017", - "dom" - ], - "sourceMap": true, - "forceConsistentCasingInFileNames": true, - "noImplicitReturns": false, - "declaration": true, - "pretty": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "moduleResolution": "node", - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - // strict rules: - "noImplicitAny": false, - "noImplicitThis": false, - "alwaysStrict": true, - "strictBindCallApply": false, - "strictNullChecks": false, - "strictFunctionTypes": false, - "strictPropertyInitialization": false - }, - "exclude": [ - "node_modules", - "scenarios" - ] + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": [ + "es2017", + "dom" + ], + "sourceMap": true, + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": false, + "declaration": true, + "pretty": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + // strict rules: + "noImplicitAny": false, + "noImplicitThis": false, + "alwaysStrict": true, + "strictBindCallApply": false, + "strictNullChecks": false, + "strictFunctionTypes": false, + "strictPropertyInitialization": false + }, + "exclude": [ + "node_modules" + ], + "include": [ + "scenarios/scripts/**/*.ts", + "scenarios/scripts/**/*.d.ts" + ] } \ No newline at end of file diff --git a/cmf-cli/resources/template_feed/iot/taskLibrary/src/%directoryname%/.gitignore b/cmf-cli/resources/template_feed/iot/taskLibrary/src/%directoryname%/.gitignore index 21ef0acd4..42344e5cf 100644 --- a/cmf-cli/resources/template_feed/iot/taskLibrary/src/%directoryname%/.gitignore +++ b/cmf-cli/resources/template_feed/iot/taskLibrary/src/%directoryname%/.gitignore @@ -49,4 +49,5 @@ test/e2e/obj/ test/**/bin !font/**/*.css -!font/svg/font.js \ No newline at end of file +!font/svg/font.js +__TEMP__ \ No newline at end of file diff --git a/core/Interfaces/IPackageTypeHandler.cs b/core/Interfaces/IPackageTypeHandler.cs index 583f4da3c..5be12657b 100644 --- a/core/Interfaces/IPackageTypeHandler.cs +++ b/core/Interfaces/IPackageTypeHandler.cs @@ -29,9 +29,8 @@ public interface IPackageTypeHandler /// Bumps the Base version of the package /// /// The new Base version. - /// New MES version for the IoT workflows & masterdata - /// IoT packages to ignore when updating the MES version of the tasks in IoT workflows - public abstract void UpgradeBase(string version, string iotVersion, List iotPackagesToIgnore); + /// The manifest file to use for the upgrade. + public abstract void Upgrade(string version, string manifest = null); /// /// Builds this instance. diff --git a/core/Utilities/IoTUtilities.cs b/core/Utilities/IoTUtilities.cs index 5848f8113..3ed5b781f 100644 --- a/core/Utilities/IoTUtilities.cs +++ b/core/Utilities/IoTUtilities.cs @@ -64,7 +64,7 @@ public static void BumpWorkflowFiles(string group, string version, string versio } /// - /// Bumps the io t master data. + /// Bumps the iot master data. /// /// The automation workflow file group. /// The version. @@ -142,7 +142,7 @@ public static void BumpIoTMasterData(string automationWorkflowFileGroup, string } string[] xmlMasterDatas = fileSystem.Directory.GetFiles(parentDirectory.FullName, "*.xml"); - string[] xlsxMasterDatas = fileSystem.Directory.GetFiles(parentDirectory.FullName, "*.xml"); + string[] xlsxMasterDatas = fileSystem.Directory.GetFiles(parentDirectory.FullName, "*.xlsx"); if (xmlMasterDatas == null || xmlMasterDatas.Length == 0) { diff --git a/tests/Objects/MockPackage.cs b/tests/Objects/MockPackage.cs index a8b8e422e..968c26b0f 100644 --- a/tests/Objects/MockPackage.cs +++ b/tests/Objects/MockPackage.cs @@ -36,6 +36,7 @@ internal static class MockPackage ""name"": ""customization.package"" }")}, { MockUnixSupport.Path(@"c:\ui\src\packages\customization.common\customization.common.js"), new MockFileData(string.Empty)}, + { MockUnixSupport.Path(@"c:\ui\transform\my-config-patch.json"), new MockFileData("\"jdttest\": true")}, // adding jdtinjection file { MockUnixSupport.Path(@"c:\ui\package.json"), new MockFileData( @"{ ""name"": ""customization.package"" @@ -55,6 +56,10 @@ internal static class MockPackage ""ignoreFiles"": [ "".npmignore"" ] + }}, + {{ + ""source"": ""{MockUnixSupport.Path("transform\\my-config-patch.json").Replace("\\", "\\\\")}"", + ""action"": ""Transform"" }} ] }}")}}); diff --git a/tests/Specs/New.cs b/tests/Specs/New.cs index 6aa8a10b7..5ecb7528f 100644 --- a/tests/Specs/New.cs +++ b/tests/Specs/New.cs @@ -600,8 +600,8 @@ public void IoTTask(string mesVersion, string taskBaseClass) consoleTask.Input.PushTextWithEnter(""); // icon class name (default) consoleTask.Input.PushTextWithEnter(""); // isProtocol: No (default false) consoleTask.Input.PushTextWithEnter(""); // lifecycle: Productive (first selection prompt option) - consoleTask.Input.PushTextWithEnter(""); // dependsOnProtocol (MultiSelect) - consoleTask.Input.PushTextWithEnter(""); // dependsOnScope (MultiSelect, 1 choice "ConnectIoT"): no selection + confirm + // dependsOnProtocol is skipped: task library has no protocols (empty list from library setup) + consoleTask.Input.PushTextWithEnter(""); // dependsOnScope MultiSelect (library has ["ConnectIoT"]): no selection + confirm if (isMesV12) { diff --git a/tests/Specs/Pack.cs b/tests/Specs/Pack.cs index 5c0a79056..1b9f803a2 100644 --- a/tests/Specs/Pack.cs +++ b/tests/Specs/Pack.cs @@ -294,6 +294,7 @@ public void HTML() List expectedFiles = new() { "manifest.xml", + "config.json", "node_modules/customization.package/package.json", "node_modules/customization.package/customization.common.js" }; @@ -302,6 +303,27 @@ public void HTML() { Assert.NotNull(entriesToExtract.FirstOrDefault(x => x.Item2.Equals(expectedFile))); } + + Assert.Null(entriesToExtract.FirstOrDefault(x => x.Item2.Equals("assets/config.json"))); + + var manifestEntry = zip.GetEntry("manifest.xml"); + Assert.NotNull(manifestEntry); + using (var manifestStream = manifestEntry.Open()) + using (var manifestReader = new StreamReader(manifestStream)) + { + var manifestXmlContent = manifestReader.ReadToEnd(); + Assert.Contains("", manifestXmlContent); + } + + var configEntry = zip.GetEntry("config.json"); + Assert.NotNull(configEntry); + using (var configStream = configEntry.Open()) + using (var configReader = new StreamReader(configStream)) + { + var configJsonContent = configReader.ReadToEnd(); + Assert.Contains("\"customizationVersion\": \"1.1.0\"", configJsonContent); + Assert.Contains("\"jdttest\": true", configJsonContent); + } } } } diff --git a/tests/Specs/Upgrade.cs b/tests/Specs/Upgrade.cs new file mode 100644 index 000000000..b3dcbdb24 --- /dev/null +++ b/tests/Specs/Upgrade.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using System.IO.Abstractions.TestingHelpers; +using Cmf.CLI.Commands; +using FluentAssertions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; + +namespace tests.Specs; + +public class Upgrade +{ + [Fact] + public void RootPackage() + { + string version = "11.1.6"; + + var fileSystem = new MockFileSystem(new Dictionary + { + { + "/cmfpackage.json", + new MockFileData( + @"{ + ""packageId"": ""Cmf.SMT.Package"", + ""version"": ""3.2.0"", + ""description"": ""Root package"", + ""packageType"": ""Root"", + ""isInstallable"": true, + ""isUniqueInstall"": false, + ""dependencies"": [ + { + ""id"": ""DS.ClickHouse.Workaround"", + ""version"": ""1.2.0"" + }, + { + ""id"": ""Cmf.Environment"", + ""version"": ""11.1.3"" + }, + { + ""id"": ""criticalmanufacturing.deploymentmetadata"", + ""version"": ""11.1.3"" + }, + { + ""id"": ""CriticalManufacturing.DeploymentMetadata"", + ""version"": ""11.1.3"" + } + ] + }" + ) + }, + }); + + var cmd = new UpgradeCommand(fileSystem); + cmd.Execute(fileSystem.DirectoryInfo.New("/"), version); + + string rootCmfpackageContents = fileSystem.File.ReadAllText("/cmfpackage.json"); + JObject rootCmfpackageObject = (JObject)JsonConvert.DeserializeObject(rootCmfpackageContents); + + rootCmfpackageObject["dependencies"][0]["version"].ToString().Should().Be("1.2.0"); + rootCmfpackageObject["dependencies"][1]["version"].ToString().Should().Be(version); + rootCmfpackageObject["dependencies"][2]["version"].ToString().Should().Be(version); + rootCmfpackageObject["dependencies"][3]["version"].ToString().Should().Be(version); + } + + [Fact] + public void BusinessPackage() + { + string version = "11.1.6"; + + var fileSystem = new MockFileSystem(new Dictionary + { + { + "/Business/cmfpackage.json", + new MockFileData( + @"{ + ""packageId"": ""Cmf.SMT.Business"", + ""version"": ""3.2.0"", + ""description"": ""Business Package"", + ""packageType"": ""Business"", + ""isInstallable"": true, + ""isUniqueInstall"": false + }" + ) + }, + { + "/Business/Common/a.b.c.csproj", + new MockFileData( + @" + + + + + + + + + " + ) + } + }); + + var cmd = new UpgradeCommand(fileSystem); + cmd.Execute(fileSystem.DirectoryInfo.New("/Business"), version); + + string csprojContents = fileSystem.File.ReadAllText("/Business/Common/a.b.c.csproj"); + csprojContents.Should().Contain($@""); + csprojContents.Should().Contain($@""); + csprojContents.Should().Contain($@""); + csprojContents.Should().Contain(@""); + } + + [Fact] + public void TestPackage() + { + string version = "11.1.6"; + + var fileSystem = new MockFileSystem(new Dictionary + { + { + "/cmfpackage.json", + new MockFileData( + @"{ + ""packageId"": ""Cmf.SMT.Tests"", + ""version"": ""3.2.0"", + ""description"": ""Tests Package"", + ""packageType"": ""Tests"", + ""isInstallable"": false, + ""isUniqueInstall"": false + }" + ) + }, + { + "/Common/a.b.c.csproj", + new MockFileData( + @" + + + + + + + + " + ) + } + }); + + var cmd = new UpgradeCommand(fileSystem); + cmd.Execute(fileSystem.DirectoryInfo.New("/"), version); + + string csprojContents = fileSystem.File.ReadAllText("/Common/a.b.c.csproj"); + csprojContents.Should().Contain($@""); + } +} \ No newline at end of file diff --git a/tests/Specs/UpgradeBase.cs b/tests/Specs/UpgradeBase.cs index 97f2caf80..ef6576899 100644 --- a/tests/Specs/UpgradeBase.cs +++ b/tests/Specs/UpgradeBase.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO.Abstractions.TestingHelpers; using System.Linq; @@ -53,7 +52,7 @@ public void ProjectConfig() }); UpgradeBaseCommand cmd = new UpgradeBaseCommand(fileSystem); - cmd.Execute(fileSystem.FileInfo.New(projectConfigPath).Directory, "11.1.6", "11.1.6", []); + cmd.Execute(fileSystem.FileInfo.New(projectConfigPath).Directory, "11.1.6", "11.1.6"); string projectConfigContents = fileSystem.File.ReadAllText(projectConfigPath); @@ -176,10 +175,8 @@ public void BusinessPackage() ) } }); - - UpgradeBaseCommand cmd = new UpgradeBaseCommand(fileSystem); - cmd.Execute(fileSystem.DirectoryInfo.New("/"), version, version, []); + cmd.Execute(fileSystem.DirectoryInfo.New("/"), version); string rootCmfpackageContents = fileSystem.File.ReadAllText("/cmfpackage.json"); @@ -207,13 +204,10 @@ public void BusinessPackage() } - [Theory] - [InlineData(true)] - [InlineData(false)] - public void DataPackage(bool iotShouldBeUpdated) + [Fact] + public void DataPackage() { string version = "11.1.6"; - string iotVersion = "11.1.6-123"; var fileSystem = new MockFileSystem(new Dictionary { @@ -508,50 +502,15 @@ public void DataPackage(bool iotShouldBeUpdated) } }); - UpgradeBaseCommand cmd = new UpgradeBaseCommand(fileSystem); - cmd.Execute(fileSystem.DirectoryInfo.New(@"/"), version, iotShouldBeUpdated ? iotVersion : null, ["ignore-this-package"]); + ExecutionContext.Initialize(fileSystem); + + UpgradeBaseUtilities.UpdateCSharpProject(fileSystem, new CmfPackage(fileSystem.FileInfo.New("/cmfpackage.json")), version, true); string csprojContents = fileSystem.File.ReadAllText(@"/DEEs/a.b.c.csproj"); csprojContents.Should().Contain( $@"" ); - if (iotShouldBeUpdated) - { - #region Masterdata validations - string mdlContents = fileSystem.File.ReadAllText(@"/MasterData/a.json"); - mdlContents.Should().ContainAll([ - $@"""PackageVersion"": ""{iotVersion}""", - $@"""MonitorPackageVersion"": ""{iotVersion}""", - $@"""ManagerPackageVersion"": ""{iotVersion}""", - $@"""ControllerPackageVersion"": ""{iotVersion}""", - $@"@criticalmanufacturing/connect-iot-controller-engine-core-tasks@{iotVersion}", - $@"@criticalmanufacturing/connect-iot-random@{iotVersion}", - $@"@criticalmanufacturing/connect-iot-controller-engine-custom-utilities-tasks@5.4.3", // The industry templates iot packages should remain unchanged - $@"@criticalmanufacturing/connect-iot-controller-engine-custom-smt-utilities-tasks@5.4.3", - $@"@criticalmanufacturing/connect-iot-utilities-semi-tasks@5.4.3", - ]); - Assert.Equal(7, Regex.Matches(mdlContents, iotVersion.Replace(".", "\\.")).Count); - #endregion IoT Masterdata validations - - #region Workflow validations - string wflContents = fileSystem.File.ReadAllText(@"/AutomationWorkFlows/workflow.json"); - JObject workflowJsonObject = (JObject)JsonConvert.DeserializeObject(wflContents); - - // Tasks - workflowJsonObject["tasks"][0]["reference"]["package"]["version"].ToString().Should().Be(iotVersion); - workflowJsonObject["tasks"][1]["reference"]["package"]["version"].ToString().Should().Be("11.1.5"); - workflowJsonObject["tasks"][2]["reference"]["package"]["version"].ToString().Should().Be(iotVersion); - - // Converters - workflowJsonObject["converters"][0]["reference"]["package"]["version"].ToString().Should().Be(iotVersion); - workflowJsonObject["converters"][1]["reference"]["package"]["version"].ToString().Should().Be("1.2.3"); - - Assert.Equal(3, Regex.Matches(wflContents, iotVersion.Replace(".", "\\.")).Count); - Assert.Single(Regex.Matches(wflContents, "11.1.5".Replace(".", "\\."))); // Ignored task - Assert.Single(Regex.Matches(wflContents, "1.2.3".Replace(".", "\\."))); // Ignored converter - #endregion IoT Workflow validations - } } [Theory] @@ -778,10 +737,8 @@ public void TestPackage() ) } }); - - UpgradeBaseCommand cmd = new UpgradeBaseCommand(fileSystem); - cmd.Execute(fileSystem.DirectoryInfo.New("/"), version, null, []); + cmd.Execute(fileSystem.DirectoryInfo.New("/"), version); string csprojContents = fileSystem.File.ReadAllText("/Common/a.b.c.csproj"); csprojContents.Should().Contain(