public BuildReport Run() { BuildReport report = new BuildReport(); Project projectToBuild = projectRegistry.GetProject(projectId); Log(Level.Info, "Starting the build runner"); lock (this) { // construct a graph of build stages foreach (BuildStage stage in projectToBuild.BuildStages) { BuildDependencyGraph(stage); } Log(Level.Debug, "Constructed build stages dependency graph"); } while (true) { Log(Level.Debug, "New cycle started"); lock (this) { // retrieve the fresh info about stage statuses foreach (BuildStage stage in stagesOrdered) { StageStatus status = GetStageStatus(stage); if (status.Outcome == BuildOutcome.InProgress) { status.StageRunner.UpdateStatus(status); } Log(Level.Info, "Build stage '{0}' status: {1}", status.Stage.StageId, status.Outcome); } } // check if the traffic buildTrafficSignals has signalled the runner to stop BuildTrafficCopSignal signal = buildTrafficSignals.WaitForControlSignal(TimeSpan.Zero); if (signal == BuildTrafficCopSignal.Stop) { break; } bool stagesPending = false; lock (this) { // check if any of the stages can be started foreach (BuildStage stage in stagesOrdered) { StageStatus status = stagesStatuses[stage.StageId]; if (status.Outcome == BuildOutcome.Initial) { bool someDependenciesFailed = false; bool allDependenciesSuccessful = true; // check dependecy stages foreach (BuildStage dependency in stage.DependsOn) { StageStatus dependencyStatus = GetStageStatus(dependency); if (dependencyStatus.Outcome == BuildOutcome.Failed) { // this stage will not be executed, so go to the next one someDependenciesFailed = true; allDependenciesSuccessful = false; break; } else if (dependencyStatus.Outcome == BuildOutcome.Successful) { continue; } allDependenciesSuccessful = false; } if (someDependenciesFailed) { status.MarkAsNotExecuted(); } else if (allDependenciesSuccessful) { // we can start this stage Log(Level.Info, "Starting stage '{0}'", status.Stage.StageId); IStageRunner stageRunner = this.buildStageRunnerFactory.CreateStageRunner(status.Stage); status.PrepareToStart(stageRunner); stageRunner.StartStage(); // update the status immediatelly stageRunner.UpdateStatus(status); stagesPending = true; } else { stagesPending = true; } } } } if (stagesPending) { Log(Level.Debug, "Some build stages are still pending"); } else { Log(Level.Debug, "The build has been executed"); break; } Log(Level.Debug, "Waiting for the traffic cop"); // check if the traffic buildTrafficSignals has signalled the runner to stop signal = buildTrafficSignals.WaitForControlSignal(pollPeriod); if (signal == BuildTrafficCopSignal.Stop) { break; } } Log(Level.Info, "Stopping the build runner"); foreach (BuildStage stage in stagesOrdered) { BuildStageReport stageReport = new BuildStageReport(); stageReport.StageOutcome = GetStageStatus(stage).Outcome; report.StageReports.Add(stage.StageId, stageReport); } return(report); }