/// <summary> /// Request the active build process to update. /// Returns <see langword="true"/> to indicate that it must be called again, otherwise <see langword="false"/> to indicate that the build has completed. /// </summary> /// <returns><see langword="true"/> if <see cref="Update"/> must be called again, otherwise <see langword="false"/>.</returns> public bool Update() { if (IsCompleted) { return(false); } if (!m_Timer.IsRunning) { m_Timer.Restart(); } try { Result = m_OnBuild(m_Context); } catch (Exception exception) { Result = m_Context.Failure(exception); } if (!IsCompleted) { return(true); } m_Timer.Stop(); Result.Duration = m_Timer.Elapsed; BuildArtifacts.Store(Result, m_Context.Values.OfType <IBuildArtifact>().ToArray()); return(false); }
/// <summary> /// Request the active build process to update. /// Returns <see langword="true"/> to indicate that it must be called again, otherwise <see langword="false"/> to indicate that the build has completed. /// </summary> /// <returns><see langword="true"/> if <see cref="Update"/> must be called again, otherwise <see langword="false"/>.</returns> public bool Update() { if (IsCompleted) { return(false); } if (!m_Timer.IsRunning) { m_Timer.Restart(); m_StartTime = DateTime.Now; } try { Result = m_OnBuild(m_Context); } catch (Exception exception) { Result = m_Context.Failure(exception); } if (!IsCompleted) { return(true); } m_Timer.Stop(); Result.StartTime = m_StartTime; Result.Duration = m_Timer.Elapsed; BuildArtifacts.Serialize(Result, m_Context.GetAllBuildArtifacts().ToArray()); return(false); }
/// <summary> /// Run all enabled build steps and cleanup. /// </summary> /// <param name="context">The current build context.</param> /// <returns>A build result indicating if successful or not.</returns> public BuildResult Run(BuildContext context) { var results = new List <BuildResult>(); var title = context.BuildProgress?.Title ?? string.Empty; // Setup build steps list var cleanupSteps = new Stack <BuildStepBase>(); var enabledSteps = m_BuildSteps.Where(step => step.IsEnabled(context)).ToArray(); // Run build steps and stop on first failure of any kind for (var i = 0; i < enabledSteps.Length; ++i) { var step = enabledSteps[i]; // Update build progress var cancelled = context.BuildProgress?.Update($"{title} (Step {i + 1} of {enabledSteps.Length})", step.Description + "...", (float)i / enabledSteps.Length) ?? false; if (cancelled) { results.Add(context.Failure($"{title} was cancelled.")); break; } // Add step to cleanup stack only if it overrides implementation if (step.GetType().GetMethod(nameof(BuildStepBase.Cleanup)).DeclaringType != typeof(BuildStepBase)) { cleanupSteps.Push(step); } // Run step try { results.Add(step.Run(context)); if (results.Last().Failed) { break; } } catch (Exception exception) { results.Add(context.Failure(exception)); break; } } // Execute cleanup (even if there are failures): // 1) in opposite order of steps that ran. // 2) can't be cancelled; cleanup must run. foreach (var step in cleanupSteps) { context.BuildProgress?.Update($"{title} (Cleanup)", step.Description + "...", 1.0F); try { results.Add(step.Cleanup(context)); } catch (Exception exception) { results.Add(context.Failure(exception)); } } // Return the first failed result if any var failure = results.FirstOrDefault(result => result.Failed); return(failure != null ? failure : context.Success()); }