Beispiel #1
0
        public static void Publish(this IDvinApp dvinApp, IFileSystemService fileSystemService, bool ignoreMissingReleaseBuild, IErrorsAndInfos errorsAndInfos)
        {
            if (!ignoreMissingReleaseBuild && !dvinApp.HasAppBeenBuiltAfterLatestSourceChanges(fileSystemService))
            {
                errorsAndInfos.Errors.Add($"No release build for dvin app {dvinApp.Id}");
                return;
            }

            if (!fileSystemService.FolderExists(dvinApp.PublishFolder))
            {
                errorsAndInfos.Errors.Add($"Folder \"{dvinApp.PublishFolder}\" not found");
                return;
            }

            if (!fileSystemService.FolderExists(dvinApp.SolutionFolder))
            {
                errorsAndInfos.Errors.Add($"Folder \"{dvinApp.SolutionFolder}\" not found");
                return;
            }

            var publishedFiles  = Artifacts(fileSystemService, new Folder(dvinApp.PublishFolder));
            var lastPublishedAt = publishedFiles.Any() ? publishedFiles.Max(f => fileSystemService.LastWriteTime(f)) : DateTime.Now;

            MakeCopiesOfAssemblies(new Folder(dvinApp.PublishFolder), fileSystemService);

            var projectFile = fileSystemService.ListFilesInDirectory(new Folder(dvinApp.SolutionFolder), "*.csproj", SearchOption.AllDirectories).FirstOrDefault(f => f.EndsWith(dvinApp.Id + ".csproj"));

            if (projectFile == null)
            {
                errorsAndInfos.Errors.Add($"No project file found for dvin app {dvinApp.Id} (must end with {dvinApp.Id}.csproj)");
                return;
            }

            var processStarter = new ProcessStarter();
            var arguments      = $"publish \"{projectFile}\" -c Release --no-restore -o \"{dvinApp.PublishFolder}\"";

            using (var process = processStarter.StartProcess("dotnet", arguments, "", errorsAndInfos)) {
                if (process != null)
                {
                    processStarter.WaitForExit(process);
                }
            }

            if (errorsAndInfos.Infos.Any(i => i.Contains("Could not copy")))
            {
                errorsAndInfos.Errors.Add($"The publish process could not copy files for dvin app {dvinApp.Id}, make sure dotnet and the app are not running");
                return;
            }

            publishedFiles = Artifacts(fileSystemService, new Folder(dvinApp.PublishFolder));
            if (!publishedFiles.Any() || lastPublishedAt >= publishedFiles.Max(f => fileSystemService.LastWriteTime(f)))
            {
                errorsAndInfos.Errors.Add($"Nothing was published for dvin app {dvinApp.Id}");
            }

            DeleteUnusedFileCopies(new Folder(dvinApp.PublishFolder), fileSystemService);
        }
Beispiel #2
0
 public static async Task ResolveFoldersAsync(this IDvinApp dvinApp, IFolderResolver folderResolver, IErrorsAndInfos errorsAndInfos)
 {
     dvinApp.AreFoldersBeingResolved = true;
     dvinApp.SolutionFolder          = (await folderResolver.ResolveAsync(dvinApp.SolutionFolder, errorsAndInfos)).FullName;
     dvinApp.ReleaseFolder           = (await folderResolver.ResolveAsync(dvinApp.ReleaseFolder, errorsAndInfos)).FullName;
     dvinApp.PublishFolder           = (await folderResolver.ResolveAsync(dvinApp.PublishFolder, errorsAndInfos)).FullName;
     dvinApp.ExceptionLogFolder      = (await folderResolver.ResolveAsync(dvinApp.ExceptionLogFolder, errorsAndInfos)).FullName;
     dvinApp.AreFoldersBeingResolved = false;
 }
Beispiel #3
0
        public static bool IsPortListenedTo(this IDvinApp dvinApp)
        {
            var processStarter = new ProcessStarter();
            var errorsAndInfos = new ErrorsAndInfos();

            using var process = processStarter.StartProcess("netstat", "-n -a", "", errorsAndInfos);
            if (process != null)
            {
                processStarter.WaitForExit(process);
            }

            return(errorsAndInfos.Infos.Any(i => i.Contains("TCP") && (i.Contains("LISTENING") || i.Contains("ABHÖREN") || i.Contains("ABH™REN")) && i.Contains($":{dvinApp.Port} ")));
        }
Beispiel #4
0
        public static Process Start(this IDvinApp dvinApp, IFileSystemService fileSystemService, IErrorsAndInfos errorsAndInfos)
        {
            if (dvinApp.IsPortListenedTo())
            {
                errorsAndInfos.Errors.Add($"Another process already listens to port {dvinApp.Port}");
                return(null);
            }

            if (!fileSystemService.FolderExists(dvinApp.PublishFolder))
            {
                errorsAndInfos.Errors.Add($"Folder \"{dvinApp.PublishFolder}\" not found");
                return(null);
            }

            var runner  = new ProcessStarter();
            var process = runner.StartProcess("dotnet", dvinApp.Executable, dvinApp.PublishFolder, errorsAndInfos);

            return(process);
        }
        private async Task <bool> StartAppAndReturnSuccess(IDvinApp dvinApp)
        {
            var fileSystemService = new FileSystemService();
            var errorsAndInfos    = new ErrorsAndInfos();

            if (!dvinApp.HasAppBeenPublishedAfterLatestSourceChanges(fileSystemService))
            {
                dvinApp.Publish(fileSystemService, true, errorsAndInfos);
                if (errorsAndInfos.AnyErrors())
                {
                    await NavigateToMessage(string.Join("<br>", errorsAndInfos.Errors));

                    return(false);
                }
            }

            if (!dvinApp.HasAppBeenPublishedAfterLatestSourceChanges(fileSystemService))
            {
                await NavigateToMessage($"{Constants.BackbendAppId} has not been published since the latest source code changes");

                return(false);
            }

            vProcess = dvinApp.Start(fileSystemService, errorsAndInfos);
            Wait.Until(() => dvinApp.IsPortListenedTo(), TimeSpan.FromSeconds(30));
            if (errorsAndInfos.AnyErrors())
            {
                await NavigateToMessage(string.Join("<br>", errorsAndInfos.Errors));

                return(false);
            }

            if (dvinApp.IsPortListenedTo())
            {
                return(true);
            }

            await NavigateToMessage($"{Constants.BackbendAppId} started but not listening");

            return(false);
        }
Beispiel #6
0
        public static DateTime LastPublishedAt(this IDvinApp dvinApp, IFileSystemService fileSystemService)
        {
            var publishedFiles = Artifacts(fileSystemService, new Folder(dvinApp.PublishFolder));

            return(publishedFiles.Any() ? publishedFiles.Max(f => fileSystemService.LastWriteTime(f)) : DateTime.Now);
        }
Beispiel #7
0
        public static void ValidatePubXml(this IDvinApp dvinApp, IFileSystemService fileSystemService, IErrorsAndInfos errorsAndInfos)
        {
            if (!fileSystemService.FolderExists(dvinApp.SolutionFolder))
            {
                errorsAndInfos.Errors.Add($"Folder \"{dvinApp.SolutionFolder}\" not found");
                return;
            }

            var solutionFolder = new Folder(dvinApp.SolutionFolder);
            var pubXmlFiles    = fileSystemService.ListFilesInDirectory(solutionFolder, "*.pubxml", SearchOption.AllDirectories);

            if (pubXmlFiles.Count != 1)
            {
                errorsAndInfos.Errors.Add($"Found {pubXmlFiles.Count} pubxml files in secret {dvinApp.Id} dvin app");
                return;
            }

            XDocument document;
            var       pubXmlFile = pubXmlFiles[0];

            try {
                document = XDocument.Parse(fileSystemService.ReadAllText(pubXmlFile));
            } catch {
                errorsAndInfos.Errors.Add($"Could not parse {pubXmlFile}");
                return;
            }

            var namespaceManager = new XmlNamespaceManager(new NameTable());

            namespaceManager.AddNamespace("cp", CsProjNamespace);

            var publishUrlElementValue = document.XPathSelectElement("./cp:Project/cp:PropertyGroup/cp:publishUrl", namespaceManager)?.Value;

            if (string.IsNullOrWhiteSpace(publishUrlElementValue))
            {
                errorsAndInfos.Errors.Add($"publishUrl element not found in {pubXmlFile}");
                return;
            }

            if (!publishUrlElementValue.StartsWith(@"$(MSBuildThisFileDirectory)"))
            {
                errorsAndInfos.Errors.Add($"publishUrl element in {pubXmlFile} does not start with $(MSBuildThisFileDirectory)");
                return;
            }

            var publishFolder = new Folder(dvinApp.PublishFolder);
            int pos;

            for (pos = 0; pos < pubXmlFile.Length && pos < publishFolder.FullName.Length && pubXmlFile[pos] == publishFolder.FullName[pos]; pos++)
            {
            }
            for (pos--; pos > 0 && pubXmlFile[pos] != '\\'; pos--)
            {
            }

            if (pos <= 0)
            {
                errorsAndInfos.Errors.Add($"{pubXmlFile} and {publishFolder.FullName} do not share a common prefix");
                return;
            }

            var expectedPublishUrlElement = "$(MSBuildThisFileDirectory)" + string.Join("", pubXmlFile.Substring(pos + 1).ToCharArray().Where(c => c == '\\').Select(_ => @"..\")) + publishFolder.FullName.Substring(pos + 1);

            if (publishUrlElementValue == expectedPublishUrlElement)
            {
                return;
            }

            errorsAndInfos.Errors.Add($"publishUrl element in {pubXmlFile} should be {expectedPublishUrlElement}, but it is {publishUrlElementValue}");
        }
Beispiel #8
0
 public static void ValidatePubXml(this IDvinApp dvinApp, IErrorsAndInfos errorsAndInfos)
 {
     ValidatePubXml(dvinApp, new FileSystemService(), errorsAndInfos);
 }
Beispiel #9
0
 public static void Publish(this IDvinApp dvinApp, IFileSystemService fileSystemService, IErrorsAndInfos errorsAndInfos)
 {
     Publish(dvinApp, fileSystemService, false, errorsAndInfos);
 }
Beispiel #10
0
 public static bool HasAppBeenBuiltAfterLatestSourceChanges(this IDvinApp dvinApp, IFileSystemService fileSystemService)
 {
     return(HaveArtifactsBeenProducedAfterLatestSourceChanges(fileSystemService, new Folder(dvinApp.SolutionFolder), new Folder(dvinApp.ReleaseFolder)));
 }