Example #1
0
        /// <summary>
        /// Gets the latest revision identifier from each project with a trigger method of Polling and pushes the project onto the build queue if there are recent changes.
        /// </summary>
        /// <returns></returns>
        public async Task PollOnceForChangesAsync()
        {
            var projectIds = await _repository.GetProjectsToPollForChanges();

            await _logger.LogInfoAsync($"Checking for changes with {projectIds.Count()} project(s).");

            foreach (var projectID in projectIds)
            {
                await _logger.LogDebugAsync($"Processing project {projectID}...");

                var projectConfigTask = _repository.GetProject(projectID);
                var latestBuildTask   = _repository.GetMostRecentBuildAsync(projectID);

                await Task.WhenAll(projectConfigTask, latestBuildTask);

                var projectConfig = projectConfigTask.Result;
                var latestBuild   = latestBuildTask.Result;
                var codeRepo      = CodeRepositoryFactory.Create(projectConfig);

                var codeStatus = await projectConfig.CheckForNeededBuild(codeRepo, latestBuild);

                if (codeStatus.NeedsBuild == true)
                {
                    await _logger.LogInfoAsync($"Adding project {projectID} to the build queue.");

                    await _queue.EnqueueBuild(new BuildQueueEntry()
                    {
                        BuildQueueID       = Guid.NewGuid(),
                        CreateDateTime     = DateTimeOffset.Now,
                        ProjectID          = projectID,
                        RevisionIdentifier = codeStatus.RevisionIdentifier,
                        BuildNumber        = projectConfig.NextBuildNumber
                    });
                }
            }

            await _logger.LogInfoAsync("Project status check complete.");
        }
Example #2
0
        /// <summary>
        /// Processes build jobs in the given queue one at a time until the queue is emtpy.
        /// </summary>
        /// <param name="projectQueue"></param>
        /// <returns></returns>
        public async Task ProcessQueueAsync(System.Collections.Concurrent.ConcurrentQueue <LocalQueuedJob> projectQueue)
        {
            LocalQueuedJob buildJob;

            while (projectQueue.TryDequeue(out buildJob))
            {
                try
                {
                    var environment = new BuildEnvironment(System.IO.Path.Combine(_options.WorkingPath, buildJob.Configuration.Name), buildJob.Output);
                    int failCount   = buildJob.QueueEntry.FailCount;

                    environment.AddGlobalVariables();
                    environment.AddAgentVariables(_options);
                    environment.AddProjectConfigurationVariables(buildJob.Configuration);
                    environment.AddQueueEntryVariables(buildJob.QueueEntry);

                    // Create the working path if it does not exist
                    if (!System.IO.Directory.Exists(environment.WorkingPath))
                    {
                        System.IO.Directory.CreateDirectory(environment.WorkingPath);
                    }

                    if (!System.IO.Directory.Exists(environment.CodePath))
                    {
                        System.IO.Directory.CreateDirectory(environment.CodePath);
                    }
                    else
                    {
                        // Delete all the files and folders contained in the working path
                        PathUtils.CleanFolder(environment.CodePath);
                    }

                    var maxFailureCount = buildJob.Configuration.MaxFailureCount;
                    var codeRepo        = CodeRepositoryFactory.Create(buildJob.Configuration);
                    var codeInfo        = await codeRepo.GetInfo(buildJob.Configuration.RepositoryPath, buildJob.RevisionIdentifier);

                    environment.AddCodeInfoVariables(codeInfo);

                    // export the code into the working code folder
                    await codeRepo.Export(buildJob.Configuration.RepositoryPath, buildJob.RevisionIdentifier, environment.CodePath);

                    // run each build task in order
                    var buildResult = await buildJob.Configuration.Tasks.RunAllAsync(environment);

                    if (buildResult.Success)
                    {
                        environment.WriteMessage(MessageSeverity.Info, "The build project completed successfully.");
                    }
                    else
                    {
                        failCount++;

                        if (failCount >= maxFailureCount)
                        {
                            buildResult = BuildResult.Fail(buildResult.StatusCode, false);

                            environment.WriteMessage(MessageSeverity.Error, $"The build project failed too many times ({failCount}) and will not be attempted again.");
                        }
                        else
                        {
                            environment.WriteMessage(MessageSeverity.Warn, $"The build project has failed on try {failCount} of {maxFailureCount} and will be attempted again.");
                        }
                    }

                    await _repository.SetBuildResultAsync(buildJob.QueueEntry.BuildQueueID, buildResult);
                }
                catch (Exception ex)
                {
                    await buildJob.Output.LogErrorAsync(ex.Message);

                    await _repository.SetBuildResultAsync(buildJob.QueueEntry.BuildQueueID, BuildResult.Fail(3, true));

                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }
        }