/// <summary> /// For stages that have to process each project of a solution, this allows the overall status to be set according to the /// lowest status of any given project. So, if 1 project out of 4 failed, the stage status is failed. /// </summary> /// <param name="status"></param> protected void SetInprocessStageStatus(StageCompletionStatusEnum status) { if (CompletionStatus == StageCompletionStatusEnum.NotStarted) { CompletionStatus = status; return; } if (CompletionStatus == status) { return; } // If the current status is warning or error and the new status is good, leave at the current status if (CompletionStatus < StageCompletionStatusEnum.Skipped && status > StageCompletionStatusEnum.Skipped) { return; } if (status == StageCompletionStatusEnum.Failure) { CompletionStatus = status; return; } // Warning does not override errors. if (status == StageCompletionStatusEnum.Warning && CompletionStatus <= status) { return; } // Catchall CompletionStatus = status; }
/// <summary> /// Writes The Final Status information /// </summary> public static void WriteFinalHeader(StageCompletionStatusEnum status, CISession ciSession) { Color color; Color lineColor = Color.DarkViolet; if (status == StageCompletionStatusEnum.Success) { color = Color.LimeGreen; } else if (status == StageCompletionStatusEnum.Failure || status == StageCompletionStatusEnum.Aborted) { color = Color.Red; } else { color = Color.Yellow; } Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(apphdr, lineColor); Console.WriteLine(apphdr, lineColor); Console.WriteLine("| " + "Overall Build Status: " + status, color); Console.WriteLine(apphdr, lineColor); Console.WriteLine(apphdr, lineColor); Console.WriteLine(); Console.WriteLine(hdrSep, lineColor); Console.WriteLine("| " + "Project Step Status: ", lineColor); Console.WriteLine(hdrSep, lineColor); Console.WriteLine(""); Console.WriteLine(" {0,-30} {1,-8} {2,-8} {3,-8} {4,-8}", "Project", "Deploy", "Compile", "Pack", "Publish"); foreach (SlugCIProject project in ciSession.Projects) { Console.Write(" {0,-30}", project.Name, Color.WhiteSmoke); Console.Write(" {0,-8}", project.Deploy.ToString(), Color.WhiteSmoke); string text; (text, lineColor) = WriteProjectStageStatus(project.Results.CompileSuccess); Console.Write(" {0,-8}", text, lineColor); (text, lineColor) = WriteProjectStageStatus(project.Results.PackedSuccess); Console.Write(" {0,-8}", text, lineColor); (text, lineColor) = WriteProjectStageStatus(project.Results.PublishedSuccess); Console.Write(" {0,-8}", text, lineColor); Console.ForegroundColor = Color.WhiteSmoke; Console.WriteLine(); } }
/// <summary> /// Constructor /// </summary> public SlugBuilder(CISession ciSession) { Misc.WriteMainHeader("SlugBuilder:: Startup"); CISession = ciSession; GitProcessorStartup(); // Setup Build Execution Plan based upon caller's Final Build Request Target // Pretend it was compile Console.ForegroundColor = Color.WhiteSmoke; LoadBuildStages(); // TODO Remove or comment this out, this is for speeding up testing. #if DEBUG bool calcVersionSkipped = false; foreach (BuildStage stage in _executionPlan.KnownStages) { /* * //if ( stage.Name != BuildStageStatic.STAGE_TYPEWRITER_PUBLISH && stage.Name != BuildStageStatic.STAGE_TYPEWRITER_VER) stage.ShouldSkip = true; * if ( stage.Name != BuildStageStatic.STAGE_PUBLISH ) stage.ShouldSkip = true; * if ( stage.Name != BuildStageStatic.STAGE_TYPEWRITER_PUBLISH && * stage.Name != BuildStageStatic.STAGE_TYPEWRITER_VER && * stage.Name != BuildStageStatic.STAGE_PUBLISH) stage.ShouldSkip = true; * * * // Leave this in - it determines if we will have a version calculated. If not, then it manually sets one, so steps can complete. * if (stage.Name == BuildStageStatic.STAGE_CALCVERSION) * ciSession.VersionInfo = new VersionInfo(new SemVersion(3, 56, 43), "656gtg"); */ } #endif _executionPlan.BuildExecutionPlan(BuildStageStatic.STAGE_FINAL); // Anything less than skipped indicates an error situation. StageCompletionStatusEnum planStatus = _executionPlan.Execute(); WriteSummary(_executionPlan, CISession.IsInteractiveRun, ciSession); // TODO Move this somewhere... // BuildStage_TypeWriterPublish tw = (BuildStage_TypeWriterPublish) _executionPlan.GetBuildStage(BuildStageStatic.STAGE_TYPEWRITER_PUBLISH); // foreach ( LineOut output in tw.StageOutput ) { Console.WriteLine(output); } }
/// <summary> /// Publishes a Nuget package to a nuget site. /// </summary> private void Publish_Nuget() { DotNetNuGetPushSettings settings = new DotNetNuGetPushSettings() { Source = CISession.NugetRepoURL, ApiKey = CISession.NugetAPIKey, SkipDuplicate = true, }; IReadOnlyCollection <AbsolutePath> nugetPackages = CISession.OutputDirectory.GlobFiles("*.nupkg"); foreach (AbsolutePath nugetPackage in nugetPackages) { if (nugetPackage.ToString().EndsWith("symbols.nupkg")) { continue; } bool pushedSuccessfully = false; StageCompletionStatusEnum stepStatus = StageCompletionStatusEnum.NotStarted; try { settings.TargetPath = nugetPackage; (BlockingCollection <ILineOut> nugetOutput, int exitCode) = DotNetNuGetPush(settings); StageOutput.AddRange(nugetOutput); ControlFlow.Assert(exitCode == 0, "Process DotNetBuild failed"); if (nugetOutput.Count > 0) { // Look for skipped message. foreach (ILineOut outputLine in nugetOutput) { if (outputLine.Text.Contains("already exists at feed")) { stepStatus = StageCompletionStatusEnum.Warning; string msg = @"A nuget package <" + Path.GetFileName(nugetPackage) + "> with this name and version already exists. " + "Assuming this is due to you re-running the publish after a prior error that occurred after the push to Nuget was successful. " + "Will carry on as though this push was successful. " + "Otherwise, if this should have been a new update, then you will need to make another commit and re-publish"; Logger.Warn(msg); } else if (outputLine.Text.Contains("package was pushed")) { pushedSuccessfully = true; stepStatus = StageCompletionStatusEnum.Success; } } } } catch (ProcessException pe) { stepStatus = StageCompletionStatusEnum.Failure; if (!CISession.NugetRepoURL.Contains("nuget.org")) { Logger.Warn( "The nuget Push process threw an error. Since you are using a service other than Nuget this may be a service outage with the site or it might mean the version of the library you are pushing already exists. You will need to perform a manual check to determine which it is."); } else { throw; } } if (pushedSuccessfully) { string fileName = Path.GetFileName(nugetPackage); fileName = fileName.TrimEnd(".symbols.nupkg"); fileName = fileName.TrimEnd(".nupkg"); fileName = fileName.TrimEnd("." + CISession.VersionInfo.SemVersionAsString); fileName = fileName.ToLower(); // Loop thru projects looking for that assembly name foreach (SlugCIProject project in CISession.Projects) { if (project.AssemblyName.ToLower() == fileName || project.PackageId.ToLower() == fileName) { // TODO - Remove - not needed anylonger. // For Tool Deployed projects, we need to copy the current version out to the deploy folder /* * if ( project.Deploy == SlugCIDeployMethod.Tool ) { * AbsolutePath deployFile = CISession.DeployCopyPath / project.Name / CISession.PublishTarget.ToString() / "Version.json"; * ToolVersionJSON toolVersionJSON = new ToolVersionJSON() {ToolVersion = CISession.VersionInfo.SemVersionAsString}; * string json = JsonSerializer.Serialize<ToolVersionJSON>(toolVersionJSON, ToolVersionJSON.SerializerOptions()); * File.WriteAllText(deployFile, json); * } */ project.Results.PublishedSuccess = true; break; } } } // Set stage status based upon Step Status SetInprocessStageStatus(stepStatus); } }
/// <summary> /// Owner of this stage record, calls this to indicate the Stage has completed all processing. /// </summary> public void Finished(StageCompletionStatusEnum completionStatus) { CompletionStatus = completionStatus; _stopwatch.Stop(); }