internal static void AddBuildTimeProperty( MergeReport mergeReport, int timeInMilliseconds) { AddNumberProperty( mergeReport, "build time (min)", GetMinutes(timeInMilliseconds)); }
static void ReportMerge( RestApi restApi, string repository, string branchName, string botName, MergeReport mergeReport) { if (mergeReport == null) { return; } try { TrunkMergebotApi.MergeReports.ReportMerge(restApi, botName, mergeReport); } catch (Exception ex) { mLog.ErrorFormat( "Unable to report merge for branch '{0}' on repository '{1}': {2}", branchName, repository, ex.Message); mLog.DebugFormat( "StackTrace:{0}{1}", Environment.NewLine, ex.StackTrace); } }
internal static void AddSucceededMergeProperty( MergeReport mergeReport, MergeToResultStatus status) { MergeReport.Entry succeededMergeProperty = new MergeReport.Entry(); succeededMergeProperty.Text = GetMergeToResultStatus(status); succeededMergeProperty.Type = MERGE_OK_TYPE; mergeReport.Properties.Add(succeededMergeProperty); }
internal static MergeReport Build(BranchModel branch) { MergeReport result = new MergeReport(); result.Timestamp = DateTime.UtcNow; result.RepositoryId = branch.RepositoryId; result.BranchId = branch.Id; result.Properties = new List <MergeReport.Entry>(); return(result); }
static void AddNumberProperty( MergeReport mergeReport, string text, double value) { MergeReport.Entry numberProperty = new MergeReport.Entry(); numberProperty.Text = text; numberProperty.Type = "number"; numberProperty.Value = value.ToString(); mergeReport.Properties.Add(numberProperty); }
internal static void AddFailedMergeProperty( MergeReport mergeReport, MergeToResultStatus status, string message) { MergeReport.Entry failedMergeProperty = new MergeReport.Entry(); failedMergeProperty.Text = GetMergeToResultStatus(status); failedMergeProperty.Type = MERGE_FAILED_TYPE; failedMergeProperty.Value = message; mergeReport.Properties.Add(failedMergeProperty); }
internal static void AddSucceededBuildProperty( MergeReport mergeReport, string planBranch) { MergeReport.Entry succeededBuildProperty = new MergeReport.Entry(); succeededBuildProperty.Text = string.Format( "build ok (plan: {0})", planBranch); succeededBuildProperty.Type = BUILD_OK_TYPE; mergeReport.Properties.Add(succeededBuildProperty); }
internal static bool TryMergeToShelve( RestApi restApi, Branch branch, string destinationBranch, MergeReport mergeReport, string comment, string taskNumber, TrunkBotConfiguration botConfig, string codeReviewsStorageFile, out int shelveId) { shelveId = -1; MergeToResponse result = TrunkMergebotApi.MergeBranchTo( restApi, branch.Repository, branch.FullName, destinationBranch, comment, TrunkMergebotApi.MergeToOptions.CreateShelve); if (result.Status == MergeToResultStatus.MergeNotNeeded) { ChangeTaskStatus.SetTaskAsMerged( restApi, branch, taskNumber, string.Format( "Branch {0} was already merged to {1} (MergeNotNeeded).", branch.FullName, botConfig.TrunkBranch), botConfig, codeReviewsStorageFile); return(false); } if (result.Status == MergeToResultStatus.AncestorNotFound || result.Status == MergeToResultStatus.Conflicts || result.Status == MergeToResultStatus.Error || result.ChangesetNumber == 0) { BuildMergeReport.AddFailedMergeProperty(mergeReport, result.Status, result.Message); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, string.Format( "Can't merge branch {0}. Reason: {1}", branch.FullName, result.Message), botConfig, codeReviewsStorageFile); return(false); } shelveId = result.ChangesetNumber; BuildMergeReport.AddSucceededMergeProperty(mergeReport, result.Status); return(true); }
internal static ShelveResult TryMergeToShelves( IRestApi restApi, Branch branch, string[] destinationBranches, MergeReport mergeReport, string taskTitle, string botName) { ShelveResult result = new ShelveResult(); foreach (string destinationBranch in destinationBranches) { MergeToResponse mergeToResult = MultilinerMergebotApi.MergeBranchTo( restApi, branch.Repository, branch.FullName, destinationBranch, GetComment(branch.FullName, destinationBranch, taskTitle, botName), MultilinerMergebotApi.MergeToOptions.CreateShelve); result.MergeStatusByTargetBranch[destinationBranch] = mergeToResult.Status; if (mergeToResult.Status == MergeToResultStatus.MergeNotNeeded) { string warningMessage = string.Format( "Branch [{0}] was already merged to [{1}] (No merge needed).", branch.FullName, destinationBranch); result.MergesNotNeededMessages.Add(warningMessage); continue; } if (IsFailedMergeTo(mergeToResult)) { string errorMsg = string.Format( "Can't merge branch [{0}] to [{1}]. Reason: {2}.", branch.FullName, destinationBranch, mergeToResult.Message); result.ErrorMessages.Add(errorMsg); BuildMergeReport.AddFailedMergeProperty( mergeReport, mergeToResult.Status, mergeToResult.Message); continue; } result.ShelvesByTargetBranch[destinationBranch] = mergeToResult.ChangesetNumber; BuildMergeReport.AddSucceededMergeProperty(mergeReport, mergeToResult.Status); } return(result); }
internal static void AddIssueProperty( MergeReport mergeReport, string issueTitle, string issueLink) { MergeReport.Entry issueProperty = new MergeReport.Entry(); issueProperty.Text = issueTitle; issueProperty.Link = issueLink; issueProperty.Type = ISSUETRACKER_TYPE; mergeReport.Properties.Add(issueProperty); }
internal static void AddFailedBuildProperty( MergeReport mergeReport, string planBranch, string message) { MergeReport.Entry failedBuildProperty = new MergeReport.Entry(); failedBuildProperty.Text = string.Format( "build ko (plan: {0})", planBranch); failedBuildProperty.Type = BUILD_FAILED_TYPE; failedBuildProperty.Value = message; mergeReport.Properties.Add(failedBuildProperty); }
public void ReportMerge( string mergebotName, MergeReport mergeReport) { Uri endpoint = ApiUris.GetFullUri( mBaseUri, ApiEndpoints.MergeReports.ReportMerge, mergebotName); string actionDescription = string.Format( "upload merge report of br:{0} (repo ID: {1})", mergeReport.BranchId, mergeReport.RepositoryId); Internal.MakeApiRequest <MergeReport>( endpoint, HttpMethod.Put, mergeReport, actionDescription, mApiKey); }
internal static void AddLabelProperty( MergeReport mergeReport, bool isSuccessfulOperation, string labelName, string message) { MergeReport.Entry labelActionProperty = new MergeReport.Entry(); labelActionProperty.Text = string.Format( "label {0} ({1})", isSuccessfulOperation ? "ok" : "ko", labelName); labelActionProperty.Value = message; labelActionProperty.Type = isSuccessfulOperation ? LABEL_OK_TYPE : LABEL_FAILED_TYPE; mergeReport.Properties.Add(labelActionProperty); }
internal static bool TryApplyShelve( RestApi restApi, Branch branch, string destinationBranch, MergeReport mergeReport, string comment, string taskNumber, int shelveId, TrunkBotConfiguration botConfig, string codeReviewsStorageFile, out int csetId) { MergeToResponse mergeResult = TrunkMergebotApi.MergeShelveTo( restApi, branch.Repository, shelveId, destinationBranch, comment, TrunkMergebotApi.MergeToOptions.EnsureNoDstChanges); csetId = mergeResult.ChangesetNumber; BuildMergeReport.UpdateMergeProperty(mergeReport, mergeResult.Status, csetId); if (mergeResult.Status == MergeToResultStatus.OK) { return(true); } if (mergeResult.Status == MergeToResultStatus.DestinationChanges) { // it should checkin the shelve only on the exact parent shelve cset. // if there are new changes in the trunk branch enqueue againg the task return(false); } ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, string.Format( "Can't merge branch {0}. Reason: {1}", branch.FullName, mergeResult.Message), botConfig, codeReviewsStorageFile); return(false); }
internal static void UpdateMergeProperty( MergeReport mergeReport, MergeToResultStatus status, int csetId) { MergeReport.Entry mergeProperty = FindPropertyByType( mergeReport.Properties, MERGE_OK_TYPE); if (mergeProperty == null) { return; } if (csetId == -1) { mergeProperty.Text = GetMergeToResultStatus(status); mergeProperty.Type = MERGE_FAILED_TYPE; return; } mergeProperty.Value = csetId.ToString(); }
internal static void SetUnexpectedExceptionProperty( MergeReport mergeReport, string message) { if (mergeReport == null) { return; } MergeReport.Entry failedBuildProperty = FindPropertyByType( mergeReport.Properties, BUILD_FAILED_TYPE); if (failedBuildProperty == null) { failedBuildProperty = new MergeReport.Entry(); failedBuildProperty.Type = BUILD_FAILED_TYPE; mergeReport.Properties.Add(failedBuildProperty); } failedBuildProperty.Text = "build ko (unexpected exception)"; failedBuildProperty.Value = message; }
static bool TryRunAfterCheckinPlan( RestApi restApi, Branch branch, MergeReport mergeReport, string taskNumber, int csetId, string labelName, TrunkBotConfiguration botConfig) { string repSpec = string.Format("{0}@{1}", branch.Repository, botConfig.Server); string scmSpecToSwitchTo = string.Format("cs:{0}@{1}", csetId, repSpec); string comment = string.Format( "Running plan after merging branch {0}", branch.FullName); BuildProperties properties = CreateBuildProperties( restApi, taskNumber, branch.FullName, labelName, BuildProperties.StageValues.POST_CHECKIN, botConfig); int iniTime = Environment.TickCount; TrunkMergebotApi.CI.PlanResult buildResult = TrunkMergebotApi.CI.Build( restApi, botConfig.CI.Plug, botConfig.CI.PlanAfterCheckin, scmSpecToSwitchTo, comment, properties); BuildMergeReport.AddBuildTimeProperty(mergeReport, Environment.TickCount - iniTime); string message = string.Empty; //TODO:shall we set any attr in trunk branch? if (buildResult.Succeeded) { BuildMergeReport.AddSucceededBuildProperty( mergeReport, botConfig.CI.PlanAfterCheckin); message = string.Format( "Plan execution after merging branch {0} was successful.", branch.FullName); Notifier.NotifyTaskStatus( restApi, branch.Owner, message, botConfig.Notifications); return(true); } BuildMergeReport.AddFailedBuildProperty( mergeReport, botConfig.CI.PlanAfterCheckin, buildResult.Explanation); message = string.Format( "Plan execution failed after merging branch {0}.\nReason: {1}", branch.FullName, buildResult.Explanation); Notifier.NotifyTaskStatus( restApi, branch.Owner, message, botConfig.Notifications); return(false); }
static bool CreateLabel( RestApi restApi, int csetId, string branchFullName, string trunkBranchName, string repository, bool isAutoLabelEnabled, string automaticLabelPattern, MergeReport mergeReport, string branchOwner, TrunkBotConfiguration.Notifier notificationsConfig, out string labelCreated) { labelCreated = string.Empty; if (!isAutoLabelEnabled) { return(true); } if (string.IsNullOrEmpty(automaticLabelPattern)) { return(true); } AutomaticLabeler.Result result = null; try { result = AutomaticLabeler.CreateLabel( restApi, csetId, repository, automaticLabelPattern, DateTime.Now); } catch (Exception e) { mLog.ErrorFormat( "An error occurred labeling the merged branch {0} in changeset {1}@{2}: {3}", branchFullName, csetId, repository, e.Message); if (result == null) { result = new AutomaticLabeler.Result(false, string.Empty, e.Message); } } labelCreated = result.Name; BuildMergeReport.AddLabelProperty( mergeReport, result.IsSuccessful, result.Name, result.ErrorMessage); string message = result.IsSuccessful ? string.Format( "Label {0} created successfully in {1} branch, changeset cs:{2}@{3}", labelCreated, trunkBranchName, csetId, repository) : string.Format( "Failed to create label after merging branch {0} " + "in {1} branch, changeset cs:{2}@{3}. Error: {4}", branchFullName, trunkBranchName, csetId, repository, result.ErrorMessage); Notifier.NotifyTaskStatus(restApi, branchOwner, message, notificationsConfig); return(result.IsSuccessful); }
internal static Result TryProcessBranch( RestApi restApi, Branch branch, TrunkBotConfiguration botConfig, string botName, string codeReviewsStorageFile) { int shelveId = -1; string taskNumber = null; MergeReport mergeReport = null; try { mLog.InfoFormat("Getting task number of branch {0} ...", branch.FullName); taskNumber = GetTaskNumber(branch.FullName, botConfig.BranchPrefix); if (!IsTaskReady( restApi, taskNumber, botConfig.Issues, botConfig.Plastic.IsApprovedCodeReviewFilterEnabled, branch.Repository, branch.Id, codeReviewsStorageFile)) { return(Result.NotReady); } if (!IsMergeAllowed(restApi, branch, botConfig.TrunkBranch)) { mLog.WarnFormat( "Branch {0} is not yet ready to be merged. " + "Jumping to next branch in the queue...", branch.FullName); return(Result.NotReady); } mLog.InfoFormat("Building the merge report of task {0} ...", taskNumber); mergeReport = BuildMergeReport.Build(TrunkMergebotApi.GetBranch( restApi, branch.Repository, branch.FullName)); string taskTittle; string taskUrl; if (GetIssueInfo(restApi, taskNumber, botConfig.Issues, out taskTittle, out taskUrl)) { BuildMergeReport.AddIssueProperty(mergeReport, taskTittle, taskUrl); } string comment = GetComment(branch.FullName, taskTittle, botName); mLog.InfoFormat("Trying to shelve server-side-merge from {0} to {1}", branch.FullName, botConfig.TrunkBranch); if (!MergeToOperations.TryMergeToShelve( restApi, branch, botConfig.TrunkBranch, mergeReport, comment, taskNumber, botConfig, codeReviewsStorageFile, out shelveId)) { return(Result.Failed); } mLog.InfoFormat("Testing branch {0} ...", branch.FullName); if (!TryBuildTask(restApi, branch, mergeReport, taskNumber, shelveId, botConfig, codeReviewsStorageFile)) { return(Result.Failed); } mLog.InfoFormat("Checking-in shelved merged {0} from {1} to {2}", shelveId, branch.FullName, botConfig.TrunkBranch); int csetId = -1; if (!MergeToOperations.TryApplyShelve( restApi, branch, botConfig.TrunkBranch, mergeReport, comment, taskNumber, shelveId, botConfig, codeReviewsStorageFile, out csetId)) { return(Result.Failed); } mLog.InfoFormat("Checkin: Created changeset {0} in branch {1}", csetId, botConfig.TrunkBranch); mLog.InfoFormat("Setting branch {0} as 'integrated'...", branch.FullName); ChangeTaskStatus.SetTaskAsMerged( restApi, branch, taskNumber, string.Format( "Branch {0} was correctly merged to {1}.", branch.FullName, botConfig.TrunkBranch), botConfig, codeReviewsStorageFile); string labelName = string.Empty; if (!CreateLabel( restApi, csetId, branch.FullName, botConfig.TrunkBranch, botConfig.Repository, botConfig.Plastic.IsAutoLabelEnabled, botConfig.Plastic.AutomaticLabelPattern, mergeReport, branch.Owner, botConfig.Notifications, out labelName)) { return(Result.Failed); } if (!HasToRunPlanAfterTaskMerged(botConfig.CI)) { return(Result.Ok); } if (!TryRunAfterCheckinPlan( restApi, branch, mergeReport, taskNumber, csetId, labelName, botConfig)) { return(Result.Failed); } } catch (Exception ex) { mLog.ErrorFormat( "The attempt to process task {0} failed for branch {1}: {2}", taskNumber, branch.FullName, ex.Message); mLog.DebugFormat( "StackTrace:{0}{1}", Environment.NewLine, ex.StackTrace); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, string.Format( "Can't process branch {0} because of an unexpected error: {1}.", branch.FullName, ex.Message), botConfig, codeReviewsStorageFile); BuildMergeReport.SetUnexpectedExceptionProperty(mergeReport, ex.Message); return(Result.Failed); } finally { ReportMerge(restApi, branch.Repository, branch.FullName, botName, mergeReport); SafeDeleteShelve(restApi, branch.Repository, shelveId); } return(Result.Ok); }
static bool TryBuildTask( RestApi restApi, Branch branch, MergeReport mergeReport, string taskNumber, int shelveId, TrunkBotConfiguration botConfig, string codeReviewsStorageFile) { if (botConfig.CI == null) { string message = "No CI plug was set for this mergebot. Therefore, no " + "build actions for task " + taskNumber + " will be performed."; mLog.Info(message); Notifier.NotifyTaskStatus( restApi, branch.Owner, message, botConfig.Notifications); return(true); } ChangeTaskStatus.SetTaskAsTesting(restApi, branch, taskNumber, string.Format( "Starting to test branch {0}.", branch.FullName), botConfig); string repSpec = string.Format("{0}@{1}", branch.Repository, botConfig.Server); string scmSpecToSwitchTo = string.Format("sh:{0}@{1}", shelveId, repSpec); string comment = string.Format( "Building branch {0}", branch.FullName); BuildProperties properties = CreateBuildProperties( restApi, taskNumber, branch.FullName, string.Empty, BuildProperties.StageValues.PRE_CHECKIN, botConfig); int iniTime = Environment.TickCount; TrunkMergebotApi.CI.PlanResult buildResult = TrunkMergebotApi.CI.Build( restApi, botConfig.CI.Plug, botConfig.CI.PlanBranch, scmSpecToSwitchTo, comment, properties); BuildMergeReport.AddBuildTimeProperty(mergeReport, Environment.TickCount - iniTime); if (buildResult.Succeeded) { BuildMergeReport.AddSucceededBuildProperty(mergeReport, botConfig.CI.PlanBranch); return(true); } BuildMergeReport.AddFailedBuildProperty(mergeReport, botConfig.CI.PlanBranch, buildResult.Explanation); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, string.Format( "Branch {0} build failed. \nReason: {1}", branch.FullName, buildResult.Explanation), botConfig, codeReviewsStorageFile); return(false); }
internal static void ReportMerge(RestApi restApi, string mergebotName, MergeReport mergeReport) { restApi.MergeReports.ReportMerge(mergebotName, mergeReport); }
internal static Result TryBuildTask( IRestApi restApi, Branch branch, MergeReport mergeReport, string taskNumber, string[] destinationBranches, Dictionary <string, int> branchMergesToObjectsMap, string buildStage, MultilinerBotConfiguration botConfig) { Result result = new Result(); result.AreAllSuccessful = true; string targetObjectPrefix = buildStage == BuildProperties.StageValues.PRE_CHECKIN ? "sh" : "cs"; string targetObjectName = buildStage == BuildProperties.StageValues.PRE_CHECKIN ? "shelve" : "changeset"; string ciPlan = buildStage == BuildProperties.StageValues.POST_CHECKIN ? botConfig.CI.PlanAfterCheckin : botConfig.CI.PlanBranch; string repSpec = string.Format("{0}@{1}", branch.Repository, botConfig.Server); string scmSpecToSwitchTo = string.Empty; BuildProperties properties = null; foreach (string destinationBranch in destinationBranches) { if (!branchMergesToObjectsMap.ContainsKey(destinationBranch)) { continue; } scmSpecToSwitchTo = string.Format( "{0}:{1}@{2}", targetObjectPrefix, branchMergesToObjectsMap[destinationBranch], repSpec); string comment = string.Format( "Building {0} [{1}], the resulting {0} from merging branch " + "[{2}] to [{3}]", targetObjectName, scmSpecToSwitchTo, branch.FullName, destinationBranch); properties = CreateBuildProperties( restApi, taskNumber, branch.FullName, string.Empty, buildStage, destinationBranch, botConfig); MultilinerMergebotApi.CI.PlanResult buildResult = MultilinerMergebotApi.CI.Build( restApi, botConfig.CI.Plug, ciPlan, scmSpecToSwitchTo, comment, properties); if (buildResult.Succeeded) { continue; } string errorMsg = string.Format( "Build failed. The build plan [{0}] of the resulting {1} [{2}] from merging branch " + "[{3}] to [{4}] has failed. " + "{5}" + "Please check your Continuous Integration report to find out more info about what happened.", ciPlan, targetObjectName, scmSpecToSwitchTo, branch.FullName, destinationBranch, string.IsNullOrWhiteSpace(buildResult.Explanation) ? string.Empty : "Error: [" + buildResult.Explanation + "]"); result.ErrorMessages.Add(errorMsg); result.AreAllSuccessful = false; if (buildStage == BuildProperties.StageValues.POST_CHECKIN) { continue; } return(result); } return(result); }
internal static CheckinResult TryApplyShelves( IRestApi restApi, Branch branch, string[] destinationBranches, ShelveResult shelves, MergeReport mergeReport, string taskNumber, string taskTitle, string botName, MultilinerBotConfiguration botConfig, string codeReviewsStorageFile) { CheckinResult result = new CheckinResult(); int shelveId; foreach (string destinationBranch in destinationBranches) { if (!shelves.ShelvesByTargetBranch.ContainsKey(destinationBranch)) { continue; } shelveId = shelves.ShelvesByTargetBranch[destinationBranch]; mLog.InfoFormat( "Checking-in shelveset [{0}] from branch [{1}] to [{2}]", shelveId, branch.FullName, destinationBranch); MergeToResponse mergeResult = MultilinerMergebotApi.MergeShelveTo( restApi, branch.Repository, shelveId, destinationBranch, GetComment(branch.FullName, destinationBranch, taskTitle, botName), MultilinerMergebotApi.MergeToOptions.EnsureNoDstChanges); result.MergeStatusByTargetBranch[destinationBranch] = mergeResult.Status; BuildMergeReport.UpdateMergeProperty(mergeReport, mergeResult.Status, mergeResult.ChangesetNumber); if (mergeResult.Status == MergeToResultStatus.OK) { result.ChangesetsByTargetBranch[destinationBranch] = mergeResult.ChangesetNumber; mLog.InfoFormat( "Checkin: Created changeset [{0}] in branch [{1}]", mergeResult.ChangesetNumber, destinationBranch); continue; } if (mergeResult.Status == MergeToResultStatus.DestinationChanges) { string dstWarnMessage = string.Format( "Can't checkin shelve [{0}], the resulting shelve from merging branch " + "[{1}] to [{2}]. Reason: new changesets appeared in destination branch " + "while mergebot {3} was processing the merge from [{1}] to [{2}].{4}{5}", shelveId, branch.FullName, destinationBranch, botName, Environment.NewLine, mergeResult.Message); // it should checkin the shelve only on the exact parent shelve cset. // if there are new changes in the destination branch enqueue again the task result.DestinationNewChangesWarnings.Add(dstWarnMessage); continue; } string errorMsg = string.Format( "Can't checkin shelve [{0}], the resulting shelve from merging branch " + "[{1}] to [{2}]. Reason: {3}", shelveId, branch.FullName, destinationBranch, mergeResult.Message); result.ErrorMessages.Add(errorMsg); } return(result); }
public static Result TryProcessBranch( IRestApi restApi, Branch branch, MultilinerBotConfiguration botConfig, string botName, string codeReviewsStorageFile) { string taskNumber = null; MergeReport mergeReport = null; string[] destinationBranches = null; MergeToOperations.ShelveResult mergesToShelves = null; string notificationMsg = null; try { mLog.InfoFormat("Getting task number of branch {0} ...", branch.FullName); taskNumber = GetTaskNumber(branch.FullName, botConfig.BranchPrefix); if (!IsTaskReady( restApi, taskNumber, botConfig.Issues, botConfig.Plastic.IsApprovedCodeReviewFilterEnabled, branch.Repository, branch.Id, codeReviewsStorageFile)) { return(Result.NotReady); } destinationBranches = GetMergeToDestinationBranches( restApi, branch, botConfig.MergeToBranchesAttrName); if (destinationBranches == null || destinationBranches.Length == 0) { notificationMsg = string.Format( "The attribute [{0}] of branch [{1}@{2}@{3}] is not properly set. " + "Branch [{1}@{2}@{3}] status will be set as 'failed': [{4}].", botConfig.MergeToBranchesAttrName, branch.FullName, branch.Repository, botConfig.Server, botConfig.Plastic.StatusAttribute.FailedValue); mLog.Warn(notificationMsg); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } foreach (string destinationBranch in destinationBranches) { if (ExistsBranch(restApi, destinationBranch, branch.Repository)) { continue; } notificationMsg = string.Format( "The destination branch [{0}@{1}@{2}] specified in attribute [{3}] " + "of branch [{4}@{1}@{2}] does not exist. " + "Branch [{4}@{1}@{2}] status will be set as 'failed': [{5}].", destinationBranch, branch.Repository, botConfig.Server, botConfig.MergeToBranchesAttrName, branch.FullName, botConfig.Plastic.StatusAttribute.FailedValue); mLog.Warn(notificationMsg); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } foreach (string destinationBranch in destinationBranches) { if (IsMergeAllowed(restApi, branch, destinationBranch)) { continue; } return(Result.NotReady); } mLog.InfoFormat("Building the merge report of task {0} ...", taskNumber); mergeReport = BuildMergeReport.Build( MultilinerMergebotApi.GetBranch(restApi, branch.Repository, branch.FullName)); string taskTittle; string taskUrl; if (GetIssueInfo( restApi, taskNumber, botConfig.Issues, out taskTittle, out taskUrl)) { BuildMergeReport.AddIssueProperty(mergeReport, taskTittle, taskUrl); } mLog.InfoFormat("Trying to shelve server-side-merge from [{0}] to [{1}]", branch.FullName, string.Join(", ", destinationBranches)); mergesToShelves = MergeToOperations.TryMergeToShelves( restApi, branch, destinationBranches, mergeReport, taskTittle, botName); if (NoMergesNeeded(mergesToShelves)) { ChangeTaskStatus.Result chStatResult = ChangeTaskStatus.SetTaskAsMerged( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); notificationMsg = string.Join(Environment.NewLine, mergesToShelves.MergesNotNeededMessages); if (!string.IsNullOrWhiteSpace(chStatResult.ErrorMessage)) { notificationMsg = string.Concat( notificationMsg, Environment.NewLine, chStatResult.ErrorMessage); } Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } if (mergesToShelves.ErrorMessages.Count > 0) { ChangeTaskStatus.Result chStatResult = ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); notificationMsg = string.Join(Environment.NewLine, mergesToShelves.ErrorMessages); if (mergesToShelves.MergesNotNeededMessages.Count > 0) { notificationMsg = string.Concat( notificationMsg, Environment.NewLine, string.Join(Environment.NewLine, mergesToShelves.MergesNotNeededMessages)); } if (!string.IsNullOrWhiteSpace(chStatResult.ErrorMessage)) { notificationMsg = string.Concat( notificationMsg, Environment.NewLine, chStatResult.ErrorMessage); } Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } if (mergesToShelves.MergesNotNeededMessages.Count > 0) { string alreadyMergedMessage = string.Join( Environment.NewLine + "\t", mergesToShelves.MergesNotNeededMessages); notificationMsg = string.Format( "Branch [{0}] is already merged to some " + "of the specified destination branches in the attribute [{1}]. " + "The {2} mergebot will continue building the " + "merge(s) from branch [{0}] to [{3}].{4}{4}" + "Report of already merged branches:{4}\t{5}", branch.FullName, botConfig.MergeToBranchesAttrName, botName, string.Join(", ", mergesToShelves.ShelvesByTargetBranch.Keys), Environment.NewLine, alreadyMergedMessage); mLog.Info(notificationMsg); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); } bool allBuildsOk = Build.PreCheckinStage( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToShelves, botConfig, codeReviewsStorageFile); if (!allBuildsOk) { return(Result.Failed); } MergeToOperations.CheckinResult mergesToCheckins = MergeToOperations.TryApplyShelves( restApi, branch, destinationBranches, mergesToShelves, mergeReport, taskNumber, taskTittle, botName, botConfig, codeReviewsStorageFile); //checkin went OK in all target branches if (mergesToCheckins.ErrorMessages.Count == 0 && mergesToCheckins.DestinationNewChangesWarnings.Count == 0) { mLog.InfoFormat("Setting branch {0} as 'integrated'...", branch.FullName); ChangeTaskStatus.SetTaskAsMerged( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); notificationMsg = string.Format( "OK: Branch [{0}] was successfully merged to [{1}]", branch.FullName, string.Join(", ", mergesToShelves.ShelvesByTargetBranch.Keys)); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Build.PostCheckinStage( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToCheckins, botConfig, codeReviewsStorageFile)); } //some of the checkins went wrong -> we must run the post-ci plan for the successful ones, //but force-set as failed the source branch (or requeue if the errors are due to New DstChanges if (mergesToCheckins.ErrorMessages.Count > 0) { ChangeTaskStatus.Result chStatResult = ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); string checkinErrorMessage = string.Join( Environment.NewLine + "\t", mergesToCheckins.ErrorMessages); if (mergesToCheckins.DestinationNewChangesWarnings.Count > 0) { string dstChangesErrorMessage = string.Join( Environment.NewLine + "\t", mergesToCheckins.DestinationNewChangesWarnings); checkinErrorMessage = string.Concat( checkinErrorMessage, Environment.NewLine + "\t", dstChangesErrorMessage); } notificationMsg = string.Format( "Failed build. The result of building merges from branch [{0}] to [{1}] went OK, " + "but there were some errors checking-in the resulting shelves:{2}\t{3}{2}{2}{4}", branch.FullName, string.Join(", ", mergesToShelves.ShelvesByTargetBranch.Keys), Environment.NewLine, checkinErrorMessage, string.IsNullOrWhiteSpace(chStatResult.ErrorMessage) ? string.Empty : chStatResult.ErrorMessage); mLog.Warn(notificationMsg); if (mergesToCheckins.ChangesetsByTargetBranch.Count == 0) { Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } Build.PostCheckinStage( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToCheckins, botConfig, codeReviewsStorageFile); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.Failed); } //LAST block -> if (mergesToCheckins.DestinationNewChangesWarnings.Count > 0) //Some of the checkins went wrong due to new changeset on at least a destination branch-> //We must run the post-ci plan for the successful ones, //but force requeuing of source branch, so the failed merges to dst branches are re-run mLog.InfoFormat("Setting branch {0} as 'resolved' (enqueue) ...", branch.FullName); MultilinerMergebotApi.ChangeBranchAttribute( restApi, branch.Repository, branch.FullName, botConfig.Plastic.StatusAttribute.Name, botConfig.Plastic.StatusAttribute.ResolvedValue); string dstBranchesNewCsetsMsg = string.Join( Environment.NewLine + "\t", mergesToCheckins.DestinationNewChangesWarnings); notificationMsg = string.Format( "Branch [{0}] will be enqueued again, as new changesets appeared in " + "merge destination branches, and thus, the branch needs to be tested again to " + "include those new changesets in the merge. Full report:{1}\t{2}", branch.FullName, Environment.NewLine, dstBranchesNewCsetsMsg); mLog.Warn(notificationMsg); if (mergesToCheckins.ChangesetsByTargetBranch.Count == 0) { Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.NotReady); } Build.PostCheckinStage( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToCheckins, botConfig, codeReviewsStorageFile); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); return(Result.NotReady); } catch (Exception ex) { mLog.ErrorFormat( "The attempt to process task {0} failed for branch {1}: {2}", taskNumber, branch.FullName, ex.Message); mLog.DebugFormat( "StackTrace:{0}{1}", Environment.NewLine, ex.StackTrace); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); notificationMsg = string.Format( "Can't process branch [{0}] because of an unexpected error: {1}.", branch.FullName, ex.Message); Notifier.NotifyTaskStatus( restApi, branch.Owner, notificationMsg, botConfig.Notifiers); BuildMergeReport.SetUnexpectedExceptionProperty(mergeReport, ex.Message); return(Result.Failed); } finally { ReportMerge(restApi, branch.Repository, branch.FullName, botName, mergeReport); MergeToOperations.SafeDeleteShelves( restApi, branch.Repository, destinationBranches, mergesToShelves); } }
internal static bool PreCheckinStage( IRestApi restApi, Branch branch, MergeReport mergeReport, string taskNumber, string[] destinationBranches, MergeToOperations.ShelveResult mergesToShelves, MultilinerBotConfiguration botConfig, string codeReviewsStorageFile) { if (botConfig.CI == null) { string noCIMessage = "No Continuous Integration Plug was set for this mergebot. Therefore, no " + "build actions for task " + taskNumber + " will be performed."; mLog.Info(noCIMessage); Notifier.NotifyTaskStatus( restApi, branch.Owner, noCIMessage, botConfig.Notifiers); return(true); } if (mergesToShelves == null || mergesToShelves.ShelvesByTargetBranch == null || mergesToShelves.ShelvesByTargetBranch.Count == 0) { string noShelvesErrorMessage = "Something wrong happened. There are no merge-to shelves to build task " + taskNumber; mLog.Info(noShelvesErrorMessage); Notifier.NotifyTaskStatus( restApi, branch.Owner, noShelvesErrorMessage, botConfig.Notifiers); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); return(false); } string startTestingMessage = string.Format( "Testing branch [{0}] before being merged in the following destination branches: [{1}].", branch.FullName, string.Join(", ", mergesToShelves.ShelvesByTargetBranch.Keys)); mLog.Info(startTestingMessage); ChangeTaskStatus.SetTaskAsTesting(restApi, branch, taskNumber, botConfig); Notifier.NotifyTaskStatus( restApi, branch.Owner, startTestingMessage, botConfig.Notifiers); int iniTime = Environment.TickCount; BuildOperations.Result result = BuildOperations.TryBuildTask( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToShelves.ShelvesByTargetBranch, Messages.BuildProperties.StageValues.PRE_CHECKIN, botConfig); BuildMergeReport.AddBuildTimeProperty( mergeReport, Environment.TickCount - iniTime); if (result.AreAllSuccessful) { BuildMergeReport.AddSucceededBuildProperty( mergeReport, botConfig.CI.PlanBranch); return(true); } string errorMessage = string.Join(Environment.NewLine, result.ErrorMessages); BuildMergeReport.AddFailedBuildProperty( mergeReport, botConfig.CI.PlanBranch, errorMessage); ChangeTaskStatus.SetTaskAsFailed( restApi, branch, taskNumber, botConfig, codeReviewsStorageFile); Notifier.NotifyTaskStatus( restApi, branch.Owner, errorMessage, botConfig.Notifiers); return(false); }
internal static Result PostCheckinStage( IRestApi restApi, Branch branch, MergeReport mergeReport, string taskNumber, string[] destinationBranches, MergeToOperations.CheckinResult mergesToCheckins, MultilinerBotConfiguration botConfig, string codeReviewsStorageFile) { if (!HasToRunPlanAfterTaskMerged(botConfig.CI)) { string noCIMessage = "No Continuous Integration Plug was set for this mergebot. Therefore, no " + "build actions for task " + taskNumber + " will be performed."; mLog.Info(noCIMessage); return(Result.Ok); } if (mergesToCheckins == null || mergesToCheckins.ChangesetsByTargetBranch == null || mergesToCheckins.ChangesetsByTargetBranch.Count == 0) { string noChangesetsErrorMessage = string.Format( "Something wrong happened. There are no merge-to changesets to build after " + "merging branch [{0}] to its destination branches.", branch.FullName); mLog.Info(noChangesetsErrorMessage); Notifier.NotifyTaskStatus( restApi, branch.Owner, noChangesetsErrorMessage, botConfig.Notifiers); return(Result.Failed); } string startTestingMessage = string.Format( "Testing branch [{0}] after being merged in the following destination branches: [{1}].", branch.FullName, string.Join(", ", mergesToCheckins.ChangesetsByTargetBranch.Keys)); mLog.Info(startTestingMessage); Notifier.NotifyTaskStatus( restApi, branch.Owner, startTestingMessage, botConfig.Notifiers); int iniTime = Environment.TickCount; BuildOperations.Result result = BuildOperations.TryBuildTask( restApi, branch, mergeReport, taskNumber, destinationBranches, mergesToCheckins.ChangesetsByTargetBranch, Messages.BuildProperties.StageValues.POST_CHECKIN, botConfig); BuildMergeReport.AddBuildTimeProperty( mergeReport, Environment.TickCount - iniTime); if (result.AreAllSuccessful) { BuildMergeReport.AddSucceededBuildProperty( mergeReport, botConfig.CI.PlanAfterCheckin); string notifyOKMesage = string.Format( "Build successful after merging branch [{0}] " + "to the following destination branches: [{1}].", branch.FullName, string.Join(", ", mergesToCheckins.ChangesetsByTargetBranch.Keys)); Notifier.NotifyTaskStatus( restApi, branch.Owner, notifyOKMesage, botConfig.Notifiers); return(Result.Ok); } string errorMessage = string.Join(Environment.NewLine, result.ErrorMessages); BuildMergeReport.AddFailedBuildProperty( mergeReport, botConfig.CI.PlanAfterCheckin, errorMessage); Notifier.NotifyTaskStatus( restApi, branch.Owner, errorMessage, botConfig.Notifiers); return(Result.Failed); }