示例#1
0
        public async Task <ExecutiveBuildDTO> GetExecutiveBuild(int projectId)
        {
            var project = await Context.Projects
                          .Include(p => p.BuildSteps)
                          .ThenInclude(s => s.PluginCommand)
                          .ThenInclude(c => c.Plugin)
                          .Include(p => p.Repository)
                          .Include(p => p.BuildSteps)
                          .ThenInclude(s => s.BuildPluginParameters)
                          .Include(p => p.BuildSteps)
                          .ThenInclude(s => s.CommandArguments)
                          .FirstOrDefaultAsync(p => p.Id == projectId);

            if (project == null)
            {
                throw new NotFoundException("Project", projectId);
            }

            var executiveBuild = new ExecutiveBuildDTO
            {
                ProjectId     = project.Id,
                RepositoryUrl = project.Repository.Url,
                BuildSteps    = project.BuildSteps
                                .Select(buildStep => Mapper.Map <BuildStepDTO>(buildStep))
                                .OrderBy(buildStep => buildStep.Index)
            };


            return(executiveBuild);
        }
        public async Task BuildProjectAsync(ExecutiveBuildDTO build)
        {
            var pathToClonedRepository = Path.Combine(
                _pathToProjects,
                $"{build.ProjectId}{DateTime.Now.Millisecond}{new Random().Next(1000000)}",
                "ClonedRepository"
                );

            CloneRepository(build.RepositoryUrl, pathToClonedRepository);

            try
            {
                var dockerFileContent = GenerateDockerFileContent(build.BuildSteps, build.RepositoryUrl);
                await CreateDockerFileAsync(dockerFileContent, pathToClonedRepository);

                BuildDockerImage(pathToClonedRepository, build.ProjectId);
            }
            catch (Exception e)
            {
                Log.Error($"Error while building docker image. Reason: {e.Message}");
            }
            finally
            {
                DeleteClonedRepository(pathToClonedRepository);

                // Remove all unused containers, networks, images (both dangling and unreferenced)
                Process process = new Process();
                process.StartInfo.FileName  = "docker";
                process.StartInfo.Arguments = "system prune -f";
                process.Start();
                process.WaitForExit();
            }
        }
        public async Task BuildProjectAsync(ExecutiveBuildDTO build)
        {
            var pathToClonedRepository = Path.Combine(
                _pathToProjects,
                $"{build.ProjectId}{DateTime.Now.Millisecond}{new Random().Next(1000000)}",
                "ClonedRepository"
                );

            CloneRepository(build.RepositoryUrl, pathToClonedRepository, build.BranchName);

            try

            {
                if (build.BuildSteps.Count() != 0 && build.BuildSteps.FirstOrDefault().BuildStepName == "Dockerfile")
                {
                    var dockerfileDirectory = build.BuildSteps.FirstOrDefault().WorkDirectory;
                    if (dockerfileDirectory != "")
                    {
                        pathToClonedRepository = Path.Combine(pathToClonedRepository, dockerfileDirectory);
                    }
                }
                else
                {
                    var dockerFileContent = GenerateDockerFileContent(build.BuildSteps, build.RepositoryUrl);
                    await CreateDockerFileAsync(dockerFileContent, pathToClonedRepository);
                }

                BuildDockerImage(pathToClonedRepository, build);
            }
            catch (Exception e)
            {
                SendBuildStatus(BuildStatus.Error, build.BuildHistoryId, build.UserId);
                Log.Error($"Error while building docker image. Reason: {e.Message}");
            }
            finally
            {
                DeleteClonedRepository(pathToClonedRepository);

                // Remove all unused containers, networks, images (both dangling and unreferenced)
                Process process = new Process();
                process.StartInfo.FileName  = "docker";
                process.StartInfo.Arguments = "system prune -f";
                process.Start();
                process.WaitForExit();
            }
        }
        public void BuildDockerImage(string path, ExecutiveBuildDTO build)
        {
            Process process = new Process();

            process.StartInfo.FileName               = "docker";
            process.StartInfo.Arguments              = $"build {path}";
            process.StartInfo.UseShellExecute        = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError  = true;
            //* Set your output and error (asynchronous) handlers
            process.OutputDataReceived += (object _sender, DataReceivedEventArgs _args) =>
                                          OutputHandler(_sender, _args, build);
            process.ErrorDataReceived += (object _sender, DataReceivedEventArgs _args) =>
                                         OutputHandler(_sender, _args, build);
            //* Start process and handlers
            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            process.WaitForExit();
        }
        public async void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine, ExecutiveBuildDTO build)
        {
            // If log starts with Step and containts FROM we stop logging because there will be useless Docker logs
            // (also applied to "Removing intermediate container" and "Sending build context"). Skip checking empty strings
            if (outLine.Data != null &&
                ((outLine.Data.StartsWith("Step") && outLine.Data.Contains("FROM")) ||
                 outLine.Data.StartsWith("Removing intermediate container") ||
                 outLine.Data.StartsWith("Sending build context")))
            {
                areDockerLogs = true;
                startLogging  = 2;
            }
            // We begin logging again after logs that starts with Step and contains RUN. Usually RUN starts process, which we need logs to take from
            // TODO: We can add checking 'contains' from list, that will have all starter commands like RUN, CMD, etc.
            else if (outLine.Data != null &&
                     (outLine.Data.StartsWith("Step") &&
                      outLine.Data.Contains("RUN")))
            {
                areDockerLogs = false;

                // Add one specific string to divide different build steps
                var log = new ProjectLog()
                {
                    Timestamp      = DateTime.Now,
                    Message        = $">>> Here starts a new step",
                    BuildHistoryId = build.BuildHistoryId,
                    ProjectId      = build.ProjectId
                };
                await _kafkaProducer.SendLog(log);
            }

            // This function is needed to get rid of first two lines before actual logs of our process
            if (!areDockerLogs)
            {
                startLogging--;
            }

            if (!areDockerLogs && startLogging < 0)
            {
                var log = new ProjectLog()
                {
                    Timestamp      = DateTime.Now,
                    Message        = outLine.Data,
                    BuildHistoryId = build.BuildHistoryId,
                    ProjectId      = build.ProjectId
                };
                await _elk.IndexDocumentAsync(log);

                await _kafkaProducer.SendLog(log);
            }
        }