Exemple #1
0
        static BuildProperties CreateBuildProperties(
            RestApi restApi,
            string taskNumber,
            string branchName,
            string labelName,
            string buildStagePreCiOrPostCi,
            TrunkBotConfiguration botConfig)
        {
            int branchHeadChangesetId = TrunkMergebotApi.GetBranchHead(
                restApi, botConfig.Repository, branchName);
            ChangesetModel branchHeadChangeset = TrunkMergebotApi.GetChangeset(
                restApi, botConfig.Repository, branchHeadChangesetId);

            int trunkHeadChangesetId = TrunkMergebotApi.GetBranchHead(
                restApi, botConfig.Repository, botConfig.TrunkBranch);
            ChangesetModel trunkHeadChangeset = TrunkMergebotApi.GetChangeset(
                restApi, botConfig.Repository, trunkHeadChangesetId);

            return(new BuildProperties
            {
                BranchName = branchName,
                TaskNumber = taskNumber,
                BranchHead = branchHeadChangeset.ChangesetId.ToString(),
                BranchHeadGuid = branchHeadChangeset.Guid.ToString(),
                ChangesetOwner = branchHeadChangeset.Owner,
                TrunkHead = trunkHeadChangeset.ChangesetId.ToString(),
                TrunkHeadGuid = trunkHeadChangeset.Guid.ToString(),
                RepSpec = string.Format("{0}@{1}", botConfig.Repository, botConfig.Server),
                LabelName = labelName,
                Stage = buildStagePreCiOrPostCi
            });
        }
Exemple #2
0
        static void SafeDeleteShelve(
            RestApi restApi,
            string repository,
            int shelveId)
        {
            if (shelveId == -1)
            {
                return;
            }

            try
            {
                TrunkMergebotApi.DeleteShelve(restApi, repository, shelveId);
            }
            catch (Exception ex)
            {
                mLog.ErrorFormat(
                    "Unable to delete shelve {0} on repository '{1}': {2}",
                    shelveId, repository, ex.Message);

                mLog.DebugFormat(
                    "StackTrace:{0}{1}",
                    Environment.NewLine, ex.StackTrace);
            }
        }
Exemple #3
0
        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 bool ExistsAttributeName(
            RestApi restApi,
            string repository,
            string attributeName)
        {
            string query = string.Format("attributetype where name='{0}' ", attributeName);

            JArray findResult = TrunkMergebotApi.Find(
                restApi,
                repository,
                query,
                DATE_FORMAT,
                "retrieve the list of attributes named " + attributeName,
                new string[] { "name" });

            return(findResult != null && findResult.Count > 0);
        }
Exemple #5
0
        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 string GetBranchName(
            RestApi restApi, string repository, string branchId)
        {
            string query = string.Format("branch where id={0}", branchId);

            JArray findResult = TrunkMergebotApi.Find(
                restApi,
                repository,
                query,
                DATE_FORMAT,
                "retrieve a single branch by ID",
                new string[] { "name" });

            if (findResult.Count == 0)
            {
                return(string.Empty);
            }

            return(GetStringValue((JObject)findResult[0], "name"));
        }
        internal static List <Branch> FindResolvedBranches(
            RestApi restApi,
            string repository,
            string prefix,
            string statusAttributeName,
            string resolvedStatusAttributeValue)
        {
            string query = string.Format(
                "branch where ( name like '{0}%' or name like '{1}%' or name like '{2}%' ) " +
                "and date > '{3}' " +
                "and attribute='{4}' and ( attrvalue='{5}' or attrvalue='{6}' or attrvalue='{7}') ",
                prefix,
                prefix.ToLowerInvariant(),
                prefix.ToUpperInvariant(),
                DateTime.Now.AddYears(-1).ToString(DATE_FORMAT),
                statusAttributeName,
                resolvedStatusAttributeValue,
                resolvedStatusAttributeValue.ToLowerInvariant(),
                resolvedStatusAttributeValue.ToUpperInvariant());

            JArray findResult = TrunkMergebotApi.Find(
                restApi,
                repository,
                query,
                DATE_FORMAT,
                "retrieve the list of branches to process",
                new string[] { "id", "name", "owner", "comment" });

            List <Branch> result = new List <Branch>();

            foreach (JObject obj in findResult)
            {
                result.Add(new Branch(
                               repository,
                               GetStringValue(obj, "id"),
                               GetStringValue(obj, "name"),
                               GetStringValue(obj, "owner"),
                               GetStringValue(obj, "comment")));
            }
            return(result);
        }
        internal static void SetTaskAsMerged(
            RestApi restApi,
            Branch branch,
            string taskNumber,
            string message,
            TrunkBotConfiguration botConfig,
            string codeReviewsStorageFile)
        {
            try
            {
                if (botConfig.Plastic.IsApprovedCodeReviewFilterEnabled)
                {
                    ReviewsStorage.DeleteBranchReviews(
                        branch.Repository, branch.Id, codeReviewsStorageFile);
                }

                TrunkMergebotApi.ChangeBranchAttribute(
                    restApi, branch.Repository, branch.FullName,
                    botConfig.Plastic.StatusAttribute.Name,
                    botConfig.Plastic.StatusAttribute.MergedValue);

                if (taskNumber != null && botConfig.Issues != null)
                {
                    TrunkMergebotApi.Issues.SetIssueField(
                        restApi, botConfig.Issues.Plug, botConfig.Issues.ProjectKey,
                        taskNumber, botConfig.Issues.StatusField.Name,
                        botConfig.Issues.StatusField.MergedValue);
                }

                Notifier.NotifyTaskStatus(
                    restApi, branch.Owner, message,
                    botConfig.Notifications);
            }
            catch (Exception ex)
            {
                Notifier.NotifyException(
                    restApi, branch, message,
                    "merged", ex, botConfig.Notifications);
            }
        }
        internal static void SetTaskAsTesting(
            RestApi restApi,
            Branch branch,
            string taskNumber,
            string message,
            TrunkBotConfiguration botConfig)
        {
            try
            {
                if (!string.IsNullOrEmpty(botConfig.Plastic.StatusAttribute.TestingValue))
                {
                    TrunkMergebotApi.ChangeBranchAttribute(
                        restApi, branch.Repository, branch.FullName,
                        botConfig.Plastic.StatusAttribute.Name,
                        botConfig.Plastic.StatusAttribute.TestingValue);
                }

                if (taskNumber != null && botConfig.Issues != null &&
                    !string.IsNullOrEmpty(botConfig.Issues.StatusField.TestingValue))
                {
                    TrunkMergebotApi.Issues.SetIssueField(
                        restApi, botConfig.Issues.Plug, botConfig.Issues.ProjectKey,
                        taskNumber, botConfig.Issues.StatusField.Name,
                        botConfig.Issues.StatusField.TestingValue);
                }

                Notifier.NotifyTaskStatus(
                    restApi, branch.Owner, message,
                    botConfig.Notifications);
            }
            catch (Exception ex)
            {
                Notifier.NotifyException(
                    restApi, branch, message,
                    "testing", ex, botConfig.Notifications);
            }
        }
Exemple #10
0
        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);
        }
Exemple #11
0
 static bool IsMergeAllowed(RestApi restApi, Branch branch, string trunkBranch)
 {
     return(TrunkMergebotApi.IsMergeAllowed(
                restApi, branch.Repository, branch.FullName, trunkBranch));
 }
        internal static List <BranchWithReview> FindPendingBranchesWithReviews(
            RestApi restApi,
            string repository,
            string prefix,
            string statusAttributeName,
            string mergedStatusAttributeValue)
        {
            string reviewTypeConditionClause = string.Empty;

            //branches from a year ago matching with prefix with status!=merged (even those without any status set)
            string branchTypeConditionClause = string.Format(
                "( " +
                "    name like '{0}%' or name like '{1}%' or name like '{2}%' " +
                ") " +
                "and " +
                "( " +
                "    date > '{3}' " +
                ") " +
                "and " +
                "( " +
                "    (not attribute='{4}') or " +
                "    (attribute='{4}' and not ( attrvalue='{5}' or attrvalue='{6}' or attrvalue='{7}' )) " +
                ") ",
                prefix,
                prefix.ToUpperInvariant(),
                prefix.ToLowerInvariant(),
                DateTime.Now.AddYears(-1).ToString(DATE_FORMAT),
                statusAttributeName,
                mergedStatusAttributeValue,
                mergedStatusAttributeValue.ToUpperInvariant(),
                mergedStatusAttributeValue.ToLowerInvariant());

            string[] outputFields = new string[]
            { "branchid", "branchname", "branchowner", "branchcomment",
              "reviewid", "reviewtargetid", "reviewstatus", "reviewtitle" };

            JArray findResult = TrunkMergebotApi.FindBranchesWithReviews(
                restApi,
                repository,
                reviewTypeConditionClause,
                branchTypeConditionClause,
                DATE_FORMAT,
                "retrieve the list of branches with reviews to process",
                outputFields);

            List <BranchWithReview> result = new List <BranchWithReview>();
            Branch branch = null;
            Review review = null;

            foreach (JObject obj in findResult)
            {
                branch = new Branch(
                    repository,
                    GetStringValue(obj, "branchid"),
                    GetStringValue(obj, "branchname"),
                    GetStringValue(obj, "branchowner"),
                    GetStringValue(obj, "branchcomment"));

                review = new Review(
                    repository,
                    GetStringValue(obj, "reviewid"),
                    GetStringValue(obj, "reviewtargetid"),
                    TranslateCodeReviewStatus(GetStringValue(obj, "reviewstatus")),
                    GetStringValue(obj, "reviewtitle"));

                result.Add(new BranchWithReview()
                {
                    Branch = branch,
                    Review = review
                });
            }

            return(result);
        }