namespace Framework.Cli.Command { using Framework.Cli.Config; using Microsoft.Extensions.CommandLineUtils; using System; using System.Collections.Generic; using System.IO; /// /// Cli build command. /// internal class CommandBuild : CommandBase { public CommandBuild(AppCli appCli) : base(appCli, "build", "Build Angular client and ASP.NET Core server") { } /// /// Build Angular client only. /// internal CommandOption OptionClientOnly; /// /// Build only first Angular client from WebsiteList. /// internal CommandOption OptionClientOnlyFirst; // Exclude further ExternalGit internal CommandOption OptionServerOnly; protected internal override void Register(CommandLineApplication configuration) { OptionClientOnly = configuration.Option("-c|--client", "Build Angular website only.", CommandOptionType.NoValue); OptionServerOnly = configuration.Option("-s|--server", "Build .NET server only.", CommandOptionType.NoValue); if (Directory.Exists(UtilFramework.FolderName + "ExternalGit")) { OptionClientOnlyFirst = configuration.Option("-f|--first", "Build Angular website first only.", CommandOptionType.NoValue); } } /// /// Copy ConfigServer.json to publish folder. /// internal static void ConfigServerPublish() { string folderNamePublish = UtilFramework.FolderName + "Application.Server/bin/Debug/net5.0/publish/"; string fileNameSource = UtilFramework.FolderName + "ConfigServer.json"; string fileNameDest = folderNamePublish + "ConfigServer.json"; UtilCliInternal.FileCopy(fileNameSource, fileNameDest); } private static void BuildServer() { string folderName = UtilFramework.FolderName + "Application.Server/"; string folderNamePublish = UtilFramework.FolderName + "Application.Server/bin/Debug/net5.0/publish/"; UtilCliInternal.FolderNameDelete(folderNamePublish); UtilFramework.Assert(!Directory.Exists(folderNamePublish), "Delete folder failed!"); UtilCliInternal.DotNet(folderName, "publish"); // Use publish instead to build. UtilFramework.Assert(Directory.Exists(folderNamePublish), "Deploy failed!"); ConfigServerPublish(); } /// /// Execute npm build command. /// private static void BuildWebsiteAngular(ConfigCliWebsite website) { string folderNameAngular = UtilFramework.StringNull(UtilFramework.FolderNameParse(website.FolderNameAngular)); if (folderNameAngular != null) { string folderName = UtilFramework.FolderName + folderNameAngular; UtilCliInternal.Npm(folderName, "install --loglevel error"); // --loglevel error prevent writing to STDERR "npm WARN optional SKIPPING OPTIONAL DEPENDENCY" UtilCliInternal.Npm(folderName, "run build:ssr", isRedirectStdErr: true); // Build Server-side Rendering (SSR) to folder Framework/Application.Website/Website01/ // TODO Bug report Angular build writes to stderr. Repo steps: Delete node_modules and run npm install and then run build:ssr. } } /// /// Build all Angular Websites. For example: "Application.Website/" /// private void BuildWebsiteAngular() { var configCli = ConfigCli.Load(); string folderNameServer = UtilFramework.FolderName + "Application.Server/Framework/Application.Website/"; UtilCliInternal.FolderDelete(folderNameServer); var folderNameAngularList = new List(); foreach (var website in configCli.WebsiteList) { var folderNameAngular = UtilFramework.FolderNameParse(website.FolderNameAngular); if (folderNameAngular != null && !folderNameAngularList.Contains(folderNameAngular.ToLower())) { folderNameAngularList.Add(folderNameAngular.ToLower()); Console.WriteLine(string.Format("### Build Website (Begin) - {0}", website.DomainNameListToString())); // Delete dist folder string folderNameDist = UtilFramework.FolderName + folderNameAngular + "dist/"; UtilCliInternal.FolderDelete(folderNameDist); // npm build BuildWebsiteAngular(website); // Copy to server string folderNameDest = folderNameServer + website.FolderNameAngularWebsite; UtilCliInternal.FolderCreate(folderNameDest); UtilCliInternal.FolderCopy(folderNameDist + "application/", folderNameDest); Console.WriteLine(string.Format("### Build Website (End) - {0}", website.DomainNameListToString())); } if (OptionClientOnlyFirst.OptionGet()) { break; } } } /// /// Clone ExternalGit repo and call prebuild script. /// private static void ExternalGit() { var configCli = ConfigCli.Load(); foreach (var item in configCli.ExternalGitList) { // Clone repo var externalGit = UtilFramework.StringNull(item.ExternalGit); if (externalGit != null) { string externalFolderName = UtilFramework.FolderName + "ExternalGit/" + item.ExternalProjectName + "/"; if (!UtilCliInternal.FolderNameExist(externalFolderName)) { Console.WriteLine("Git Clone ExternalGit"); UtilCliInternal.FolderCreate(externalFolderName); externalGit += " ."; // See also: https://stackoverflow.com/questions/6224626/clone-contents-of-a-github-repository-without-the-folder-itself UtilCliInternal.Start(externalFolderName, "git", "clone --recursive -q" + " " + externalGit); // --recursive clone also submodule Framework -q do not write to stderr on linux UtilFramework.Assert(UtilCliInternal.FolderNameExist(externalFolderName), string.Format("Expected folder does not exist after git clone ({0}])!", externalFolderName)); } } } } /// /// Run method AppCli.CommandExternalGit(); on ExternalGit/ProjectName/ /// private static void CommandExternalGit() { var configCli = ConfigCli.Load(); foreach (var item in configCli.ExternalGitList) { // ExternalGit url var externalGit = UtilFramework.StringNull(item.ExternalGit); // Call cli command ExternalGit (prebuild script) var externalProjectName = UtilFramework.StringNull(item.ExternalProjectName); if (externalGit != null && externalProjectName != null) { string folderName = UtilFramework.FolderName + "ExternalGit/" + externalProjectName + "/" + "Application.Cli"; UtilCliInternal.DotNet(folderName, "run -- externalGit"); } } } protected internal override void Execute() { // Clone ExternalGit repo ExternalGit(); // Run cli ExternalGit command. Override for example custom components. if (!OptionClientOnlyFirst.OptionGet()) { CommandExternalGit(); } // Build Angular Website(s) if (OptionServerOnly.OptionGet() == false) { BuildWebsiteAngular(); } // Version tag and build Build Angular and .NET Core server. UtilCliInternal.VersionBuild(() => { if (OptionClientOnly.OptionGet() == false) { // Build .NET Core server (dotnet) BuildServer(); } }); } } }