コード例 #1
0
        // Get the Uri for the TR before disconnected assuming disconnect was done in
        // previous save. Preconditions should be checked by caller.
        static public Uri getDisconnectedTRLink(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            WorkItemChangedEvent notification)
        {
            // Apparently we need to check on second last revision to get the correct
            // value for the previous value. This does not show in UI, but is clear when
            // debugging. So check we have > 2 revisions, and then compare.

            if (workItem.Revision < 3)
            {
                return(null);
            }

            Revision lastRev   = workItem.Revisions[workItem.Revision - 2];
            String   oldTrLink = lastRev.Fields[TFSMapper.ERICSSON_DEFECT_LINK_FIELD].Value.ToString();

            if (oldTrLink == null || oldTrLink.Length == 0)
            {
                return(null);
            }

            HandlerSettings.LogMessage(
                String.Format(
                    "Disconnected TR '{0}' from WorkItem with id {1}.",
                    oldTrLink, "" + workItem.Id), HandlerSettings.LoggingLevel.INFO);

            return(new Uri(HandlerSettings.GetUriForTR(oldTrLink)));
        }
コード例 #2
0
        // =============================================================
        // Ignore all changes done by ourselves - i.e. the functional user used to handle save events.
        // Note that IF functional user would be logged in as regular user, events will not be handled.

        private bool ignoreSaveEvent(WorkItemChangedEvent ev)
        {
            bool ignore = HandlerSettings.IgnoreEventByUser(
                getStore().TeamProjectCollection,
                ev.ChangerTeamFoundationId);

            return(ignore);
        }
コード例 #3
0
        // Check if we should disconnect a TR. Condition is that an external save
        // (by TFSProviderUser) has caused the TR Link field to transition from a
        // value to an empty value, This indicates disconnect.
        private EventType CheckDisconnect(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem wi,
            WorkItemChangedEvent notification,
            String user)
        {
            if (!user.Equals(HandlerSettings.TFSProviderUser, StringComparison.OrdinalIgnoreCase))
            {
                // Only disconnect based on incoming external event.
                // Disconnect by user is handled by separate code
                return(EventType.Ignore);
            }

            if (notification.ChangeType == ChangeTypes.New)
            {
                // Disconnect can only happen for a changed WI, not a new.
                return(EventType.Ignore);
            }

            // Get the current field - Disconnect case assume this is ""
            if (!wi.Fields.Contains(TFSMapper.ERICSSON_DEFECT_LINK_FIELD))
            {
                // Odd case where the mandatory field is missing
                return(EventType.Ignore);
            }

            Object trLinkValue = wi.Fields[TFSMapper.ERICSSON_DEFECT_LINK_FIELD].Value;

            if (trLinkValue == null)
            {
                return(EventType.Ignore);
            }
            String trLink = trLinkValue.ToString();

            if (trLink != null && trLink.Length > 0)
            {
                return(EventType.Ignore);
            }

            TextField[] changedTextFields = notification.TextFields;
            if (changedTextFields == null || changedTextFields.Length == 0)
            {
                // The TR Link field is a Text field - if no changes, ignore.
                return(EventType.Ignore);
            }

            // Check so also the TR Link field is changed
            for (int i = 0; i < changedTextFields.Length; i++)
            {
                String name = changedTextFields[i].ReferenceName;
                if (name.Equals(TFSMapper.ERICSSON_DEFECT_LINK_FIELD))
                {
                    return(EventType.Disconnect);
                }
            }

            return(EventType.Ignore);
        }
コード例 #4
0
        // UC 6: Create a TR based on a Bug.
        // Return if the bug is updated or not.
        private void createTR(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            WorkItemChangedEvent notification,
            String user,
            ref Status status)
        {
            // Create the ECR
            callCreateTR(ECRMapper.mapFromWorkitem(workItem, null, ECRMapper.ACTION_CREATE), user, ref status);
            if (!status.OK)
            {
                return;
            }

            // UC 3 (one case): Update all changed attributes before handling any state change

            // Note: If adding an entry in History on create this should propagate to Progress Info, but
            // this caused Bug to appear dirty after Save, see issue 79. Given almost all fields are used on
            // create, it does not make sense to make extra update as below. TBD if we should re-add in a
            // changed form.

            //EnterpriseChangeRequest updatedEcr = ECRMapper.mapFromUpdatedWorkitem(workItem, status.TRAbout, notification);
            //if (updatedEcr != null)
            //{
            //    // Note: Failure to update will be Warning not Error, so status still OK.
            //    callUpdateTR(updatedEcr, user, null, ref status);
            //}

            // Set the ECR in state Registered
            EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, status.TRAbout, ECRMapper.ACTION_REGISTER_ROUTE);

            callUpdateTR(ecr, user, ECRMapper.TR_STATE_REGISTERED_S, ref status);
            if (!status.OK)
            {
                return;
            }

            // Set the ECR in state Assigned if we have a defined owner
            ecr = ECRMapper.mapFromWorkitem(workItem, status.TRAbout, ECRMapper.ACTION_ASSIGN);
            if (ecr.GetOwner() != null && ecr.GetOwner().Length > 0)
            {
                callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref status);
                if (!status.OK)
                {
                    return;
                }
            }

            if (status.OK)
            {
                HandlerSettings.LogMessage(
                    String.Format("Created TR based on workitem named: {0}", workItem.Title),
                    HandlerSettings.LoggingLevel.INFO);
            }
        }
コード例 #5
0
        // For call to create TR we need Ericsson user id (also domain?) - seems like we have what we want here.
        // TDOD: Try and make sure we are getting the correct attribute.
        // See http://stackoverflow.com/questions/19911368/using-the-tfs-2012-api-how-do-i-get-the-email-address-of-a-user
        static public String GetSignumForChangeNotification(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            WorkItemChangedEvent notification)
        {
            TfsTeamProjectCollection tpc = workItem.Store.TeamProjectCollection;
            String userId = notification.ChangerTeamFoundationId;

            IIdentityManagementService mgmntService = tpc.GetService <IIdentityManagementService>();

            Guid[] ids = new Guid[1];
            ids[0] = new Guid(notification.ChangerTeamFoundationId);

            TeamFoundationIdentity[] members = mgmntService.ReadIdentities(ids, MembershipQuery.Direct);

            return(GetUserFromSignum(members[0].UniqueName));
        }
コード例 #6
0
        // Update the changed fields that are mapped. Return if the bug is updated or not.
        private void updateTRFields(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            WorkItemChangedEvent notification,
            String user,
            Uri about,
            ref Status status)
        {
            // UC 3 (one case): Update all changed attributes before handling any state change.
            EnterpriseChangeRequest updatedEcr = ECRMapper.mapFromUpdatedWorkitem(workItem, about, notification);

            if (updatedEcr != null)
            {
                // Note: Failure to update will be Warning not Error, so status still OK.
                callUpdateTR(updatedEcr, user, null, ref status);
            }
        }
コード例 #7
0
        // Return if the workitem is updated (saved) by the handling code.
        public void handleEvent(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            String user,
            WorkItemChangedEvent notification)
        {
            Status status = new Status();

            // If the user is the OSLC Provider functional user we will only update status
            // message if so needed. This as changes from the OSLC Provider originates from
            // external source = currently: MHWeb. Need revisit to allow multiple clients.
            String aboutStr = AttributesMapper.GetTfsValueForEcrKey(TFSMapper.ECM_ABOUT, workItem);

            if (!user.Equals(HandlerSettings.TFSProviderUser, StringComparison.OrdinalIgnoreCase))
            {
                if (aboutStr.Length == 0)
                {
                    // We do not have a linked TR, we need to create
                    createTR(workItem, notification, user, ref status);
                }
                else
                {
                    Uri    about        = new Uri(aboutStr);
                    Status statusAssign = null;

                    EnterpriseChangeRequest ecr        = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_ASSIGN);
                    TeamFoundationIdentity  assignedTo = HandlerSettings.GetSignumForAssignedTo(workItem);
                    if (user != null && assignedTo != null && !user.Equals(HandlerSettings.GetUserFromSignum(assignedTo.UniqueName), StringComparison.OrdinalIgnoreCase))
                    {
                        statusAssign = new Status();
                        ecr.SetOwner(user);
                        callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref statusAssign);
                    }

                    // We have a TR linked which might need to be updated
                    updateTR(workItem, notification, user, about, ref status);

                    if (statusAssign != null && statusAssign.OK)
                    {
                        ecr.SetOwner(HandlerSettings.GetUserFromSignum(assignedTo.UniqueName));
                        callUpdateTR(ecr, user, ECRMapper.TR_STATE_ASSIGNED_S, ref statusAssign);
                    }
                }
            }

            // Handle update of Bug
            ECRMapper.updateBug(status, user, workItem);
        }
コード例 #8
0
        public static XmlNode SerializeXml(WorkItemChangedEvent workItemChangedEvent)
        {
            if (null == workItemChangedEvent)
            {
                return(null);
            }

            var xmlSerializer = new XmlSerializer(typeof(WorkItemChangedEvent));
            var memoryStream  = new MemoryStream();

            xmlSerializer.Serialize(memoryStream, workItemChangedEvent);

            memoryStream.Position = 0;
            var xmlDocument = new XmlDocument();

            xmlDocument.Load(memoryStream);
            memoryStream.Close();

            return(xmlDocument.ChildNodes[1]);
        }
コード例 #9
0
        public TeamFoundationJobExecutionResult Run(
            TeamFoundationRequestContext requestContext,
            TeamFoundationJobDefinition jobDefinition,
            DateTime queueTime,
            out string resultMessage)
        {
            resultMessage = string.Empty;
            try
            {
                string strConfigFile = this.workflowRunner.ExecutionPath.FullName + ".config";
                XmlConfigurator.Configure(new Uri(strConfigFile));
                AppendSuffixToLoggingPath("_JobAgent");

                this.LogInfo(string.Format("Enter Job for WorkitemChangedEvent"));

                lock (JobLock)
                {
                    XmlNode xmlData = jobDefinition.Data;
                    WorkItemChangedEvent workItemChangedEvent = WorkItemChangedEventSerializer.DeserializeXml(xmlData);
                    this.workflowRunner.ProcessEvent(requestContext, workItemChangedEvent);
                }
            }
            catch (RequestCanceledException e)
            {
                this.LogError(string.Format("Workflow cancel: "), e);
                return(TeamFoundationJobExecutionResult.Stopped);
            }
            catch (Exception e)
            {
                this.LogError(string.Format("Workflow error: "), e);
                resultMessage = e.ToString();
                return(TeamFoundationJobExecutionResult.Failed);
            }

            this.LogInfo(string.Format("Leave Job for WorkitemChangedEvent"));

            return(TeamFoundationJobExecutionResult.Succeeded);
        }
コード例 #10
0
        // =========================================================
        // Handle the WorkItemChangedEvent event

        // Disconnect TR if conditions are matching. Return if workitem has been saved.
        public void handleDisconnectEvent(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            String user,
            WorkItemChangedEvent notification)
        {
            Uri about = ECRMapper.getDisconnectedTRLink(workItem, notification);

            if (about == null)
            {
                return;
            }
            EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(
                workItem, about, ECRMapper.ACTION_DISCONNECT);
            Status status = new Status();

            callUpdateTR(ecr, user, null, ref status);
            if (!status.OK)
            {
                HandlerSettings.LogMessage(
                    "Failed to disconnect TR from Bug.",
                    HandlerSettings.LoggingLevel.WARN);
            }
        }
コード例 #11
0
        /// <summary>
        /// Main factory method that determines the workitem type 
        /// </summary>
        /// <param name="_wice">
        /// Workitem Change Event object
        /// </param>
        /// <returns>
        /// Correct child object for workitem changed
        /// </returns>
        public IHarleysvilleWorkItemAlerts GetWorkItem(WorkItemChangedEvent _wice, TFSIdentity _tfsId)
        {
            IHarleysvilleWorkItemAlerts _Ihar = null;

            foreach (StringField _sf in _wice.CoreFields.StringFields)
            {
                if (_sf.Name.Equals("Work Item Type", StringComparison.CurrentCultureIgnoreCase))
                {
                    switch (_sf.NewValue)
                    {
                        case "Deployment Backlog Item":
                            _Ihar = new HarleysvilleDBIAlerts(_wice, _tfsId);
                            break;
                        case "Build Backlong Item":
                            _Ihar = new HarelysvilleWorkItemAlerts();
                            break;
                        case "Sprint Backlog Item":
                            _Ihar = new HarelysvilleWorkItemAlerts();
                            break;
                        case "Release Backlog Item":
                            _Ihar = new HarelysvilleWorkItemAlerts();
                            break;
                        case "Product Backlog Item":
                            _Ihar = new HarelysvilleWorkItemAlerts();
                            break;
                        case "Label Backlog Item":
                            _Ihar = new HarleysvilleLBIAlerts(_wice, _tfsId);
                            break;
                        default :
                            _Ihar = new HarelysvilleWorkItemAlerts();
                            break;
                    }
                }
            }

            return _Ihar;
        }
コード例 #12
0
        private IdentityDescriptor GetIdentityToImpersonate(TeamFoundationRequestContext requestContext, WorkItemChangedEvent workItemChangedEvent)
        {
            Uri server = this.GetCollectionUriFromContext(requestContext);

            var configurationServer = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(server);

            // TODO: Find a way to read the identity from the server object model instead.
            IIdentityManagementService identityManagementService =
            configurationServer.GetService<IIdentityManagementService>();

            TeamFoundationIdentity identity =
                identityManagementService.ReadIdentities(
                    new Guid[] { new Guid(workItemChangedEvent.ChangerTeamFoundationId) },
                    MembershipQuery.None).FirstOrDefault();

            return identity?.Descriptor;
        }
コード例 #13
0
 public void SetWorkItemHelper(WorkItemChangedEvent wice, TFWI tfs)
 {
     _wice = wice;
     SetWorkItemHelper();
     _tfs = tfs;
     _wiFields = _tfs.GetWorkItemFields();
     _wiState = _wiFields["State"];
 }
コード例 #14
0
 public void SetWorkItemHelper(WorkItemChangedEvent wice, string tfsUrl)
 {
     _wice = wice;
     SetWorkItemHelper();
     _tfs = new TFWI(tfsUrl, _wiNumber);
     _wiFields = _tfs.GetWorkItemFields();
     _wiState = _wiFields["State"];
 }
コード例 #15
0
 private void Catcher(Exception ex, WorkItemChangedEvent _wice)
 {
     WriteErrorLog("ERROR: " + ex.ToString() + "\n" + _wice.DisplayUrl);
 }
コード例 #16
0
    private void Catcher(Exception ex, IHarleysvilleWorkItemAlerts _Iha, WorkItemChangedEvent _wice)
    {
        //WriteLog(ex.ToString());
        StringBuilder _sb = new StringBuilder();

        _sb.AppendLine(ex.ToString())
            .AppendLine()
            .AppendLine("Below is URL to Work item: ")
            .AppendLine(_wice.DisplayUrl);

        _Iha.DebugMailer(ConfigurationManager.AppSettings.Get("DebugEmailSubject"), _sb.ToString());

        WriteErrorLog(_sb.ToString());

        if (ConfigurationManager.AppSettings.Get("DebugMode").Equals("on", StringComparison.CurrentCultureIgnoreCase))
        {
            WriteLog(_sb.ToString());
        }
    }
コード例 #17
0
        // =======================================================================
        // Mapping from workItem to ECR

        // Return the Bug and TR state change if part of update
        public static void getStatusChange(WorkItemChangedEvent notification,
                                           Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
                                           out String oldState,
                                           out String newState,
                                           out String action)
        {
            newState = null;
            oldState = null;
            action   = null;

            // If the Bug and TR are in different states, block update from Bug to TR.
            if (ECRMapper.IsSyncError(workItem))
            {
                action = ACTION_IGNORE;
                return;
            }

            bool changedAssignedTo = false;

            // If Bug marked as Duplicate, the only activity to be propagated to TR is Unduplicate.
            String substate           = workItem.Fields[TFSMapper.TFS_SUBSTATE].Value.ToString();
            bool   isDuplicate        = substate.Equals(TFSMapper.TFS_SUBSTATE_DUPLICATE);
            bool   isDuplicateChanged = false;

            if (notification.ChangedFields == null || notification.ChangedFields.StringFields == null)
            {
                // No fields of interest are changed
                return;
            }

            StringField[] changedFields = notification.ChangedFields.StringFields;
            for (int i = 0; i < changedFields.Length; i++)
            {
                String name = changedFields[i].ReferenceName;
                if (name.Equals(TFSMapper.TFS_STATE, StringComparison.OrdinalIgnoreCase))
                {
                    oldState = changedFields[i].OldValue;
                    newState = changedFields[i].NewValue;
                }
                else if (name.Equals(TFSMapper.TFS_OWNER, StringComparison.OrdinalIgnoreCase))
                {
                    changedAssignedTo = true;
                }

                // If TFS_SUBSTATE is changed to/from Duplicate the TR should be set to
                // corresponding state. If marked as Duplicate, the only activity that
                // should be propagated to TR is Unduplicate.
                else if (name.Equals(TFSMapper.TFS_SUBSTATE))
                {
                    if (changedFields[i].NewValue.Equals(TFSMapper.TFS_SUBSTATE_DUPLICATE) ||
                        changedFields[i].OldValue.Equals(TFSMapper.TFS_SUBSTATE_DUPLICATE))
                    {
                        isDuplicateChanged = true;
                    }
                }

                // If the release is changed, we need to update the TR product
                // Note: In case we also set to Duplicate, we will disregard product change
                else if (name.Equals(TFSMapper.TFS_FAULTY_PRODUCT))
                {
                    action = ACTION_CHANGE_PRODUCT;
                }
            }

            if (isDuplicateChanged)
            {
                // If the Duplicate flag is changed we need to act on this. This is a substate flag, so
                // it can happen also during a state transition.
                action = isDuplicate ? ACTION_DUPLICATE : ACTION_UNDUPLICATE;
                return;
            }
            else if (isDuplicate)
            {
                // If Bug is duplicate and there is no change for this state, we should send no
                // updates to TR until unduplicated.
                action = ACTION_IGNORE;
                return;
            }

            // If we have a changed of "Assigned To" this will only be possible to update in specific
            // TR states. So if Assigned To changed at same time as state - likely need to prevent.
            if (changedAssignedTo)
            {
                if (newState == null || oldState == null)
                {
                    // No state change for Bug, but for TR
                    oldState = BUG_STATE_ACTIVE;
                    newState = BUG_STATE_ACTIVE;
                }
                else
                {
                    HandlerSettings.LogMessage(
                        String.Format(
                            "The 'Assigned To' change can not be done for TR: {0} at same time as state change",
                            workItem.Title),
                        HandlerSettings.LoggingLevel.WARN);
                }
            }
        }
コード例 #18
0
        // Return an EnterpriseChangeRequest with mapped values for the update
        public static EnterpriseChangeRequest mapFromUpdatedWorkitem(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            Uri about,
            WorkItemChangedEvent notification)
        {
            EnterpriseChangeRequest newEcr = new EnterpriseChangeRequest();

            newEcr.SetAbout(about);

            // The notification contain all changed fields. To understand what to
            // propagate to the client, we need to check which ecm fields that are
            // affected by the changes and are configured for notifyChange

            int noOfMappedChanged = 0;

            if (notification.ChangedFields != null)
            {
                // Most fields are String fields
                StringField[] changedStrFields = notification.ChangedFields.StringFields;
                if (changedStrFields != null)
                {
                    for (int i = 0; i < changedStrFields.Length; i++)
                    {
                        String fieldName = changedStrFields[i].ReferenceName;
                        noOfMappedChanged += mapFromUpdated(workItem, newEcr, fieldName);
                    }
                }

                // For example Priority is an Integer field
                IntegerField[] changedIntFields = notification.ChangedFields.IntegerFields;
                if (changedIntFields != null)
                {
                    for (int i = 0; i < changedIntFields.Length; i++)
                    {
                        String fieldName = changedIntFields[i].ReferenceName;
                        noOfMappedChanged += mapFromUpdated(workItem, newEcr, fieldName);
                    }
                }
            }

            // For example the Description is a Text field
            TextField[] changedTextFields = notification.TextFields;
            if (changedTextFields != null)
            {
                for (int i = 0; i < changedTextFields.Length; i++)
                {
                    String fieldName = changedTextFields[i].ReferenceName;
                    noOfMappedChanged += mapFromUpdated(workItem, newEcr, fieldName);
                }
            }

            // To find a change in the Comment/History one need to look at revision - 1.
            noOfMappedChanged += mapFromUpdated(workItem, newEcr, TFSMapper.TFS_HISTORY);

            // Need to send list of attachments in all cases when we have another update. So if we already have
            // an update (noOfMappedChanged > 0), send - otherwise, check if changed then send.
            if ((noOfMappedChanged > 0 || TFSMapper.getInstance().hasLinksChanged(workItem)))
            {
                noOfMappedChanged += mapFromUpdated(workItem, newEcr, TFSMapper.ERICSSON_DEFECT_HYPERLINK);
            }

            if (noOfMappedChanged > 0)
            {
                // More than 1 field that was mapped changed
                return(newEcr);
            }
            else
            {
                // No field of interest was changed
                HandlerSettings.LogMessage(
                    String.Format("No mapped fields was updated for: {0}", workItem.Title),
                    HandlerSettings.LoggingLevel.INFO);
                return(null);
            }
        }
コード例 #19
0
 int getWorkItemID(WorkItemChangedEvent ev)
 {
     try {
         IntegerField idField =  ev.CoreFields.IntegerFields.Where<IntegerField>(field => field.Name.Equals("ID")).FirstOrDefault<IntegerField>();
         return idField.NewValue;
     }
     catch (Exception) {
         return 0;
     }
 }
コード例 #20
0
        private IdentityDescriptor GetIdentityToImpersonate(TeamFoundationRequestContext requestContext, WorkItemChangedEvent workItemChangedEvent)
        {
            Uri server = this.GetCollectionUriFromContext(requestContext);

            var configurationServer = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(server);

            // TODO: Find a way to read the identity from the server object model instead.
            IIdentityManagementService identityManagementService =
                configurationServer.GetService <IIdentityManagementService>();

            TeamFoundationIdentity identity =
                identityManagementService.ReadIdentities(
                    new Guid[] { new Guid(workItemChangedEvent.ChangerTeamFoundationId) },
                    MembershipQuery.None).FirstOrDefault();

            return(identity?.Descriptor);
        }
コード例 #21
0
 public BBIHelper(WorkItemChangedEvent _wice, string tfsUrl, int _bbiNum)
 {
     SetWorkItemHelper(_wice, tfsUrl, _bbiNum);
 }
コード例 #22
0
 public NotificationWrapper(NotificationType notification, WorkItemChangedEvent eventArgs)
 {
     this.notification = notification;
     this.eventArgs    = eventArgs;
 }
コード例 #23
0
        // Update the connected TR.
        private void updateTR(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem workItem,
            WorkItemChangedEvent notification,
            String user,
            Uri about,
            ref Status status)
        {
            String oldState, newState, action;

            ECRMapper.getStatusChange(notification, workItem, out oldState, out newState, out action);

            if (action != null)
            {
                if (action.Equals(ECRMapper.ACTION_IGNORE))
                {
                    // Ignore all changes
                    return;
                }

                if (action.Equals(ECRMapper.ACTION_DUPLICATE))
                {
                    // UC 9.4: Duplicate - Find Bug with duplicate id, get attached TR and send action duplicate

                    // Update needs to be done before setting the Bug as Duplicate as the TR can't change after.
                    updateTRFields(workItem, notification, user, about, ref status);

                    EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_DUPLICATE);

                    if (ecr.GetPrimaryTR() == null || ecr.GetPrimaryTR().Length == 0)
                    {
                        // Failed to find a Bug with a connected TR. Log error and return.
                        String msg = String.Format(
                            "Failed to find duplicate to Bug: {0}, or duplicate Bug had not TR Link set",
                            workItem.Title);
                        HandlerSettings.LogMessage(msg, HandlerSettings.LoggingLevel.ERROR);
                        status.ErrorMessage = msg;
                        return;
                    }

                    callUpdateTR(ecr, user, null, ref status);
                    if (!status.OK)
                    {
                        // Log issue, but continue if e.g. a state change
                        HandlerSettings.LogMessage(
                            String.Format("Failed to set TR as duplicate based on Bug: {0}", workItem.Title),
                            HandlerSettings.LoggingLevel.WARN);
                    }

                    // After setting Bug/TR as Duplicated, no futher changes should be propagated.
                    return;
                }

                if (action.Equals(ECRMapper.ACTION_UNDUPLICATE))
                {
                    // UC 9.4: Unduplicate - Move TR back to Registered by sending action unduplicate
                    EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_UNDUPLICATE);
                    callUpdateTR(ecr, user, null, ref status);
                    if (!status.OK)
                    {
                        // Log issue, but continue if e.g. a state change
                        HandlerSettings.LogMessage(
                            String.Format("Failed to unduplicate TR based on Bug ", workItem.Title),
                            HandlerSettings.LoggingLevel.WARN);
                    }

                    // Update needs to be done after "Unduplicating" the Bug as the TR can't change before.
                    updateTRFields(workItem, notification, user, about, ref status);

                    // Return before handling a possible state change as states can be out of sync
                    // (normal case) when Bug has been Duplicate. Bug then Resolved / Closed, and
                    // TR in an Active state. User needs to set TR state to Active.
                    return;
                }

                else if (action.Equals(ECRMapper.ACTION_CHANGE_PRODUCT))
                {
                    // UC 10.2: Update of the release - propagate info to TR
                    EnterpriseChangeRequest ecr = ECRMapper.mapFromWorkitem(workItem, about, ECRMapper.ACTION_CHANGE_PRODUCT);

                    bool noProduct = ecr.GetProduct().Length == 0;
                    if (noProduct)
                    {
                        // No product found, so value is for internal release - add message in notebook
                        ecr.SetNotebook("The referenced design item was moved to a product internal to Design");
                    }

                    callUpdateTR(ecr, user, null, ref status);
                    if (!status.OK)
                    {
                        // Log issue, but continue if e.g. a state change
                        HandlerSettings.LogMessage(
                            String.Format("Failed to change product on TR based on Bug ", workItem.Title),
                            HandlerSettings.LoggingLevel.WARN);
                    }
                }
            }

            updateTRFields(workItem, notification, user, about, ref status);

            if (newState != null)
            {
                // Handle state change
                updateTRState(workItem, oldState, newState, user, about, ref status);;
            }
        }
コード例 #24
0
 //private BBIHelper _bbihelper;
 public HarleysvilleDBIAlerts(WorkItemChangedEvent _wice, TFSIdentity tfsId)
 {
     WIChangeEvent = _wice;
     _dbihelper.SetDBI(_wice, tfsId);
     SetMailPriority();
 }
コード例 #25
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);
        }
コード例 #26
0
 public LBIHelper(WorkItemChangedEvent _wice, string tfsUrl)
 {
     SetWorkItemHelper(_wice, tfsUrl);
 }
コード例 #27
0
        // Check the Release is or just changed from a maintenance product.
        // TODO: This is cheating as we have hardcoded knowledge where release field is.
        // Need to make this fast, but to be correct we should use regular TFSMapper way.
        public EventType GetEventType(
            Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem wi,
            WorkItemChangedEvent notification,
            String user)
        {
            Field createTR = wi.Fields[TFSMapper.ERICSSON_DEFECT_CREATETR];

            if (createTR == null ||
                createTR.Value.ToString().Length == 0 ||
                createTR.Value.ToString().Equals("No", StringComparison.OrdinalIgnoreCase))
            {
                return(EventType.Ignore);
            }


            // Check project name. If not as defined for product mapping, disregard event.
            // This allows other projects on TFS server to be non-connected to TR system.
            if (serviceProvider.Length > 0 &&
                !wi.Project.Name.Equals(serviceProvider, StringComparison.OrdinalIgnoreCase))
            {
                return(EventType.Ignore);
            }



            bool inMaint = IsProductInMaintenance(wi);

            if (inMaint)
            {
                // Currenty selected release / product is in maintenance
                EventType evType = CheckDisconnect(wi, notification, user);
                if (evType == EventType.Disconnect)
                {
                    return(EventType.Disconnect);
                }
                return(EventType.CreateUpdate);
            }

            // ========================================================================
            // Check if we just changed from having a product in maintenance. Rare case,
            // then need to allow severing links and updating state of the workitem.

            if (notification.ChangeType == ChangeTypes.New)
            {
                // Can only happen for a changed WI, not a new.
                return(EventType.Ignore);
            }

            if (notification.ChangedFields == null || notification.ChangedFields.StringFields == null)
            {
                // No fields of interest are changed
                return(EventType.Ignore);
            }

            StringField[] changedFields = notification.ChangedFields.StringFields;
            for (int i = 0; i < changedFields.Length; i++)
            {
                String name = changedFields[i].ReferenceName;

                // If the release is changed, we need to update the TR product
                // Note: In case we also set to Duplicate, we will disregard product change
                if (name.Equals(TFSMapper.TFS_FAULTY_PRODUCT))
                {
                    String releaseName = changedFields[i].OldValue;
                    if (releaseName == null || releaseName.Length == 0)
                    {
                        // Should not happen - Mapping needs to be initialized
                        HandlerSettings.LogMessage(
                            "Can not tell if product is in maintenance as the Release name not defined.",
                            HandlerSettings.LoggingLevel.WARN);
                        return(EventType.Ignore);
                    }

                    if (releaseToProductMap.ContainsKey(releaseName))
                    {
                        return(EventType.CreateUpdate);
                    }
                    else
                    {
                        return(EventType.Ignore);
                    }
                }
            }

            return(EventType.Ignore);
        }
コード例 #28
0
 public NotificationWrapper(NotificationType notification, WorkItemChangedEvent eventArgs)
 {
     this.notification = notification;
     this.eventArgs = eventArgs;
 }
コード例 #29
0
        public void SetDBI(WorkItemChangedEvent wice, TFSIdentity tfsId)
        {
            _dbi = new DBI(GetDBINumber(wice.CoreFields.IntegerFields), tfsId.Url);

            this.SetWorkItemHelper(wice, (TFWI)_dbi);

            _dbiType = GetDBIType();
            _state = GetState();
            _stateChange = GetStateChangeType();
            _targetEnv = GetTargetEnvironment();

            if (ChangeType == ChangeTypes.New ||
                !HasBeenAutoFilled() ||
                Check4NewBuildPackage())
            {
                this.AutoFill();
                SetBuildNumbersField();
                ResetWIFields();
                PopBuildNumbersList();
                LinkBBIs();
            }
            else
            {
                PopBuildNumbersList();
                LinkBBIs();

            }

            if (WiFields["New Test Environment"].Equals("Production", StringComparison.CurrentCultureIgnoreCase))
            {
                _isPrd = true;
            }

            if ((_state == DBIStates.Ready4IRB || _state == DBIStates.IRBApproved) && _stateChange == WIStateChangeType.New)
            {
                _isIRB = true;
            }
        }