/// <summary> /// Get the <see cref="BuildStepResult"/> for the specified <see cref="IBuildStep"/>. /// </summary> /// <param name="buildStep">The build step to search for the result.</param> /// <param name="value">The <see cref="BuildStepResult"/> if found, otherwise default(<see cref="BuildStepResult"/>)</param> /// <returns><see langword="true"/> if the IBuildStep was found, otherwise <see langword="false"/>.</returns> public bool TryGetBuildStepResult(IBuildStep buildStep, out BuildStepResult value) { foreach (var result in BuildStepsResults) { if (result.BuildStep == buildStep) { value = result; return(true); } } value = default; return(false); }
/// <summary> /// Construct <see cref="BuildStepResult"/> from this <see cref="BuildStep"/> that represent a failed execution. /// </summary> /// <param name="message">Message that explain why the <see cref="BuildStep"/> execution failed.</param> /// <returns>A new <see cref="BuildStepResult"/> instance.</returns> public BuildStepResult Failure(string message) => BuildStepResult.Failure(this, message);
/// <summary> /// Construct <see cref="BuildStepResult"/> from this <see cref="BuildStep"/> that represent a successful execution. /// </summary> /// <returns>A new <see cref="BuildStepResult"/> instance.</returns> public BuildStepResult Success() => BuildStepResult.Success(this);
BuildPipelineResult RunBuildSteps(BuildContext context) { var timer = new Stopwatch(); var status = context.BuildPipelineStatus; var title = context.BuildProgress?.Title ?? string.Empty; // Setup build steps list var cleanupSteps = new Stack <BuildStep>(); var enabledSteps = EnumerateBuildSteps().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) { status.Succeeded = false; status.Message = $"{title} was cancelled."; break; } // Add step to cleanup stack only if it overrides implementation if (step.GetType().GetMethod(nameof(BuildStep.CleanupBuildStep)).DeclaringType != typeof(BuildStep)) { cleanupSteps.Push(step); } // Run build step try { timer.Restart(); var result = step.RunBuildStep(context); timer.Stop(); // Update build step duration result.Duration = timer.Elapsed; // Add build step result to pipeline status status.BuildStepsResults.Add(result); // Stop execution for normal build steps after failure if (!result.Succeeded) { break; } } catch (Exception exception) { // Add build step exception to pipeline status, and stop executing build steps status.BuildStepsResults.Add(BuildStepResult.Exception(step, exception)); break; } } // Execute cleanup even if there are failures in build steps. // * In opposite order of build steps that ran // * Can't be cancelled; cleanup step must run foreach (var step in cleanupSteps) { // Update build progress context.BuildProgress?.Update($"{title} (Cleanup)", step.Description + "...", 1.0F); // Run cleanup step try { timer.Restart(); var result = step.CleanupBuildStep(context); timer.Stop(); // Update cleanup step duration result.Duration = timer.Elapsed; // Add cleanup step result to pipeline status status.BuildStepsResults.Add(result); } catch (Exception exception) { // Add cleanup step exception to pipeline status (not stopping execution) status.BuildStepsResults.Add(BuildStepResult.Exception(step, exception)); } } return(status); }
static void RunBuildSteps(BuildContext context, IReadOnlyCollection <IBuildStep> steps) { var timer = new Stopwatch(); var status = context.BuildPipelineStatus; var title = context.BuildProgress?.Title ?? string.Empty; // Setup build step actions to perform var cleanupSteps = new Stack <IBuildStep>(); var enabledSteps = steps.Where(step => step.IsEnabled(context)).ToArray(); // Execute build step actions (Stop executing on first failure - of any kind) for (var i = 0; i < enabledSteps.Length; ++i) { var step = enabledSteps[i]; var cancelled = context.BuildProgress?.Update($"{title} (Step {i + 1} of {enabledSteps.Length})", step.Description + "...", (float)i / enabledSteps.Length) ?? false; if (cancelled) { status.Succeeded = false; status.Message = $"{title} was cancelled."; break; } cleanupSteps.Push(step); try { timer.Restart(); var result = step.RunStep(context); timer.Stop(); result.Duration = timer.Elapsed; status.BuildStepsResults.Add(result); // Stop execution for normal build steps after failure if (!result.Succeeded) { break; } } catch (Exception exception) { // Stop execution for normal build steps after failure status.BuildStepsResults.Add(BuildStepResult.Exception(step, exception)); break; } } // Execute Cleanup (Even if there are failures) // * In opposite order of the run steps (Only run the cleanup steps, for steps that ran) // * can't be cancelled, cleanup must always run foreach (var step in cleanupSteps) { context.BuildProgress?.Update($"{title} (Cleanup)", step.Description + "...", 1.0F); try { timer.Restart(); var result = step.CleanupStep(context); timer.Stop(); result.Duration = timer.Elapsed; // All clean steps must run even if there are failures status.BuildStepsResults.Add(result); } catch (Exception exception) { // All clean steps must run even if there are failures status.BuildStepsResults.Add(BuildStepResult.Exception(step, exception)); } } }
public BuildStepResult CleanupStep(BuildContext context) => BuildStepResult.Success(this);
/// <summary> /// Construct <see cref="BuildStepResult"/> from this <see cref="IBuildStep"/> that represent an exception during execution. /// </summary> /// <param name="exception">The exception.</param> /// <returns>A new <see cref="BuildStepResult"/> instance.</returns> public BuildStepResult Exception(Exception exception) => BuildStepResult.Exception(this, exception);