public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
        {
            statusCode = 0;
            properties = null;
            statusMessage = string.Empty;
            try
            {
                if (notificationType == NotificationType.Notification && notificationEventArgs is CheckinNotification)
                {
                    var checkinNotification = notificationEventArgs as CheckinNotification;
                    if (ShouldMergeItemsIfNecessary(requestContext, checkinNotification))
                    {
                        var changeset = requestContext.GetChangeset(checkinNotification.Changeset);
                        if (changeset != null)
                        {
                            TfsTeamProjectCollection impersonatedCollection = requestContext.GetImpersonatedCollection(changeset.Committer);
                            MergeWorkItems(impersonatedCollection, changeset.ChangesetId);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                TeamFoundationApplicationCore.LogException("Inmeta.TFS.MergeWorkItemEventHandler encountered an exception", ex);
            }

            return EventNotificationStatus.ActionPermitted;
        }
        /// <summary>
        /// TFS Main Event Handler
        /// </summary>
        /// <param name="requestContext">Event context passed in by TFS</param>
        /// <param name="notificationType">DecisionPoint or Notification</param>
        /// <param name="notificationEventArgs">Object that was published</param>
        /// <param name="statusCode">Code to return to the user when a decision point fails</param>
        /// <param name="statusMessage">Message to return to the user when a decision point fails</param>
        /// <param name="properties">Properties to return to the user when a decision point fails</param>
        /// <returns></returns>
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType,
                                                    object notificationEventArgs, out int statusCode, out string statusMessage,
                                                    out ExceptionPropertyCollection properties)
        {
            #region method outputs
            EventNotificationStatus returnStatus = EventNotificationStatus.ActionPermitted; //allows the action if no other subscribers reject
            statusCode = 0;
            properties = null;
            statusMessage = String.Empty;
            #endregion

            try {
                var ev = notificationEventArgs as WorkItemChangedEvent;
                if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) {
                    int thisWorkItemID = getWorkItemID(ev);
                    if (ev.ChangeType == ChangeTypes.New) { //new TFS Work Item created
                        returnStatus = TfsEvent_WorkItemCreated(requestContext, notificationEventArgs, ev.PortfolioProject, thisWorkItemID);
                    }
                }
            }
            catch (Exception exception) {
                TeamFoundationApplicationCore.LogException("Error processing event", exception);
            }

            return returnStatus;
        }
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
        {
            statusCode = 0;
            properties = null;
            statusMessage = string.Empty;

            try
            {
                if (notificationType == NotificationType.DecisionPoint &&
                    notificationEventArgs is CheckinNotification)
                {
                    var args = notificationEventArgs as
                               CheckinNotification;
                    if (args.PolicyOverrideInfo.PolicyFailures.Length > 0)
                    {
                        statusMessage = "Policy Overriding is not allowed.";
                        return EventNotificationStatus.ActionDenied;
                    }
                }
                return EventNotificationStatus.ActionPermitted;
            }
            catch (Exception ex)
            {
                // log the error and fail the check in
                statusMessage = "Error in plugin '" + this.Name + "', error details: "
                                + ex;
                EventLog.WriteEntry("TFS Service", statusMessage,
                    EventLogEntryType.Error);
                return EventNotificationStatus.ActionDenied;
            }
        }
        internal static void InformUserOfFailure(string email
            , TeamFoundationRequestContext requestContext, PushNotification pushNotification
            , List<Validation> validationResults)
        {
            var buf = new StringBuilder();
            buf.AppendFormat("{0}'s {1} request was refused for the following reasons:"
                , requestContext.GetNameToDisplay()
                , requestContext.ServiceName
                );
            buf.AppendLine();
            buf.AppendLine();
            foreach (var res in validationResults.Where(res => res.Fails))
            {
                buf.Append(" - ");
                buf.AppendLine(res.ReasonMessage);
            }
            buf.AppendLine();

            buf.AppendLine("Additional information:");
            buf.Append(requestContext.GetSummary());
            buf.AppendLine();

            var message = new MailMessage();
            message.From = new MailAddress(PluginConfiguration.Instance.EmailSender);
            message.To.Add(new MailAddress(email));
            message.Subject = "Push refused";
            message.Body = buf.ToString();
            var smtp = new SmtpClient(PluginConfiguration.Instance.EmailSmtpServer);
            smtp.Send(message);
        }
        public override async Task NotifyAsync(TeamFoundationRequestContext requestContext, INotification notification, BotElement bot, EventRuleElement matchingRule)
        {
            var token = bot.GetSetting("token");
            if (string.IsNullOrEmpty(token)) throw new ArgumentException("Missing token!");

            var tasks = new List<Task>();
            var slackClient = new SlackClient();

            foreach (string tfsUserName in notification.TargetUserNames)
            {
                var userId = bot.GetMappedUser(tfsUserName);

                if (userId != null)
                {
                    Message slackMessage = ToSlackMessage((dynamic)notification, bot, null, true);
                    if (slackMessage != null)
                    {
                        slackMessage.AsUser = true;
                        var t = Task.Run(async () =>
                        {
                            var response = await slackClient.SendApiMessageAsync(slackMessage, token, userId);
                            response.EnsureSuccessStatusCode();
                            var content = await response.Content.ReadAsStringAsync();
                        });
                        tasks.Add(t);
                    }
                }
            }

            await Task.WhenAll(tasks);
        }
示例#6
0
 public TFSHelper(TeamFoundationRequestContext requestContext, string projectName)
 {
     TFSCollection = getTeamProjectCollectionFromRequestContext(requestContext);
        // TFSCollection.EnsureAuthenticated();
     workItemStore = TFSCollection.GetService<WorkItemStore>();
     teamProject = workItemStore.Projects[projectName];
 }
示例#7
0
        internal static void LogRequest(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
        {
            if (!PluginConfiguration.Instance.HasLog)
                return;

            var lines = new List<string>();

            lines.Add(string.Format("Request from {0} for {1}"
                , requestContext.GetNameToDisplay()
                , requestContext.ServiceName
                ));
            lines.Add("Summary for " + requestContext.GetSummary());

            lines.Add(string.Format("{6} #{0} on {1} repo {2} at {3} by {5} ({4})"
                , pushNotification.PushId
                , pushNotification.TeamProjectUri
                , pushNotification.RepositoryName
                , pushNotification.PushTime
                , pushNotification.AuthenticatedUserName
                , pushNotification.Pusher
                , requestContext.Method.Name
                ));

            lines.Add("- Included Commits:");
            foreach (var commitHash in pushNotification.IncludedCommits)
            {
                var commit = repository.TryLookupObject(requestContext, commitHash) as TfsGitCommit;
                lines.Add(string.Format("   Commit {0}: {1} '{2}'"
                    , commit.ObjectId.DisplayHash()
                    , commit.GetCommitterName(requestContext)
                    , commit.GetComment(requestContext)
                    ));

                foreach (var parentCommit in commit.GetParents(requestContext))
                {
                    lines.Add(string.Format("      Parent {0}: {1} '{2}'"
                        , parentCommit.ObjectId.DisplayHash()
                        , parentCommit.GetCommitterName(requestContext)
                        , parentCommit.GetComment(requestContext)
                        ));
                }
            }

            lines.Add("- Ref Update Results:");
            foreach (var refUpdate in pushNotification.RefUpdateResults)
            {
                lines.Add(string.Format("   on {0} {1}..{2} is {3} (succeeded: {4}) rejecter '{5}' message '{6}'"
                    , refUpdate.Name
                    , refUpdate.NewObjectId.DisplayHash()
                    , refUpdate.OldObjectId.DisplayHash()
                    , refUpdate.Status
                    , refUpdate.Succeeded
                    , refUpdate.RejectedBy
                    , refUpdate.CustomMessage
                    ));
            }//for

            File.AppendAllLines(PluginConfiguration.Instance.LogFile, lines);
        }
示例#8
0
 public List<Validation> CheckRules(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
 {
     var res = new List<Validation>();
     foreach (var rule in this.Rules)
     {
         res.Add(rule.CheckRule(requestContext, pushNotification, repository));
     }//for
     return res;
 }
        long GetCommitSize(TfsGitCommit gitCommit, TeamFoundationRequestContext requestContext)
        {
            var tree = gitCommit.GetTree(requestContext);
            if (tree == null)
                return 0;

            long totalSize = tree.GetBlobs(requestContext).Aggregate(
                0L,
                (size, blob) => size + blob.GetLength(requestContext));
            return totalSize;
        }
示例#10
0
        public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
        {
            var result = new Validation();

            // refuse any push
            result.Fails = true;
            result.ReasonCode = 99;
            result.ReasonMessage = string.Format(
                "Repository '{0}' is in read-only mode",
                pushNotification.RepositoryName);

            return result;
        }
示例#11
0
 public void LeaveMethod(TeamFoundationRequestContext requestContext)
 {
     //Log(String.Format("LeaveMethod: {0} ({1})", requestContext.Method.Name, requestContext.Method.MethodType));
     //Log("Status: " + requestContext.Status.GetType());
     //foreach (var key in requestContext.Method.Parameters.AllKeys)
     //{
     //    Log(String.Format("{0} : {1}", key, requestContext.Method.Parameters[key]));
     //}
     //foreach (var key in requestContext.Items.Keys)
     //{
     //    Log(String.Format("{0} :: {1}", key, requestContext.Items[key].GetType()));
     //}
 }
        protected bool IsUserExempted(TeamFoundationRequestContext requestContext, PushNotification pushNotification)
        {
            string collectionUrl = requestContext.GetCollectionUri();
            // client API
            TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(collectionUrl));
            var identityManagement = tfs.GetService<IIdentityManagementService>();
            var requestIdentity = identityManagement.ReadIdentity(IdentitySearchFactor.AccountName, pushNotification.AuthenticatedUserName, MembershipQuery.Direct, ReadIdentityOptions.None);

            bool exempted = false;
            foreach (var groupName in this.Groups)
            {
                var groupIdentity = identityManagement.ReadIdentity(IdentitySearchFactor.AccountName, groupName, MembershipQuery.Direct, ReadIdentityOptions.None);
                exempted |= identityManagement.IsMember(groupIdentity.Descriptor, requestIdentity.Descriptor);
            }//for
            return exempted;
        }
        public async Task NotifyAsync(TeamFoundationRequestContext requestContext, INotification notification, BotElement bot, EventRuleElement matchingRule)
        {
            string room = bot.GetSetting("room");
            string baseUrl = bot.GetSetting("apiBaseUrl");
            string authToken = bot.GetSetting("roomNotificationToken");

            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);

            string json = ToJson((dynamic)notification, bot);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            string url = baseUrl + "/room/" + room + "/notification";
            requestContext.Trace(0, TraceLevel.Verbose, Constants.TraceArea, "HipChatNotifier", "Sending notification to {0}\n{1}", url, json);

            await httpClient.PostAsync(url, content).ContinueWith(t => t.Result.EnsureSuccessStatusCode());
        }
        public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
        {
            var result = new Validation();

            long totalSize = 0;
            foreach (var commitId in pushNotification.IncludedCommits)
            {
                TfsGitCommit gitCommit = repository.LookupObject(requestContext, commitId) as TfsGitCommit;
                if (gitCommit == null)
                    continue;

                long size = GetCommitSize(gitCommit, requestContext);
                totalSize += size;
            }//for

            // convert to MB
            totalSize = totalSize / (1024 * 1024);

            if (totalSize < this.Megabytes)
            {
                Logger.Log(string.Format(
                    "Push request is {0} MB, below the {1} MB limit."
                    , totalSize, this.Megabytes
                    , "Limit Size"));
            }
            else
            {
                if (IsUserExempted(requestContext, pushNotification))
                {
                    Logger.Log(string.Format(
                        "Push request is {0} MB, above or equal to the {1} MB limit, but user is exempted."
                        , totalSize, this.Megabytes
                        , "Limit Size"));
                }
                else
                {
                    result.Fails = true;
                    result.ReasonCode = 2;
                    result.ReasonMessage = string.Format(
                        "Push request is {0} MB, above or equal to the {1} MB limit: refused."
                        , totalSize, this.Megabytes);
                }
            }//if

            return result;
        }
示例#15
0
        public static bool IsForceRequired(this PushNotification pushNotification, TeamFoundationRequestContext requestContext, TfsGitRepository repository)
        {
            foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded))
            {
                // Don't bother with new or deleted refs
                if (refUpdateResult.OldObjectId.IsZero() || refUpdateResult.NewObjectId.IsZero()) continue;

                TfsGitObject gitObject = repository.LookupObject(requestContext, refUpdateResult.NewObjectId);
                if (gitObject.ObjectType != TfsGitObjectType.Commit) continue;
                TfsGitCommit gitCommit = (TfsGitCommit)gitObject;

                if (!gitCommit.IsDescendantOf(requestContext, refUpdateResult.OldObjectId))
                    return true;
            }

            return false;
        }
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out Microsoft.TeamFoundation.Common.ExceptionPropertyCollection properties)
        {
            statusCode = 0;
            properties = null;
            statusMessage = string.Empty;

            try
            {
                if (notificationType == NotificationType.Notification &&
                    notificationEventArgs is CheckinNotification)
                {
                    CheckinNotification args = notificationEventArgs as CheckinNotification;
                    NumberParser numberParser = new NumberParser();
                    WorkItemStore workItemStore = WorkItemStoreFactory.GetWorkItemStore(GetTFSUri(requestContext));
                    VersionControlServer service = workItemStore.TeamProjectCollection.GetService<VersionControlServer>();
                    Changeset changeset = service.GetChangeset(args.Changeset);
                    foreach (int workItemID in numberParser.Parse(args.Comment))
                    {
                        var workItem = workItemStore.GetWorkItem(workItemID);

                        if (workItem != null)
                        {
                            //now create the link
                            ExternalLink changesetLink = new ExternalLink(
                                workItemStore.RegisteredLinkTypes[ArtifactLinkIds.Changeset],
                                changeset.ArtifactUri.AbsoluteUri);
                            //you should verify if such a link already exists
                            if (!workItem.Links.OfType<ExternalLink>()
                                .Any(l => l.LinkedArtifactUri == changeset.ArtifactUri.AbsoluteUri))
                            {
                                workItem.Links.Add(changesetLink);
                                workItem.Save();
                            }
                        }
                    }
                }
                return EventNotificationStatus.ActionPermitted;
            }
            catch (Exception ex)
            {
                // log the error and fail the check in
                statusMessage = "Error in plugin '" + Name + "', error details: " + ex.ToString();
                EventLog.WriteEntry("TFS Service", statusMessage, EventLogEntryType.Error);
                return EventNotificationStatus.ActionDenied;
            }
        }
示例#17
0
 internal static void LogEvent(TeamFoundationRequestContext requestContext, string message, LogEventInformationLevel informationLevel)
 {
     switch (informationLevel)
     {
         case LogEventInformationLevel.Information:
             TeamFoundationTrace.Info(message);
             break;
         case LogEventInformationLevel.Warning:
             TeamFoundationTrace.Warning(message);
             TeamFoundationApplicationCore.Log(requestContext, message, TeamFoundationEventId.WarehouseErrorsBaseEventId, System.Diagnostics.EventLogEntryType.Warning);
             break;
         case LogEventInformationLevel.Error:
             TeamFoundationTrace.Error(message);
             TeamFoundationApplicationCore.Log(requestContext, message, TeamFoundationEventId.WarehouseErrorsBaseEventId, System.Diagnostics.EventLogEntryType.Error);
             break;
     }
 }
示例#18
0
        public async Task NotifyAsync(TeamFoundationRequestContext requestContext, INotification notification, BotElement bot, EventRuleElement matchingRule)
        {
            var channels = bot.GetCsvSetting("channels");
            var tasks = new List<Task>();
            var slackClient = new SlackClient();

            foreach (string channel in channels)
            {
                Message slackMessage = ToSlackMessage((dynamic)notification, bot, channel);
                if (slackMessage != null)
                {
                    tasks.Add(slackClient.SendMessageAsync(slackMessage, bot.GetSetting("webhookUrl")).ContinueWith(t => t.Result.EnsureSuccessStatusCode()));
                }
            }

            await Task.WhenAll(tasks);
        }
        protected EventNotificationStatus TfsEvent_WorkItemCreated(TeamFoundationRequestContext requestContext, object notificationEventArgs, string TFSProjectName,int TFSworkItemID)
        {
            TFSHelper tfs = new TFSHelper(requestContext, TFSProjectName);

            if (TFSworkItemID > 0) {
                Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem thisWorkItem = tfs.getWorkItem(TFSworkItemID);

                if ((thisWorkItem != null)) {
                    if (tfs.isWorkItemEligibleForClone(thisWorkItem)) {
                        Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem templateWorkItem = tfs.getTemplateForWorkItem(thisWorkItem);
                        if (templateWorkItem != null) tfs.createChildWorkItems(thisWorkItem, templateWorkItem);
                    }
                }
                else { throw new System.Exception(string.Format(Resources.errorMessages.UNABLETOGET_WORKITEM, TFSworkItemID.ToString())); }
            }
            else {throw new System.ArgumentException(String.Format(Resources.errorMessages.ERROR_INVALID_WORK_ITEMID, TFSworkItemID.ToString()));}

            return EventNotificationStatus.ActionPermitted; //allows the action if no other subscribers reject.
        }
        public override Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
        {
            var result = new Validation();

            foreach (var refUpdateResult in pushNotification.RefUpdateResults)
            {
                // new or deleted refs have id==0
                if (IsNullHash(refUpdateResult.OldObjectId)
                    || IsNullHash(refUpdateResult.NewObjectId))
                    continue;

                TfsGitCommit gitCommit = repository.LookupObject(requestContext, refUpdateResult.NewObjectId) as TfsGitCommit;
                if (gitCommit == null)
                    continue;

                string authorEmail = gitCommit.GetAuthorEmail(requestContext);
                if (!AuthorEmail.Any(pattern => Regex.IsMatch(authorEmail, pattern)))
                {
                    result.Fails = true;
                    result.ReasonCode = 2;
                    result.ReasonMessage = string.Format(
                        "Author email '{0}' on commit {1} is not admitted",
                        authorEmail,
                        gitCommit.ObjectId.DisplayHash());
                    break;
                }

                string committerEmail = gitCommit.GetCommitterEmail(requestContext);
                if (!CommitterEmail.Any(pattern => Regex.IsMatch(committerEmail, pattern)))
                {
                    result.Fails = true;
                    result.ReasonCode = 3;
                    result.ReasonMessage = string.Format(
                        "Committer email '{0}' on commit {1} is not admitted",
                        authorEmail,
                        gitCommit.ObjectId.DisplayHash());
                    break;
                }//if
            }//for changes

            return result;
        }
示例#21
0
        public static bool IsDescendantOf(this TfsGitCommit commit, TeamFoundationRequestContext requestContext, byte[] ancestorId)
        {
            Queue<TfsGitCommit> q = new Queue<TfsGitCommit>();
            HashSet<byte[]> visited = new HashSet<byte[]>(new ByteArrayComparer());

            q.Enqueue(commit);

            while (q.Count > 0)
            {
                TfsGitCommit current = q.Dequeue();
                if (!visited.Add(current.ObjectId))
                    continue;

                if (current.ObjectId.SequenceEqual(ancestorId)) return true;

                foreach (var c in current.GetParents(requestContext))
                    q.Enqueue(c);

            }
            return false;
        }
示例#22
0
        /// <summary>
        /// This is the one where all the magic starts.  Main() so to speak.  I will load the settings, connect to tfs and apply the aggregation rules.
        /// </summary>
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs,
                                                    out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
        {
            statusCode    = 0;
            properties    = null;
            statusMessage = String.Empty;
            int    currentAggregationId   = 0;
            int    workItemId             = 0;
            string currentAggregationName = string.Empty;

            try
            {
                if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
                {
                    // Change this object to be a type we can easily get into
                    WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent;
                    // Connect to the setting file and load the location of the TFS server
                    string tfsUri = TFSAggregatorSettings.TFSUri;
                    // Connect to TFS so we are ready to get and send data.
                    Store store = new Store(tfsUri);
                    // Get the id of the work item that was just changed by the user.
                    workItemId = ev.CoreFields.IntegerFields[0].NewValue;
                    // Download the work item so we can update it (if needed)
                    WorkItem        eventWorkItem    = store.Access.GetWorkItem(workItemId);
                    string          workItemTypeName = eventWorkItem.Type.Name;
                    List <WorkItem> workItemsToSave  = new List <WorkItem>();

                    if (TFSAggregatorSettings.LoggingIsEnabled)
                    {
                        MiscHelpers.LogMessage(String.Format("Change detected to {0} [{1}]", workItemTypeName, workItemId));
                        MiscHelpers.LogMessage(String.Format("{0}Processing {1} AggregationItems", "  ", TFSAggregatorSettings.ConfigAggregatorItems.Count.ToString()));
                    }

                    // Apply the aggregation rules to the work item
                    foreach (ConfigAggregatorItem configAggregatorItem in TFSAggregatorSettings.ConfigAggregatorItems)
                    {
                        IEnumerable <WorkItem> sourceWorkItems = null;
                        WorkItem targetWorkItem = null;
                        currentAggregationName = configAggregatorItem.Name;

                        // Check to make sure that the rule applies to the work item type we have
                        if (eventWorkItem.Type.Name == configAggregatorItem.WorkItemType)
                        {
                            if (TFSAggregatorSettings.LoggingIsEnabled)
                            {
                                MiscHelpers.LogMessage(String.Format("{0}[Entry {2}] Aggregation '{3}' applies to {1} work items", "    ", workItemTypeName, currentAggregationId, currentAggregationName));
                            }

                            // Use the link type to see what the work item we are updating is
                            if (configAggregatorItem.LinkType == ConfigLinkTypeEnum.Self)
                            {
                                // We are updating the same workitem that was sent in the event.
                                sourceWorkItems = new List <WorkItem> {
                                    eventWorkItem
                                };
                                targetWorkItem = eventWorkItem;

                                if (TFSAggregatorSettings.LoggingIsEnabled)
                                {
                                    MiscHelpers.LogMessage(String.Format("{0}{0}{0}Aggregation applies to SELF. ({1} {2})", "  ", workItemTypeName, workItemId));
                                }

                                // Make sure that all conditions are true before we do the aggregation
                                // If any fail then we don't do this aggregation.
                                if (!configAggregatorItem.Conditions.AreAllConditionsMet(targetWorkItem))
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled)
                                    {
                                        MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for aggregation are not met.", "    "));
                                    }
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled)
                                {
                                    MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for aggregation are met.", "    "));
                                }
                            }
                            // We are aggregating to the parent
                            else if (configAggregatorItem.LinkType == ConfigLinkTypeEnum.Parent)
                            {
                                bool parentLevelFound = true;

                                // Go up the tree till we find the level of parent that we are looking for.
                                WorkItem iterateToParent = eventWorkItem;
                                for (int i = 0; i < configAggregatorItem.LinkLevel; i++)
                                {
                                    // Load the parent from the saved list (if we have it in there) or just load it from the store.
                                    WorkItem nullCheck = iterateToParent.GetParentFromListOrStore(workItemsToSave, store);
                                    //
                                    if (nullCheck != null)
                                    {
                                        iterateToParent = nullCheck;
                                    }
                                    else
                                    {
                                        parentLevelFound = false;
                                    }
                                }
                                // If we did not find the correct parent then we are done with this aggregation.
                                if (!parentLevelFound)
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled)
                                    {
                                        MiscHelpers.LogMessage(String.Format("{0}{0}{0}Couldn't find a PARENT {2} {4} up from {3} [{1}]. This aggregation will not continue.", "  ", workItemId, configAggregatorItem.LinkLevel, workItemTypeName, configAggregatorItem.LinkLevel > 1 ? "levels" : "level"));
                                    }
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled)
                                {
                                    MiscHelpers.LogMessage(String.Format("{0}{0}{0}Found {1} [{2}] {3} {4} up from {5} [{6}].  Aggregation continues.", "  ", iterateToParent.Type.Name, iterateToParent.Id, configAggregatorItem.LinkLevel, configAggregatorItem.LinkLevel > 1 ? "levels" : "level", workItemTypeName, workItemId));
                                }

                                targetWorkItem = iterateToParent;

                                // Make sure that all conditions are true before we do the aggregation
                                // If any fail then we don't do this aggregation.
                                if (!configAggregatorItem.Conditions.AreAllConditionsMet(targetWorkItem))
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled)
                                    {
                                        MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for parent aggregation are not met", "    "));
                                    }
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled)
                                {
                                    MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for parent aggregation are met", "    "));
                                }

                                // Get the children down how ever many link levels were specified.
                                List <WorkItem> iterateFromParents = new List <WorkItem> {
                                    targetWorkItem
                                };
                                for (int i = 0; i < configAggregatorItem.LinkLevel; i++)
                                {
                                    List <WorkItem> thisLevelOfKids = new List <WorkItem>();
                                    // Iterate all the parents to find the children of current set of parents
                                    foreach (WorkItem iterateFromParent in iterateFromParents)
                                    {
                                        thisLevelOfKids.AddRange(iterateFromParent.GetChildrenFromListOrStore(workItemsToSave, store));
                                    }

                                    iterateFromParents = thisLevelOfKids;
                                }

                                // remove the kids that are not the right type that we are working with
                                ConfigAggregatorItem configAggregatorItemClosure = configAggregatorItem;
                                iterateFromParents.RemoveAll(x => x.Type.Name != configAggregatorItemClosure.WorkItemType);

                                sourceWorkItems = iterateFromParents;
                            }

                            // Do the actual aggregation now
                            bool changeMade = Aggregator.Aggregate(sourceWorkItems, targetWorkItem, configAggregatorItem);

                            // If we made a change then add this work item to the list of items to save.
                            if (changeMade)
                            {
                                // Add the target work item to the list of work items to save.
                                workItemsToSave.AddIfUnique(targetWorkItem);
                            }
                        }
                        else
                        {
                            if (TFSAggregatorSettings.LoggingIsEnabled)
                            {
                                MiscHelpers.LogMessage(String.Format("{0}[Entry {2}] Aggregation '{3}' does not apply to {1} work items", "    ", workItemTypeName, currentAggregationId, currentAggregationName));
                            }
                        }

                        currentAggregationId++;
                    }

                    // Save any changes to the target work items.
                    workItemsToSave.ForEach(x =>
                    {
                        bool isValid = x.IsValid();

                        if (TFSAggregatorSettings.LoggingIsEnabled)
                        {
                            MiscHelpers.LogMessage(String.Format("{0}{0}{0}{1} [{2}] {3} valid to save. {4}",
                                                                 "    ",
                                                                 x.Type.Name,
                                                                 x.Id,
                                                                 isValid ? "IS" : "IS NOT",
                                                                 String.Format("\n{0}{0}{0}{0}Invalid fields: {1}", "    ", MiscHelpers.GetInvalidWorkItemFieldsList(x).ToString())));
                        }

                        if (isValid)
                        {
                            x.PartialOpen();
                            x.Save();
                        }
                    });

                    MiscHelpers.AddRunSeparatorToLog();
                }
            }
            catch (Exception e)
            {
                string message = String.Format("Exception encountered processing Work Item [{2}]: {0} \nStack Trace:{1}", e.Message, e.StackTrace, workItemId);
                if (e.InnerException != null)
                {
                    message += String.Format("\n    Inner Exception: {0} \nStack Trace:{1}", e.InnerException.Message, e.InnerException.StackTrace);
                }
                MiscHelpers.LogMessage(message, true);
            }

            return(EventNotificationStatus.ActionPermitted);
        }
 /// <summary>
 /// Shortcut for tracing - could be refactored further
 /// </summary>
 /// <param name="requestContext"></param>
 /// <param name="message"></param>
 /// <param name="args"></param>
 private void Trace(TeamFoundationRequestContext requestContext, string message, params object[] args)
 {
     requestContext.Trace(0, TraceLevel.Verbose, Constants.TraceArea, this.GetType().Name, message, args);
 }
示例#24
0
        protected override IEnumerable <Notifications.INotification> CreateNotifications(TeamFoundationRequestContext requestContext, ReviewerVoteNotification ev, int maxLines)
        {
            var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>();
            var identityService   = requestContext.GetService <ITeamFoundationIdentityService>();
            var commonService     = requestContext.GetService <ICommonStructureService>();

            var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Reviewer.Identifier);

            using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId))
            {
                var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>();
                TfsGitPullRequest pullRequest;
                if (pullRequestService.TryGetPullRequestDetails(requestContext, repository, ev.PullRequestId, out pullRequest))
                {
                    string repoUri      = repository.GetRepositoryUri(requestContext);
                    var    creator      = identityService.ReadIdentities(requestContext, new[] { pullRequest.Creator }).First();
                    var    reviewers    = identityService.ReadIdentities(requestContext, pullRequest.Reviewers.Select(r => r.Reviewer).ToArray());
                    var    notification = new Notifications.PullRequestReviewerVoteNotification()
                    {
                        TeamProjectCollection = requestContext.ServiceHost.Name,
                        CreatorUniqueName     = creator.UniqueName,
                        Vote              = ev.ReviewerVote,
                        UniqueName        = identity.UniqueName,
                        DisplayName       = identity.DisplayName,
                        ProjectName       = commonService.GetProject(requestContext, ev.TeamProjectUri).Name,
                        RepoUri           = repoUri,
                        RepoName          = ev.RepositoryName,
                        PrId              = pullRequest.PullRequestId,
                        PrUrl             = $"{repoUri}/pullrequest/{ev.PullRequestId}#view=discussion",
                        PrTitle           = pullRequest.Title,
                        TeamNames         = GetUserTeamsByProjectUri(requestContext, ev.TeamProjectUri, ev.Reviewer),
                        SourceBranch      = new Notifications.GitRef(pullRequest.SourceBranchName),
                        TargetBranch      = new Notifications.GitRef(pullRequest.TargetBranchName),
                        ReviewerUserNames = reviewers.Select(r => r.UniqueName)
                    };
                    yield return(notification);
                }
                else
                {
                    throw new TfsNotificationRelayException("Unable to get pull request " + ev.PullRequestId);
                }
            }
        }
示例#25
0
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType,
                                                    object notificationEventArgs, out int statusCode, out string statusMessage, out Microsoft.TeamFoundation.Common.ExceptionPropertyCollection properties)
        {
            statusCode    = 0;
            statusMessage = string.Empty;
            properties    = null;

            try
            {
                if (notificationType == NotificationType.Notification && notificationEventArgs is PushNotification)
                {
                    Stopwatch timer = new Stopwatch();
                    timer.Start();

                    PushNotification pushNotification = notificationEventArgs as PushNotification;
                    var repositoryService             = requestContext.GetService <TeamFoundationGitRepositoryService>();
                    var commonService = requestContext.GetService <CommonStructureService>();

                    using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId))
                    {
                        string repoName    = pushNotification.RepositoryName;
                        string projectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name;
                        string userName    = pushNotification.AuthenticatedUserName.Replace(DOMAIN_PREFIX, "");

                        var lines = new List <string>();

                        string pushText = pushNotification.IsForceRequired(requestContext, repository) ? "FORCE push" : "push";
                        lines.Add(String.Format("{0} by {1} to {2}/{3}", pushText, userName, projectName, repoName));

                        var refNames   = new Dictionary <byte[], List <string> >(new ByteArrayComparer());
                        var oldCommits = new HashSet <byte[]>(new ByteArrayComparer());
                        var unknowns   = new List <RefUpdateResultGroup>();

                        // Associate refs (branch, ligtweight and annotated tag) with corresponding commit
                        var refUpdateResultGroups = pushNotification.RefUpdateResults
                                                    .Where(r => r.Succeeded)
                                                    .GroupBy(r => r.NewObjectId, (key, items) => new RefUpdateResultGroup(key, items), new ByteArrayComparer());

                        foreach (var refUpdateResultGroup in refUpdateResultGroups)
                        {
                            byte[] newObjectId = refUpdateResultGroup.NewObjectId;
                            byte[] commitId    = null;

                            if (newObjectId.IsZero())
                            {
                                commitId = newObjectId;
                            }
                            else
                            {
                                TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId);

                                if (gitObject.ObjectType == TfsGitObjectType.Commit)
                                {
                                    commitId = newObjectId;
                                }
                                else if (gitObject.ObjectType == TfsGitObjectType.Tag)
                                {
                                    var tag    = (TfsGitTag)gitObject;
                                    var commit = tag.TryResolveToCommit(requestContext);
                                    if (commit != null)
                                    {
                                        commitId = commit.ObjectId;
                                    }
                                }
                            }

                            if (commitId != null)
                            {
                                List <string> names;
                                if (!refNames.TryGetValue(commitId, out names))
                                {
                                    names = new List <string>();
                                    refNames.Add(commitId, names);
                                }
                                names.AddRange(RefsToStrings(refUpdateResultGroup.RefUpdateResults));

                                if (commitId.IsZero() || !pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commitId)))
                                {
                                    oldCommits.Add(commitId);
                                }
                            }
                            else
                            {
                                unknowns.Add(refUpdateResultGroup);
                            }
                        }

                        // Display new commits with refs
                        foreach (byte[] commitId in pushNotification.IncludedCommits)
                        {
                            TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId);
                            string       line      = CommitToString(requestContext, gitCommit, "commit", pushNotification, refNames);
                            lines.Add(line);
                        }

                        // Display updated refs to old commits
                        foreach (byte[] commitId in oldCommits)
                        {
                            string line = null;

                            if (commitId.IsZero())
                            {
                                line = String.Format("{0} deleted", String.Join("", refNames[commitId]));
                            }
                            else
                            {
                                TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId);
                                line = CommitToString(requestContext, gitCommit, "->", pushNotification, refNames);
                            }
                            lines.Add(line);
                        }

                        // Display "unknown" refs
                        foreach (var refUpdateResultGroup in unknowns)
                        {
                            byte[]       newObjectId = refUpdateResultGroup.NewObjectId;
                            TfsGitObject gitObject   = repository.LookupObject(requestContext, newObjectId);
                            string       line        = String.Format("{0} -> {1} {2}", RefsToString(refUpdateResultGroup.RefUpdateResults), gitObject.ObjectType, newObjectId.ToHexString());

                            lines.Add(line);
                        }

                        //Log(lines);

                        List <string> sendLines = lines;
                        if (lines.Count > MAX_LINES)
                        {
                            sendLines = lines.Take(MAX_LINES).ToList();
                            sendLines.Add(String.Format("{0} more line(s) suppressed.", lines.Count - MAX_LINES));
                        }

                        Task.Run(() => SendToBot(sendLines));
                    }

                    timer.Stop();
                    //Log("Time spent in ProcessEvent: " + timer.Elapsed);
                }
            }
            catch (Exception ex)
            {
                Log(ex.Message);
                Log(ex.StackTrace);
            }

            return(EventNotificationStatus.ActionPermitted);
        }
示例#26
0
 protected abstract IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, T notificationEventArgs, int maxLines);
示例#27
0
 public void BeginRequest(TeamFoundationRequestContext requestContext)
 {
 }
示例#28
0
 public void EndRequest(TeamFoundationRequestContext requestContext)
 {
 }
        protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, PushNotification pushNotification, int maxLines)
        {
            var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>();
            var commonService     = requestContext.GetService <CommonStructureService>();
            var commitService     = requestContext.GetService <TeamFoundationGitCommitService>();
            var identityService   = requestContext.GetService <TeamFoundationIdentityService>();

            var identity  = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, pushNotification.Pusher.Identifier);
            var teamNames = GetUserTeamsByProjectUri(requestContext, pushNotification.TeamProjectUri, pushNotification.Pusher);

            using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId))
            {
                var pushRow = new PushRow()
                {
                    UniqueName  = pushNotification.AuthenticatedUserName,
                    DisplayName = identity.DisplayName,
                    RepoName    = pushNotification.RepositoryName,
                    RepoUri     = repository.GetRepositoryUri(requestContext),
                    ProjectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name,
                    IsForcePush = settings.IdentifyForcePush ? pushNotification.IsForceRequired(requestContext, repository) : false
                };
                var notification = new GitPushNotification(requestContext.ServiceHost.Name, pushRow.ProjectName,
                                                           pushNotification.AuthenticatedUserName, pushRow.RepoName, teamNames,
                                                           pushNotification.RefUpdateResults.Where(r => r.Succeeded).Select(r => new GitRef(r)));
                notification.Add(pushRow);
                notification.TotalLineCount++;

                var refLookup   = new Dictionary <byte[], List <GitRef> >(new ByteArrayComparer());
                var deletedRefs = new List <GitRef>();
                var oldCommits  = new HashSet <TfsGitCommit>(new TfsGitObjectEqualityComparer());
                var unknowns    = new List <TfsGitRefUpdateResult>();

                // Associate refs (branch, lightweight and annotated tag) with corresponding commit
                foreach (var refUpdateResult in pushNotification.RefUpdateResults.Where(r => r.Succeeded))
                {
                    var          newObjectId = refUpdateResult.NewObjectId;
                    TfsGitCommit commit      = null;

                    if (newObjectId.IsZero())
                    {
                        deletedRefs.Add(new GitRef(refUpdateResult));
                        continue;
                    }

                    TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId);

                    if (gitObject.ObjectType == TfsGitObjectType.Commit)
                    {
                        commit = gitObject as TfsGitCommit;
                    }
                    else if (gitObject.ObjectType == TfsGitObjectType.Tag)
                    {
                        var tag = (TfsGitTag)gitObject;
                        commit = tag.TryResolveToCommit(requestContext);
                    }

                    if (commit != null)
                    {
                        List <GitRef> refs;
                        if (!refLookup.TryGetValue(commit.ObjectId, out refs))
                        {
                            refs = new List <GitRef>();
                            refLookup.Add(commit.ObjectId, refs);
                        }
                        refs.Add(new GitRef(refUpdateResult));

                        if (!pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commit.ObjectId)))
                        {
                            oldCommits.Add(commit);
                        }
                    }
                    else
                    {
                        unknowns.Add(refUpdateResult);
                    }
                }

                notification.TotalLineCount += pushNotification.IncludedCommits.Count() + oldCommits.Count + unknowns.Count;

                // Add new commits with refs
                foreach (var commitId in pushNotification.IncludedCommits.TakeWhile(c => notification.Count < maxLines))
                {
                    TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId);
                    notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.Commit, pushNotification, refLookup));
                }

                // Add updated refs to old commits
                foreach (TfsGitCommit gitCommit in oldCommits.OrderByDescending(c => c.GetCommitTime(requestContext)).TakeWhile(c => notification.Count < maxLines))
                {
                    notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.RefUpdate, pushNotification, refLookup));
                }

                // Add deleted refs if any
                if (deletedRefs.Any() && notification.Count < maxLines)
                {
                    notification.Add(new DeleteRow()
                    {
                        Refs = deletedRefs
                    });
                }

                // Add "unknown" refs
                foreach (var refUpdateResult in unknowns.TakeWhile(c => notification.Count < maxLines))
                {
                    var          newObjectId = refUpdateResult.NewObjectId;
                    TfsGitObject gitObject   = repository.LookupObject(requestContext, newObjectId);
                    notification.Add(new RefUpdateRow()
                    {
                        NewObjectId = newObjectId,
                        ObjectType  = gitObject.ObjectType,
                        Refs        = new[] { new GitRef(refUpdateResult) }
                    });
                }

                yield return(notification);
            }
        }
示例#30
0
 public void RequestReady(TeamFoundationRequestContext requestContext)
 {
 }
示例#31
0
 public abstract Validation CheckRule(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository);
        public EventNotificationStatus ProcessEvent(
            TeamFoundationRequestContext requestContext, NotificationType notificationType,
            object notificationEventArgs,
            out int statusCode, out string statusMessage,
            out Microsoft.TeamFoundation.Common.ExceptionPropertyCollection properties)
        {
            statusCode = 0;
            statusMessage = string.Empty;
            properties = null;

            try
            {
                if (notificationType == NotificationType.DecisionPoint
                    && notificationEventArgs is PushNotification)
                {
                    PushNotification pushNotification = notificationEventArgs as PushNotification;

                    // validation applies?
                    var policy = GetPolicy(requestContext, pushNotification);
                    if (policy != null)
                    {
                        Logger.LogStart("Request controlled by policy");

                        var gitRepoService = requestContext.GetService<TeamFoundationGitRepositoryService>();
                        using (var repository = gitRepoService.FindRepositoryById(requestContext, pushNotification.RepositoryId))
                        {
                            Logger.LogRequest(requestContext, pushNotification, repository);

                            var validationResults = policy.CheckRules(requestContext, pushNotification, repository);
                            //TODO accumulate failures
                            var failsAt = validationResults.FirstOrDefault(v => v.Fails);
                            if (failsAt != null)
                            {
                                if (PluginConfiguration.Instance.ShouldSendEmail)
                                {
                                    try
                                    {
                                        string email = GetEmailAddress(requestContext, pushNotification);
                                        if (string.IsNullOrWhiteSpace(email))
                                            // no email for user -> notify admin
                                            email = PluginConfiguration.Instance.AdministratorEmail;
                                        UserAlerter.InformUserOfFailure(email, requestContext, pushNotification, validationResults);
                                    }
                                    catch (Exception e)
                                    {
                                        Logger.Log(string.Format("Error: failed to notify user {0}, reason {1}", pushNotification.AuthenticatedUserName, e.Message));
                                    }//try
                                }//if

                                Logger.LogDenied(failsAt.ReasonMessage);
                                statusCode = failsAt.ReasonCode;
                                statusMessage = failsAt.ReasonMessage;
                                return EventNotificationStatus.ActionDenied;
                            }//if
                        }//using
                    }//if
                }//if
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                throw; // TFS will disable plugin
            }//try

            /*
             * from https://msdn.microsoft.com/en-us/library/Gg214903%28v=vs.120%29.aspx
             * ActionDenied	Action denied; do not notify other subscribers.
             * ActionPermitted	Action permitted; continue with subscriber notification.
             * ActionApproved	Like ActionPermitted, but do not notify other subscribers.
             */
            return EventNotificationStatus.ActionPermitted;
        }
        private bool ShouldMergeItemsIfNecessary(
			TeamFoundationRequestContext requestContext, 
			CheckinNotification checkinNotification)
        {
            if (checkinNotification.Comment != null &&
                checkinNotification.Comment.IndexOf("***NO_PBI***", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                return false;
            }

            return true;
        }
 public RequestContextWrapper(TeamFoundationRequestContext context)
 {
     this.context = context;
 }
示例#35
0
 protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, object notificationEventArgs, int maxLines)
 {
     return(CreateNotifications(requestContext, (T)notificationEventArgs, maxLines));
 }
示例#36
0
        public static string GetCollectionUri(this TeamFoundationRequestContext requestContext)
        {
            TeamFoundationLocationService service = requestContext.GetService <TeamFoundationLocationService>();

            return(service.GetHostLocation(requestContext, service.GetPublicAccessMapping(requestContext, service.CurrentServiceOwner)));
        }
示例#37
0
        internal static void LogRequest(TeamFoundationRequestContext requestContext, PushNotification pushNotification, TfsGitRepository repository)
        {
            if (!PluginConfiguration.Instance.HasLog)
            {
                return;
            }

            var lines = new List <string>();

            lines.Add(string.Format("Request from {0} for {1}"
                                    , requestContext.GetNameToDisplay()
                                    , requestContext.ServiceName
                                    ));
            lines.Add("Summary for " + requestContext.GetSummary());

            lines.Add(string.Format("{6} #{0} on {1} repo {2} at {3} by {5} ({4})"
                                    , pushNotification.PushId
                                    , pushNotification.TeamProjectUri
                                    , pushNotification.RepositoryName
                                    , pushNotification.PushTime
                                    , pushNotification.AuthenticatedUserName
                                    , pushNotification.Pusher
                                    , requestContext.Method.Name
                                    ));

            lines.Add("- Included Commits:");
            foreach (var commitHash in pushNotification.IncludedCommits)
            {
                var commit = repository.TryLookupObject(requestContext, commitHash) as TfsGitCommit;
                lines.Add(string.Format("   Commit {0}: {1} '{2}'"
                                        , commit.ObjectId.DisplayHash()
                                        , commit.GetCommitterName(requestContext)
                                        , commit.GetComment(requestContext)
                                        ));

                foreach (var parentCommit in commit.GetParents(requestContext))
                {
                    lines.Add(string.Format("      Parent {0}: {1} '{2}'"
                                            , parentCommit.ObjectId.DisplayHash()
                                            , parentCommit.GetCommitterName(requestContext)
                                            , parentCommit.GetComment(requestContext)
                                            ));
                }
            }

            lines.Add("- Ref Update Results:");
            foreach (var refUpdate in pushNotification.RefUpdateResults)
            {
                lines.Add(string.Format("   on {0} {1}..{2} is {3} (succeeded: {4}) rejecter '{5}' message '{6}'"
                                        , refUpdate.Name
                                        , refUpdate.NewObjectId.DisplayHash()
                                        , refUpdate.OldObjectId.DisplayHash()
                                        , refUpdate.Status
                                        , refUpdate.Succeeded
                                        , refUpdate.RejectedBy
                                        , refUpdate.CustomMessage
                                        ));
            }//for

            File.AppendAllLines(PluginConfiguration.Instance.LogFile, lines);
        }
示例#38
0
        protected override IEnumerable <INotification> CreateNotifications(TeamFoundationRequestContext requestContext, WorkItemChangedEvent ev, int maxLines)
        {
            var notifications = new List <INotification>();

            var identityService = requestContext.GetService <TeamFoundationIdentityService>();
            var identity        = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.ChangerSid);

            if (ev.CoreFields == null)
            {
                throw new TfsNotificationRelayException("ev.CoreFields is null");
            }
            if (ev.CoreFields.StringFields == null)
            {
                throw new TfsNotificationRelayException("ev.CoreFields.StringFields is null");
            }
            if (ev.CoreFields.IntegerFields == null)
            {
                throw new TfsNotificationRelayException("ev.CoreFields.IntegerFields is null");
            }

            var typeField = ev.CoreFields.StringFields.SingleOrDefault(f => f.ReferenceName == "System.WorkItemType");

            if (typeField == null)
            {
                throw new TfsNotificationRelayException("missing System.WorkItemType");
            }
            string type = typeField.NewValue;

            var idField = ev.CoreFields.IntegerFields.Single(f => f.ReferenceName == "System.Id");

            if (idField == null)
            {
                throw new TfsNotificationRelayException("missing System.Id");
            }
            int id = idField.NewValue;

            var    assignedTo         = ev.CoreFields.StringFields.GetFieldValue("System.AssignedTo", f => f.NewValue);
            string assignedToUserName = null;

            if (!string.IsNullOrEmpty(assignedTo))
            {
                var assignedToIdentity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.DisplayName, assignedTo);
                if (assignedToIdentity != null)
                {
                    assignedToUserName = assignedToIdentity.UniqueName;
                }
            }

            var teamNames = GetUserTeamsByProjectUri(requestContext, ev.ProjectNodeId, identity.Descriptor);

            if (ev.TextFields != null)
            {
                var comment = ev.TextFields.FirstOrDefault(f => f.ReferenceName == "System.History" && !String.IsNullOrEmpty(f.Value));
                if (comment != null)
                {
                    var commentNotification = new WorkItemCommentNotification()
                    {
                        TeamProjectCollection = requestContext.ServiceHost.Name,
                        UniqueName            = identity.UniqueName,
                        DisplayName           = identity.DisplayName,
                        WiUrl              = ev.DisplayUrl,
                        WiType             = type,
                        WiId               = id,
                        WiTitle            = ev.WorkItemTitle,
                        ProjectName        = ev.PortfolioProject,
                        AreaPath           = ev.AreaPath,
                        AssignedTo         = assignedTo,
                        AssignedToUserName = assignedToUserName,
                        CommentHtml        = comment.Value,
                        Comment            = TextHelper.HtmlToText(comment.Value),
                        TeamNames          = teamNames
                    };

                    notifications.Add(commentNotification);
                }
            }

            var changeNotification = new WorkItemChangedNotification()
            {
                TeamProjectCollection = requestContext.ServiceHost.Name,
                IsNew               = ev.ChangeType == ChangeTypes.New,
                UniqueName          = identity.UniqueName,
                DisplayName         = identity.DisplayName,
                WiUrl               = ev.DisplayUrl,
                WiType              = type,
                WiId                = id,
                WiTitle             = ev.WorkItemTitle,
                ProjectName         = ev.PortfolioProject,
                AreaPath            = ev.AreaPath,
                IsStateChanged      = ev.ChangedFields != null && ev.ChangedFields.StringFields != null && ev.ChangedFields.StringFields.Any(f => f.ReferenceName == "System.State"),
                IsAssignmentChanged = ev.ChangedFields != null && ev.ChangedFields.StringFields != null && ev.ChangedFields.StringFields.Any(f => f.ReferenceName == "System.AssignedTo"),
                State               = ev.CoreFields.StringFields.GetFieldValue("System.State", f => f.NewValue),
                AssignedTo          = assignedTo,
                AssignedToUserName  = assignedToUserName,
                CoreFields          = ev.CoreFields,
                ChangedFields       = ev.ChangedFields,
                TeamNames           = teamNames
            };

            notifications.Add(changeNotification);

            return(notifications);
        }
示例#39
0
        protected override void Execute(CodeActivityContext context)
        {
            TeamFoundationRequestContext requestContextCollection = context.GetValue(this.RequestContext);
            string argToAdress   = context.GetValue(this.ToAdress);
            string argSubject    = context.GetValue(this.Subject);
            bool   argIsBodyHtml = context.GetValue(this.IsBodyHtml);
            string argBody       = context.GetValue(this.Body);

            // services on the configuration
            #if UsingOrganizationServiceHost
            TeamFoundationRequestContext requestContextConfiguration = requestContextCollection.ServiceHost.OrganizationServiceHost.CreateServicingContext();
            #else
            TeamFoundationRequestContext requestContextConfiguration = requestContextCollection.ServiceHost.ApplicationServiceHost.CreateServicingContext();
            #endif
            TeamFoundationRegistryService srvRegistryConfiguration = requestContextConfiguration.GetService <TeamFoundationRegistryService>();

            // read the parameters from TFS registry
            var arrRegEntries = srvRegistryConfiguration.ReadEntries(requestContextConfiguration, "/Service/Integration/Settings/*").ToArray();
            var keyvalues     = new List <string>()
            {
                "EmailEnabled",
                "EmailNotificationFromAddress",
                // "SmtpAnonymousAuth",
                "SmtpCertThumbprint",
                "SmtpEnableSsl",
                "SmtpPassword",
                "SmtpPort",
                "SmtpServer",
                "SmtpUser"
            }.Select(name =>
            {
                string path  = "/Service/Integration/Settings/" + name;
                string value = null;
                try
                {
                    // value = srvRegistryConfiguration.ReadEntries(requestContextConfiguration, path).First().Value;
                    value = arrRegEntries.Where(regEntry => regEntry.Name == name).Select(regEntry => regEntry.Value).FirstOrDefault();
                }
                catch (Exception e)
                {
                    this.LogInfo(string.Format("registry value '{0}' not found", path));
                    this.LogInfo(e.Message);
                }
                return(new { key = name, value = value });
            });

            // dispose the request context
            requestContextConfiguration.Dispose();

            foreach (var keyvalue in keyvalues)
            {
                if (keyvalue.value == null)
                {
                    this.LogInfo(string.Format("registry value '{0}' not found", keyvalue.key));
                }
            }

            bool TfsEmailEnabled = bool.Parse(keyvalues.Where(kv => kv.key == "EmailEnabled").First().value);
            if (!TfsEmailEnabled)
            {
                this.LogInfo(string.Format("TFS Email Alter Settings are disabled"));
                return;
            }

            string TfsSmtpServer = keyvalues.Where(kv => kv.key == "SmtpServer").First().value;
            int    TfsSmtpPort   = int.Parse(keyvalues.Where(kv => kv.key == "SmtpPort").First().value);
            string TfsEmailNotificationFromAddress = keyvalues.Where(kv => kv.key == "EmailNotificationFromAddress").First().value;
            string TfsSmtpUser     = keyvalues.Where(kv => kv.key == "SmtpUser").First().value;
            string TfsSmtpPassword = keyvalues.Where(kv => kv.key == "SmtpPassword").First().value;

            this.LogInfo(string.Format("TFS SmptServer: {0}:{1}", TfsSmtpServer, TfsSmtpPort));
            this.LogInfo(string.Format("TFS SmptUser: {0} (from address: {1})", TfsSmtpUser, TfsEmailNotificationFromAddress));

            // setup connection to the SMTP host.
            SmtpClient client = new SmtpClient(TfsSmtpServer, TfsSmtpPort);
            if (string.IsNullOrWhiteSpace(TfsSmtpUser))
            {
                client.UseDefaultCredentials = true;
            }
            else
            {
                client.Credentials = new System.Net.NetworkCredential(TfsSmtpUser, TfsSmtpPassword);
            }

            // Specify the e-mail sender.
            // Create a mailing address that includes a UTF8 character
            // in the display name.
            MailAddress from = new MailAddress(TfsEmailNotificationFromAddress, TfsEmailNotificationFromAddress);
            // Set destinations for the e-mail message.
            MailAddress to = new MailAddress(argToAdress);
            // Specify the message content.
            MailMessage message = new MailMessage(from, to);
            message.Subject         = argSubject;
            message.SubjectEncoding = System.Text.Encoding.UTF8;
            message.Body            = argBody;
            message.BodyEncoding    = System.Text.Encoding.UTF8;
            message.IsBodyHtml      = argIsBodyHtml;

            // send the mail
            client.Send(message);
        }
        protected override IEnumerable <Notifications.INotification> CreateNotifications(TeamFoundationRequestContext requestContext, PullRequestCreatedNotification ev, int maxLines)
        {
            var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>();
            var identityService   = requestContext.GetService <ITeamFoundationIdentityService>();
            var commonService     = requestContext.GetService <ICommonStructureService>();

            var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, ev.Creator.Identifier);

            using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, ev.RepositoryId))
            {
                var pullRequestService = requestContext.GetService <ITeamFoundationGitPullRequestService>();
                TfsGitPullRequest pullRequest;
                if (pullRequestService.TryGetPullRequestDetails(requestContext, repository, ev.PullRequestId, out pullRequest))
                {
                    string repoUri = repository.GetRepositoryUri(requestContext);

                    var notification = new Notifications.PullRequestCreatedNotification()
                    {
                        TeamProjectCollection = requestContext.ServiceHost.Name,
                        UniqueName            = identity.UniqueName,
                        DisplayName           = identity.DisplayName,
                        ProjectName           = commonService.GetProject(requestContext, ev.TeamProjectUri).Name,
                        RepoUri   = repoUri,
                        RepoName  = ev.RepositoryName,
                        PrId      = pullRequest.PullRequestId,
                        PrUrl     = string.Format("{0}/pullrequest/{1}#view=discussion", repoUri, ev.PullRequestId),
                        PrTitle   = pullRequest.Title,
                        TeamNames = GetUserTeamsByProjectUri(requestContext, ev.TeamProjectUri, ev.Creator)
                    };
                    yield return(notification);
                }
                else
                {
                    throw new TfsNotificationRelayException("Unable to get pull request " + ev.PullRequestId);
                }
            }
        }
        protected override Notifications.INotification CreateNotification(TeamFoundationRequestContext requestContext, object eventargs, int maxLines)
        {
            Logger.Log("eventargs: " + JObject.FromObject(eventargs).ToString());

            throw new Tfs2SlackException("DebugHandler");
        }
        private string GetEmailAddress(TeamFoundationRequestContext requestContext, PushNotification pushNotification)
        {
            var collectionUrl = new Uri(requestContext.GetCollectionUri());
            var collection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(collectionUrl);
            var managementService = collection.GetService<IIdentityManagementService>();
            TeamFoundationIdentity teamFoundationIdentity = managementService.ReadIdentity(
                    IdentitySearchFactor.AccountName,
                    pushNotification.AuthenticatedUserName,
                    MembershipQuery.None,
                    ReadIdentityOptions.None);

            return teamFoundationIdentity.GetAttribute("Mail", null);
        }
示例#43
0
        TfsTeamProjectCollection getTeamProjectCollectionFromRequestContext(TeamFoundationRequestContext requestContext)
        {
            //todo: Avoid hardcoding credentials.
            System.Net.ICredentials cred = new System.Net.NetworkCredential("John", "cheese");

            IdentityDescriptor id; requestContext.GetAuthenticatedIdentity(out id);
            //ICredentialsProvider c = requestContext.GetAuthenticatedIdentity

            TeamFoundationLocationService service = requestContext.GetService<TeamFoundationLocationService>();
            Uri selfReferenceUri = service.GetSelfReferenceUri(requestContext, service.GetDefaultAccessMapping(requestContext));
            return new TfsTeamProjectCollection(selfReferenceUri, cred);
        }
        private Policy GetPolicy(TeamFoundationRequestContext requestContext, PushNotification pushNotification)
        {
            // HACK
            string collectionName = requestContext.ServiceHost.VirtualDirectory.Replace("/tfs/", "").Replace("/", "");
            // HACK is this cheap?
            var commonService = requestContext.GetService<CommonStructureService>();
            string projectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name;
            string repositoryName = pushNotification.RepositoryName;

            foreach (var policy in PluginConfiguration.Instance.Policies)
            {
                if (policy.AppliesTo(collectionName, projectName, repositoryName))
                    return policy;
            }//for

            return null;
        }
示例#45
0
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
        {
            properties    = null;
            statusCode    = 0;
            statusMessage = null;

            if (notificationType != NotificationType.DecisionPoint)
            {
                return(EventNotificationStatus.ActionApproved);
            }

            var notification = notificationEventArgs as PullRequestNotification;

            if (notification != null)
            {
                var gitPullRequestService = requestContext.GetService <TeamFoundationGitPullRequestService>();
                var gitrepositoryService  = requestContext.GetService <TeamFoundationGitRepositoryService>();
                var pullRequest           = gitPullRequestService.GetPullRequestDetails(requestContext, notification.PullRequestId);
                var repository            = gitrepositoryService.FindRepositoryById(requestContext, pullRequest.RepositoryId);


                var reviews = pullRequest.Reviewers.ToList();
                reviews.Add(new TfsGitPullRequest.ReviewerWithVote(new Guid(), 4, ReviewerVoteStatus.Rejected));
                gitPullRequestService.UpdatePullRequest(requestContext, repository, pullRequest.PullRequestId, pullRequest.Status, pullRequest.Title, pullRequest.Description, reviews);

                var messageBuilder = new StringBuilder();
                messageBuilder.AppendFormat(DateTime.Now.ToShortTimeString());
                messageBuilder.Append(" : ");

                messageBuilder.AppendFormat(@"PullRequestId = {0}", pullRequest.PullRequestId);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"MergeId = {0}", pullRequest.MergeId);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"PullRequestId = {0}", pullRequest.SourceBranchName);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"SourceBranchName = {0}", pullRequest.TargetBranchName);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"LastMergeCommit = {0}", pullRequest.LastMergeCommit);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"LastMergeSourceCommit = {0}", pullRequest.LastMergeSourceCommit);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"LastMergeTargetCommit = {0}", pullRequest.LastMergeTargetCommit);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"Status = {0}", pullRequest.Status);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"Title = {0}", pullRequest.Title);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"MergeStatus = {0}", pullRequest.MergeStatus);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"CompleteWhenMergedAuthority = {0}", pullRequest.CompleteWhenMergedAuthority);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"Description = {0}", pullRequest.Description);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"Creator = {0}", pullRequest.Creator);
                messageBuilder.AppendLine();

                messageBuilder.AppendFormat(@"CreationDate = {0}", pullRequest.CreationDate);
                messageBuilder.AppendLine();
                messageBuilder.AppendLine("==========================================================");


                File.AppendAllText(@"C:\TMP\NPTV_TEST_LOG.txt", messageBuilder.ToString());
            }

            return(EventNotificationStatus.ActionApproved);
        }
示例#46
0
        protected override INotification CreateNotification(TeamFoundationRequestContext requestContext, PushNotification pushNotification, int maxLines)
        {
            var repositoryService = requestContext.GetService <TeamFoundationGitRepositoryService>();
            var commonService     = requestContext.GetService <CommonStructureService>();
            var commitService     = requestContext.GetService <TeamFoundationGitCommitService>();
            var identityService   = requestContext.GetService <TeamFoundationIdentityService>();

            var identity = identityService.ReadIdentity(requestContext, IdentitySearchFactor.Identifier, pushNotification.Pusher.Identifier);

            using (TfsGitRepository repository = repositoryService.FindRepositoryById(requestContext, pushNotification.RepositoryId))
            {
                var pushRow = new PushRow()
                {
                    UniqueName  = pushNotification.AuthenticatedUserName,
                    DisplayName = identity.DisplayName,
                    RepoName    = pushNotification.RepositoryName,
                    RepoUri     = repository.GetRepositoryUri(requestContext),
                    ProjectName = commonService.GetProject(requestContext, pushNotification.TeamProjectUri).Name,
                    IsForcePush = settings.IdentifyForcePush ? pushNotification.IsForceRequired(requestContext, repository) : false
                };
                var notification = new GitPushNotification(requestContext.ServiceHost.Name, pushRow.ProjectName, pushRow.RepoName);
                notification.Add(pushRow);
                notification.TotalLineCount++;

                var refNames   = new Dictionary <byte[], List <string> >(new ByteArrayComparer());
                var oldCommits = new HashSet <byte[]>(new ByteArrayComparer());
                var unknowns   = new List <RefUpdateResultGroup>();

                // Associate refs (branch, lightweight and annotated tag) with corresponding commit
                var refUpdateResultGroups = pushNotification.RefUpdateResults
                                            .Where(r => r.Succeeded)
                                            .GroupBy(r => r.NewObjectId, (key, items) => new RefUpdateResultGroup(key, items), new ByteArrayComparer());

                foreach (var refUpdateResultGroup in refUpdateResultGroups)
                {
                    byte[] newObjectId = refUpdateResultGroup.NewObjectId;
                    byte[] commitId    = null;

                    if (newObjectId.IsZero())
                    {
                        commitId = newObjectId;
                    }
                    else
                    {
                        TfsGitObject gitObject = repository.LookupObject(requestContext, newObjectId);

                        if (gitObject.ObjectType == TfsGitObjectType.Commit)
                        {
                            commitId = newObjectId;
                        }
                        else if (gitObject.ObjectType == TfsGitObjectType.Tag)
                        {
                            var tag    = (TfsGitTag)gitObject;
                            var commit = tag.TryResolveToCommit(requestContext);
                            if (commit != null)
                            {
                                commitId = commit.ObjectId;
                            }
                        }
                    }

                    if (commitId != null)
                    {
                        List <string> names;
                        if (!refNames.TryGetValue(commitId, out names))
                        {
                            names = new List <string>();
                            refNames.Add(commitId, names);
                        }
                        names.AddRange(RefsToStrings(refUpdateResultGroup.RefUpdateResults));

                        if (commitId.IsZero() || !pushNotification.IncludedCommits.Any(r => r.SequenceEqual(commitId)))
                        {
                            oldCommits.Add(commitId);
                        }
                    }
                    else
                    {
                        unknowns.Add(refUpdateResultGroup);
                    }
                }

                notification.TotalLineCount += pushNotification.IncludedCommits.Count() + oldCommits.Count + unknowns.Count;

                // Add new commits with refs
                foreach (byte[] commitId in pushNotification.IncludedCommits.TakeWhile(c => notification.Count < maxLines))
                {
                    TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId);
                    notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.Commit, pushNotification, refNames));
                }

                // Add updated refs to old commits
                foreach (byte[] commitId in oldCommits.TakeWhile(c => notification.Count < maxLines))
                {
                    if (commitId.IsZero())
                    {
                        notification.Add(new DeleteRow()
                        {
                            RefNames = refNames[commitId]
                        });
                    }
                    else
                    {
                        TfsGitCommit gitCommit = (TfsGitCommit)repository.LookupObject(requestContext, commitId);
                        notification.Add(CreateCommitRow(requestContext, commitService, gitCommit, CommitRowType.RefUpdate, pushNotification, refNames));
                    }
                }

                // Add "unknown" refs
                foreach (var refUpdateResultGroup in unknowns.TakeWhile(c => notification.Count < maxLines))
                {
                    byte[]       newObjectId = refUpdateResultGroup.NewObjectId;
                    TfsGitObject gitObject   = repository.LookupObject(requestContext, newObjectId);
                    notification.Add(new RefUpdateRow()
                    {
                        NewObjectId = newObjectId,
                        ObjectType  = gitObject.ObjectType,
                        RefNames    = RefsToStrings(refUpdateResultGroup.RefUpdateResults)
                    });
                }

                return(notification);
            }
        }
        /// <summary>
        /// This is the one where all the magic starts.  Main() so to speak.  I will load the settings, connect to tfs and apply the aggregation rules.
        /// </summary>
        public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs,
                                                    out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
        {
            statusCode = 0;
            properties = null;
            statusMessage = String.Empty;
            int currentAggregationId = 0;
            int workItemId = 0;
            string currentAggregationName = string.Empty;

            try
            {
                if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
                {
                    // Change this object to be a type we can easily get into
                    WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent;
                    // Connect to the setting file and load the location of the TFS server
                    string tfsUri = TFSAggregatorSettings.TFSUri;
                    // Connect to TFS so we are ready to get and send data.
                    Store store = new Store(tfsUri);
                    // Get the id of the work item that was just changed by the user.
                    workItemId = ev.CoreFields.IntegerFields[0].NewValue;
                    // Download the work item so we can update it (if needed)
                    WorkItem eventWorkItem = store.Access.GetWorkItem(workItemId);
                    string workItemTypeName = eventWorkItem.Type.Name;
                    List<WorkItem> workItemsToSave = new List<WorkItem>();

                    if (TFSAggregatorSettings.LoggingIsEnabled)
                    {
                        MiscHelpers.LogMessage(String.Format("Change detected to {0} [{1}]", workItemTypeName, workItemId));
                        MiscHelpers.LogMessage(String.Format("{0}Processing {1} AggregationItems", "  ", TFSAggregatorSettings.ConfigAggregatorItems.Count.ToString()));
                    }

                    // Apply the aggregation rules to the work item
                    foreach (ConfigAggregatorItem configAggregatorItem in TFSAggregatorSettings.ConfigAggregatorItems)
                    {
                        IEnumerable<WorkItem> sourceWorkItems = null;
                        WorkItem targetWorkItem = null;
                        currentAggregationName = configAggregatorItem.Name;

                        // Check to make sure that the rule applies to the work item type we have
                        if (eventWorkItem.Type.Name == configAggregatorItem.WorkItemType)
                        {
                            if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}[Entry {2}] Aggregation '{3}' applies to {1} work items", "    ", workItemTypeName, currentAggregationId, currentAggregationName));

                            // Use the link type to see what the work item we are updating is
                            if (configAggregatorItem.LinkType == ConfigLinkTypeEnum.Self)
                            {
                                // We are updating the same workitem that was sent in the event.
                                sourceWorkItems = new List<WorkItem> {eventWorkItem};
                                targetWorkItem = eventWorkItem;

                                if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}{0}Aggregation applies to SELF. ({1} {2})", "  ", workItemTypeName, workItemId));

                                // Make sure that all conditions are true before we do the aggregation
                                // If any fail then we don't do this aggregation.
                                if (!configAggregatorItem.Conditions.AreAllConditionsMet(targetWorkItem))
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for aggregation are not met.", "    "));
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for aggregation are met.", "    "));

                            }
                                // We are aggregating to the parent
                            else if (configAggregatorItem.LinkType == ConfigLinkTypeEnum.Parent)
                            {
                                bool parentLevelFound = true;

                                // Go up the tree till we find the level of parent that we are looking for.
                                WorkItem iterateToParent = eventWorkItem;
                                for (int i = 0; i < configAggregatorItem.LinkLevel; i++)
                                {

                                    // Load the parent from the saved list (if we have it in there) or just load it from the store.
                                    WorkItem nullCheck = iterateToParent.GetParentFromListOrStore(workItemsToSave, store);
                                    //
                                    if (nullCheck != null)
                                    {
                                        iterateToParent = nullCheck;
                                    }
                                    else
                                        parentLevelFound = false;

                                }
                                // If we did not find the correct parent then we are done with this aggregation.
                                if (!parentLevelFound)
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}{0}Couldn't find a PARENT {2} {4} up from {3} [{1}]. This aggregation will not continue.", "  ", workItemId, configAggregatorItem.LinkLevel, workItemTypeName, configAggregatorItem.LinkLevel > 1 ? "levels" : "level"));
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}{0}Found {1} [{2}] {3} {4} up from {5} [{6}].  Aggregation continues.", "  ", iterateToParent.Type.Name, iterateToParent.Id, configAggregatorItem.LinkLevel, configAggregatorItem.LinkLevel > 1 ? "levels" : "level", workItemTypeName, workItemId));

                                targetWorkItem = iterateToParent;

                                // Make sure that all conditions are true before we do the aggregation
                                // If any fail then we don't do this aggregation.
                                if (!configAggregatorItem.Conditions.AreAllConditionsMet(targetWorkItem))
                                {
                                    if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for parent aggregation are not met", "    "));
                                    currentAggregationId++;
                                    continue;
                                }

                                if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}{0}All conditions for parent aggregation are met", "    "));

                                // Get the children down how ever many link levels were specified.
                                List<WorkItem> iterateFromParents = new List<WorkItem> {targetWorkItem};
                                for (int i = 0; i < configAggregatorItem.LinkLevel; i++)
                                {
                                    List<WorkItem> thisLevelOfKids = new List<WorkItem>();
                                    // Iterate all the parents to find the children of current set of parents
                                    foreach (WorkItem iterateFromParent in iterateFromParents)
                                    {
                                        thisLevelOfKids.AddRange(iterateFromParent.GetChildrenFromListOrStore(workItemsToSave, store));
                                    }

                                    iterateFromParents = thisLevelOfKids;
                                }

                                // remove the kids that are not the right type that we are working with
                                ConfigAggregatorItem configAggregatorItemClosure = configAggregatorItem;
                                iterateFromParents.RemoveAll(x => x.Type.Name != configAggregatorItemClosure.WorkItemType);

                                sourceWorkItems = iterateFromParents;
                            }

                            // Do the actual aggregation now
                            bool changeMade = Aggregator.Aggregate(sourceWorkItems, targetWorkItem, configAggregatorItem);

                            // If we made a change then add this work item to the list of items to save.
                            if (changeMade)
                            {
                                // Add the target work item to the list of work items to save.
                                workItemsToSave.AddIfUnique(targetWorkItem);
                            }
                        }
                        else
                        {
                            if (TFSAggregatorSettings.LoggingIsEnabled) MiscHelpers.LogMessage(String.Format("{0}[Entry {2}] Aggregation '{3}' does not apply to {1} work items", "    ", workItemTypeName, currentAggregationId, currentAggregationName));
                        }

                        currentAggregationId++;
                    }

                    // Save any changes to the target work items.
                    workItemsToSave.ForEach(x =>
                    {
                        bool isValid = x.IsValid();

                        if (TFSAggregatorSettings.LoggingIsEnabled)
                        {
                            MiscHelpers.LogMessage(String.Format("{0}{0}{0}{1} [{2}] {3} valid to save. {4}",
                                                                "    ",
                                                                x.Type.Name,
                                                                x.Id,
                                                                isValid ? "IS" : "IS NOT",
                                                                String.Format("\n{0}{0}{0}{0}Invalid fields: {1}", "    ", MiscHelpers.GetInvalidWorkItemFieldsList(x).ToString())));
                        }

                        if (isValid)
                        {
                            x.PartialOpen();
                            x.Save();
                        }
                    });

                    MiscHelpers.AddRunSeparatorToLog();
                }

            }
            catch (Exception e)
            {
                string message = String.Format("Exception encountered processing Work Item [{2}]: {0} \nStack Trace:{1}", e.Message, e.StackTrace, workItemId);
                if (e.InnerException != null)
                {
                    message += String.Format("\n    Inner Exception: {0} \nStack Trace:{1}", e.InnerException.Message, e.InnerException.StackTrace);
                }
                MiscHelpers.LogMessage(message, true);
            }

            return EventNotificationStatus.ActionPermitted;
        }
 public static Uri GetTFSUri(TeamFoundationRequestContext requestContext)
 {
     return new Uri(requestContext.GetService<TeamFoundationLocationService>().GetServerAccessMapping(requestContext).AccessPoint.Replace("localhost", Environment.MachineName) + "/" + requestContext.ServiceHost.Name);
 }
 public RequestContextWrapper(TeamFoundationRequestContext context)
 {
     this.context = context;
 }
 protected abstract INotification CreateNotification(TeamFoundationRequestContext requestContext, T notificationEventArgs, int maxLines);