Exemplo n.º 1
0
 public long?CalculateAssignedUserId(long boardId, string assignedTo)
 {
     if (!String.IsNullOrEmpty(assignedTo))
     {
         if (_tfsUsers != null && _tfsUsers.Any())
         {
             var user = _tfsUsers.FirstOrDefault(x =>
                                                 x != null &&
                                                 x.DisplayName != null &&
                                                 !String.IsNullOrEmpty(x.DisplayName) &&
                                                 x.DisplayName.ToLowerInvariant() == assignedTo.ToLowerInvariant());
             if (user != null)
             {
                 var lkUser = LeanKit.GetBoard(boardId).BoardUsers.FirstOrDefault(x => x != null &&
                                                                                  (((!String.IsNullOrEmpty(x.EmailAddress)) && (!String.IsNullOrEmpty(user.MailAddress)) && x.EmailAddress.ToLowerInvariant() == user.MailAddress.ToLowerInvariant()) || ((!String.IsNullOrEmpty(x.FullName)) && (!String.IsNullOrEmpty(user.DisplayName)) && x.FullName.ToLowerInvariant() == user.DisplayName.ToLowerInvariant()) ||
                                                                                   ((!String.IsNullOrEmpty(x.FullName)) && (!string.IsNullOrEmpty(user.DisplayName)) && x.FullName.ToLowerInvariant() == user.DisplayName.ToLowerInvariant()) ||
                                                                                   ((!String.IsNullOrEmpty(x.UserName)) && (!String.IsNullOrEmpty(user.AccountName)) && x.UserName.ToLowerInvariant() == user.AccountName.ToLowerInvariant())));
                 if (lkUser != null)
                 {
                     return(lkUser.Id);
                 }
             }
         }
     }
     return(null);
 }
Exemplo n.º 2
0
 private void SetAssignedUser(WorkItem workItem, long boardId, long userId)
 {
     try
     {
         var lkUser = LeanKit.GetBoard(boardId).BoardUsers.FirstOrDefault(x => x.Id == userId);
         if (lkUser != null)
         {
             var gss     = (IGroupSecurityService)_projectCollection.GetService(typeof(IGroupSecurityService));
             var sids    = gss.ReadIdentity(SearchFactor.AccountName, "Project Collection Valid Users", QueryMembership.Expanded);
             var users   = gss.ReadIdentities(SearchFactor.Sid, sids.Members, QueryMembership.None);
             var tfsUser = users.FirstOrDefault(x =>
                                                ((!string.IsNullOrEmpty(lkUser.EmailAddress)) && (!string.IsNullOrEmpty(x.MailAddress)) && lkUser.EmailAddress.ToLowerInvariant() == x.MailAddress.ToLowerInvariant()) ||
                                                ((!string.IsNullOrEmpty(lkUser.FullName)) && (!string.IsNullOrEmpty(x.DisplayName)) && lkUser.FullName.ToLowerInvariant() == x.DisplayName.ToLowerInvariant()) ||
                                                ((!string.IsNullOrEmpty(lkUser.UserName)) && (!string.IsNullOrEmpty(x.AccountName)) && lkUser.UserName.ToLowerInvariant() == x.AccountName.ToLowerInvariant()));
             if (tfsUser != null && tfsUser.DisplayName != null)
             {
                 workItem.Fields["System.AssignedTo"].Value = tfsUser.DisplayName;
             }
         }
     }
     catch (Exception ex)
     {
         Log.Error(string.Format("An error occurred: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
     }
 }
        public override string ToString()
        {
            var sb = new StringBuilder();

            sb.AppendLine("          LeanKit : " + LeanKit.ToString());
            sb.AppendLine("          Target  : " + Target);
            return(sb.ToString());
        }
        protected override void Synchronize(BoardMapping project)
        {
            Log.Debug("Polling GitHub for Pull Requests");

            var queryAsOfDate = QueryDate.AddMilliseconds(Configuration.PollingFrequency * -1.5);

            //https://api.github.com/repos/{0}/{1}/pulls?state=Open
            var request = new RestRequest(string.Format("repos/{0}/{1}/pulls", Configuration.Target.Host, project.Identity.Target), Method.GET);

            request.AddParameter("state", project.QueryStates[0]);

            var resp = _restClient.Execute(request);

            if (resp.StatusCode != HttpStatusCode.OK)
            {
                var serializer   = new JsonSerializer <ErrorMessage>();
                var errorMessage = serializer.DeserializeFromString(resp.Content);
                Log.Error(string.Format("Unable to get Pull Requests from GitHub, Error: {0}. Check your board/repo mapping configuration.", errorMessage.Message));
                return;
            }

            var pulls = new JsonSerializer <List <Pull> >().DeserializeFromString(resp.Content);

            Log.Info("\nQueried [{0}] at {1} for changes after {2}", project.Identity.Target, QueryDate, queryAsOfDate.ToString("o"));

            if (pulls != null && pulls.Any() && pulls[0].Id > 0)
            {
                foreach (var pull in pulls)
                {
                    if (pull.Id > 0)
                    {
                        Log.Info("Pull Requests [{0}]: {1}, {2}, {3}", pull.Number, pull.Title, pull.User.Login, pull.State);

                        // does this workitem have a corresponding card?
                        var card = LeanKit.GetCardByExternalId(project.Identity.LeanKit, pull.Id + "|" + pull.Number.ToString());

                        if (card == null || !card.ExternalSystemName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase))
                        {
                            Log.Debug("Create new card for Pull Request [{0}]", pull.Number);
                            CreateCardFromItem(project, pull);
                        }
                        else
                        {
                            Log.Debug("Previously created a card for Pull Request [{0}]", pull.Number);
                            if (project.UpdateCards)
                            {
                                PullUpdated(pull, card, project);
                            }
                            else
                            {
                                Log.Info("Skipped card update because 'UpdateCards' is disabled.");
                            }
                        }
                    }
                }
                Log.Info("{0} item(s) queried.\n", pulls.Count);
            }
        }
        private void PullUpdated(Pull pull, Card card, BoardMapping boardMapping)
        {
            Log.Info("Pull [{0}] updated, comparing to corresponding card...", pull.Id);

            long boardId = boardMapping.Identity.LeanKit;

            // sync and save those items that are different (of title, description, priority)
            bool saveCard = false;

            if (pull.Title != card.Title)
            {
                card.Title = pull.Title;
                saveCard   = true;
            }

            if (pull.Body.SanitizeCardDescription() != card.Description)
            {
                card.Description = pull.Body.SanitizeCardDescription();
                saveCard         = true;
            }

            var priority = pull.LeanKitPriority();

            if (priority != card.Priority)
            {
                card.Priority = priority;
                saveCard      = true;
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && boardMapping.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
                saveCard = true;
            }

            if (saveCard)
            {
                Log.Info("Updating card [{0}]", card.Id);
                LeanKit.UpdateCard(boardId, card);
            }
        }
Exemplo n.º 6
0
        private void UpdateBoardVersion(long boardId, long?version = null)
        {
            if (!version.HasValue)
            {
                var board = LeanKit.GetBoard(boardId);
                if (board == null)
                {
                    return;
                }
                version = board.Version;
            }

            if (AppSettings.BoardVersions.ContainsKey(boardId))
            {
                AppSettings.BoardVersions[boardId] = version.Value;
            }
            else
            {
                AppSettings.BoardVersions.Add(boardId, version.Value);
            }
            LocalStorage.Save(AppSettings);
        }
Exemplo n.º 7
0
        public long?CalculateAssignedUserId(long boardId, Ticket ticket)
        {
            if (ticket == null)
            {
                return(null);
            }

            if (ticket.Assignee_Id > 0)
            {
                // http://mysubdomain.unfuddle.com/api/v1/people/{id}
                var request      = new RestRequest(string.Format("/api/v1/people/{0}", ticket.Assignee_Id), Method.GET);
                var unfuddleResp = _restClient.Execute(request);

                if (unfuddleResp.StatusCode != HttpStatusCode.OK)
                {
                    var serializer   = new JsonSerializer <ErrorMessage>();
                    var errorMessage = serializer.DeserializeFromString(unfuddleResp.Content);
                    Log.Warn(string.Format("Unable to get user from Unfuddle, Error: {0}", errorMessage.Message));
                }
                else
                {
                    var user = new JsonSerializer <Person>().DeserializeFromString(unfuddleResp.Content);

                    if (user != null)
                    {
                        var lkUser = LeanKit.GetBoard(boardId).BoardUsers.FirstOrDefault(x => x != null &&
                                                                                         ((!string.IsNullOrEmpty(x.EmailAddress)) && (!string.IsNullOrEmpty(user.Email)) && x.EmailAddress.ToLowerInvariant() == user.Email.ToLowerInvariant()) ||
                                                                                         ((!string.IsNullOrEmpty(x.FullName)) && (!string.IsNullOrEmpty(user.Last_Name)) && x.FullName.ToLowerInvariant() == (user.First_Name + " " + user.Last_Name).ToLowerInvariant()) ||
                                                                                         ((!string.IsNullOrEmpty(x.UserName)) && (!string.IsNullOrEmpty(user.Username)) && x.UserName.ToLowerInvariant() == user.Username.ToLowerInvariant()));
                        if (lkUser != null)
                        {
                            return(lkUser.Id);
                        }
                    }
                }
            }

            return(null);
        }
Exemplo n.º 8
0
        private void LoadBoardValues(BoardMapping boardMapping)
        {
            Board board = null;

            try
            {
                board = LeanKit.GetBoard(boardMapping.Identity.LeanKit);
            }
            catch (LeanKitAPIException ex)
            {
                Log.Error(ex, string.Format("Error getting Board: {0}", boardMapping.Identity.LeanKit));
            }

            if (board == null)
            {
                return;
            }

            if (board.CardTypes != null && board.CardTypes.Any())
            {
                boardMapping.ValidCardTypes = board.CardTypes;

                // check to make sure we have a default card type
                var defaultCard = boardMapping.ValidCardTypes.FirstOrDefault(x => x.IsDefault);
                if (defaultCard == null)
                {
                    // if we do not have a default card type then check
                    // to see if there is a Task card type and make that the default
                    var taskCardType = boardMapping.ValidCardTypes.FirstOrDefault(x => x.Name.ToLowerInvariant() == "task");
                    if (taskCardType != null)
                    {
                        boardMapping.ValidCardTypes.FirstOrDefault(x => x.Name.ToLowerInvariant() == "task").IsDefault = true;
                    }
                    else
                    {
                        // otherwise just set the first card type to be the default
                        boardMapping.ValidCardTypes.FirstOrDefault().IsDefault = true;
                    }
                }
            }

            if (board.ArchiveTopLevelLaneId.HasValue)
            {
                boardMapping.ArchiveLaneId = board.ArchiveTopLevelLaneId.Value;
            }
            else
            {
                var archive = board.Archive.FirstOrDefault(x => x.ParentLaneId == 0);
                if (archive != null && archive.Id.HasValue)
                {
                    boardMapping.ArchiveLaneId = archive.Id.Value;
                }

                if (boardMapping.ArchiveLaneId == 0)
                {
                    var allLanes = board.AllLanes();
                    archive = allLanes.FirstOrDefault(x => x.ClassType == LaneClassType.Archive && x.ParentLaneId == 0);
                    if (archive != null && archive.Id.HasValue)
                    {
                        boardMapping.ArchiveLaneId = archive.Id.Value;
                    }
                }
            }

            if (board.Lanes != null && board.Lanes.Any())
            {
                var validLanes = board.AllLanes().Where(x => x.ClassType != LaneClassType.Archive).OrderBy(x => x.Index).ToList();
                var maxIndex   = validLanes.Max(x => x.Index);

                // only use active lanes for the purpose of selecting the default drop lane
                var activeLanes       = board.Lanes.Where(x => x.ClassType == LaneClassType.Active).OrderBy(x => x.Index).ToList();
                var defaultDropLaneId = GetDefaultDropLane(activeLanes);

                boardMapping.ValidLanes = validLanes
                                          .Select(x => new Lane
                {
                    Id           = x.Id.Value,
                    Name         = x.Title,
                    IsFirst      = x.Id == defaultDropLaneId,
                    ChildLaneIds = (x.ChildLaneIds != null && x.ChildLaneIds.Any()) ? x.ChildLaneIds : null,
                    IsLast       = (boardMapping.ArchiveLaneId > 0) ? x.Id == boardMapping.ArchiveLaneId : x.Index == maxIndex
                })
                                          .ToList();

                if (boardMapping.ArchiveLaneId > 0)
                {
                    var archiveLane = board.GetLaneById(boardMapping.ArchiveLaneId);
                    if (archiveLane != null)
                    {
                        boardMapping.ValidLanes.Add(new Lane
                        {
                            Id      = boardMapping.ArchiveLaneId,
                            Name    = archiveLane.Title,
                            IsFirst = false,
                            IsLast  = true
                        });
                    }
                }
            }

            if (boardMapping.Types == null)
            {
                boardMapping.Types = new List <WorkItemType>();
            }

            // values in LaneToStatesMap are assumed to valid, as they were configured using valid values.
            if (boardMapping.LaneToStatesMap == null)
            {
                Log.Fatal("An unexpected error occurred -- there is no valid lane-to-states mapping.");
            }
        }
Exemplo n.º 9
0
        private void CheckForMissedCardMoves(BoardMapping mapping)
        {
            // if we have local storage, we have saved board versions and we have one for this board
            long boardId = mapping.Identity.LeanKit;

            if (AppSettings != null &&
                AppSettings.BoardVersions != null &&
                AppSettings.BoardVersions.Any() &&
                AppSettings.BoardVersions.ContainsKey(boardId))
            {
                var version = AppSettings.BoardVersions[boardId];
                Log.Debug(string.Format("Checking for any cards moved to mapped lanes on board [{0}] since service last ran, version [{1}].", boardId, version));
                try
                {
                    var events = LeanKit.GetBoardHistorySince(boardId, (int)version);
                    var board  = LeanKit.GetBoard(boardId);
                    if (board != null && events != null)
                    {
                        foreach (var ev in events)
                        {
                            // check for created cards
                            if (ev.EventType == "CardCreation")
                            {
                                var card = LeanKit.GetCard(board.Id, ev.CardId);
                                if (card != null && string.IsNullOrEmpty(card.ExternalCardID))
                                {
                                    try
                                    {
                                        CreateNewItem(card.ToCard(), mapping);
                                    }
                                    catch (Exception e)
                                    {
                                        Log.Error("Exception for CreateNewItem: " + e.Message);
                                    }
                                }
                            }
                            // only look for moved cards
                            else if (ev.ToLaneId != 0)
                            {
                                var lane = board.GetLaneById(ev.ToLaneId);
                                if (lane != null)
                                {
                                    if (lane.Id.HasValue && mapping.LaneToStatesMap.Any() && mapping.LaneToStatesMap.ContainsKey(lane.Id.Value))
                                    {
                                        if (mapping.LaneToStatesMap[lane.Id.Value] != null && mapping.LaneToStatesMap[lane.Id.Value].Count > 0)
                                        {
                                            // board.GetCard() only seems to get cards in active lanes
                                            // using LeanKitApi.GetCard() instead because it will get
                                            // cards in archive lanes
                                            var card = LeanKit.GetCard(board.Id, ev.CardId);
                                            if (card != null && !string.IsNullOrEmpty(card.ExternalCardID))
                                            {
                                                try {
                                                    UpdateStateOfExternalItem(card.ToCard(), mapping.LaneToStatesMap[lane.Id.Value], mapping);
                                                } catch (Exception e) {
                                                    Log.Error("Exception for UpdateStateOfExternalItem: " + e.Message);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        UpdateBoardVersion(board.Id, board.Version);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(string.Format("An error occured: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
                }
            }
        }
Exemplo n.º 10
0
        protected override void CreateNewItem(Card card, BoardMapping boardMapping)
        {
            var jiraIssueType = GetJiraIssueType(boardMapping, card.TypeId);

            string json = "{ \"fields\": { ";

            json += "\"project\":  { \"key\": \"" + boardMapping.Identity.Target + "\" }";
            json += ", \"summary\": \"" + card.Title.Replace("\"", "\\\"") + "\" ";
            json += ", \"description\": \"" + (card.Description != null ? card.Description.Replace("</p>", "").Replace("<p>", "").Replace("\r", "\\r").Replace("\n", "\\n").Replace("\"", "\\\"") : "") + "\" ";
            json += ", \"issuetype\": { \"name\": \"" + jiraIssueType + "\" }";
            json += ", \"priority\": { \"name\": \"" + GetPriority(card.Priority) + "\" }";

            if (jiraIssueType.ToLowerInvariant() == "epic")
            {
                if (CustomFields.Any())
                {
                    var epicNameField = CustomFields.FirstOrDefault(x => x.Name == "Epic Name");
                    if (epicNameField != null)
                    {
                        json += ", \"" + epicNameField.Id + "\": \"" + card.Title.Replace("\"", "\\\"") + "\"";
                    }
                }
            }

            if (!string.IsNullOrEmpty(card.DueDate) && CurrentUser != null)
            {
                try
                {
                    var dateFormat = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    var parsed     = DateTime.ParseExact(card.DueDate, dateFormat, CultureInfo.InvariantCulture);

                    json += ", \"duedate\": \"" + parsed.ToString("o") + "\"";
                }
                catch (Exception ex)
                {
                    Log.Warn(ex, "Could not parse due date: {0}", card.DueDate);
                }
            }

            if (!string.IsNullOrEmpty(card.Tags))
            {
                var    newLabels    = card.Tags.Split(',');
                string updateLabels = "";
                int    ctr          = 0;
                foreach (string newLabel in newLabels)
                {
                    if (ctr > 0)
                    {
                        updateLabels += ", ";
                    }

                    updateLabels += "\"" + newLabel.Trim() + "\"";

                    ctr++;
                }
                json += ", \"labels\": [" + updateLabels + "]";
            }

            json += "}}";

            Issue newIssue = null;

            try
            {
                //https://yoursite.atlassian.net/rest/api/latest/issue
                var createRequest = new RestRequest("/rest/api/latest/issue", Method.POST);
                createRequest.AddParameter("application/json", json, ParameterType.RequestBody);
                var resp = _restClient.Execute(createRequest);

                if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.Created)
                {
                    var serializer   = new JsonSerializer <ErrorMessage>();
                    var errorMessage = serializer.DeserializeFromString(resp.Content);
                    Log.Error(string.Format("Unable to create Issue from card [{0}], Description: {1}, Message: {2}",
                                            card.ExternalCardID, resp.StatusDescription, errorMessage.Message));
                }
                else
                {
                    newIssue = new JsonSerializer <Issue>().DeserializeFromString(resp.Content);
                    Log.Debug(String.Format("Created Issue [{0}]", newIssue.Key));
                }
            }
            catch (Exception ex)
            {
                Log.Error(string.Format("Unable to create Issue from Card [{0}], Exception: {1}", card.ExternalCardID, ex.Message));
            }

            if (newIssue != null)
            {
                try
                {
                    card.ExternalCardID     = newIssue.Key;
                    card.ExternalSystemName = ServiceName;
                    card.ExternalSystemUrl  = string.Format(_externalUrlTemplate, newIssue.Key);

                    // now that we've created the work item let's try to set it to any matching state defined by lane
                    var states = boardMapping.LaneToStatesMap[card.LaneId];
                    if (states != null)
                    {
                        UpdateStateOfExternalItem(card, states, boardMapping, true);
                    }

                    LeanKit.UpdateCard(boardMapping.Identity.LeanKit, card);
                }
                catch (Exception ex)
                {
                    Log.Error(string.Format("Error updating Card [{0}] after creating new Issue, Exception: {1}", card.ExternalCardID,
                                            ex.Message));
                }
            }
        }
Exemplo n.º 11
0
        private void CreateCardFromItem(BoardMapping project, Issue issue)
        {
            if (issue == null)
            {
                return;
            }

            var boardId = project.Identity.LeanKit;

            var mappedCardType = issue.LeanKitCardType(project);

            var validLanes = project.LanesFromState(issue.Fields.Status.Name);
            var laneId     = validLanes.Any() ? validLanes.First() : project.DefaultCardCreationLaneId;

            var card = new Card
            {
                Active             = true,
                Title              = issue.Fields.Summary,
                Description        = issue.Fields.Description.SanitizeCardDescription(),
                Priority           = issue.LeanKitPriority(),
                TypeId             = mappedCardType.Id,
                TypeName           = mappedCardType.Name,
                LaneId             = laneId,
                ExternalCardID     = issue.Key,
                ExternalSystemName = ServiceName,
                ExternalSystemUrl  = string.Format(_externalUrlTemplate, issue.Key)
            };

            var assignedUserId = issue.LeanKitAssignedUserId(boardId, LeanKit);

            if (assignedUserId != null)
            {
                card.AssignedUserIds = new[] { assignedUserId.Value }
            }
            ;

            if (issue.Fields != null && issue.Fields.DueDate != null && CurrentUser != null)
            {
                var dateFormat = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                card.DueDate = issue.Fields.DueDate.Value.ToString(dateFormat, CultureInfo.InvariantCulture);
            }

            if (issue.Fields != null && issue.Fields.Labels != null && issue.Fields.Labels.Any())
            {
                card.Tags = string.Join(",", issue.Fields.Labels);
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && project.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
            }

            // TODO: Add size from the custom story points field.

            Log.Info("Creating a card of type [{0}] for issue [{1}] on Board [{2}] on Lane [{3}]", mappedCardType.Name, issue.Key, boardId, laneId);

            CardAddResult cardAddResult = null;

            int  tries   = 0;
            bool success = false;

            while (tries < 10 && !success)
            {
                if (tries > 0)
                {
                    Log.Error(string.Format("Attempting to create card for work item [{0}] attempt number [{1}]", issue.Key, tries));
                    // wait 5 seconds before trying again
                    Thread.Sleep(new TimeSpan(0, 0, 5));
                }

                try
                {
                    cardAddResult = LeanKit.AddCard(boardId, card, "New Card From Jira Issue");
                    success       = true;
                }
                catch (Exception ex)
                {
                    Log.Error(string.Format("An error occurred: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
                }
                tries++;
            }
            card.Id = cardAddResult.CardId;

            Log.Info("Created a card [{0}] of type [{1}] for work item [{2}] on Board [{3}] on Lane [{4}]", card.Id, mappedCardType.Name, issue.Key, boardId, laneId);
        }
Exemplo n.º 12
0
        protected override void Synchronize(BoardMapping project)
        {
            Log.Debug("Polling Jira for Issues");

            var queryAsOfDate = QueryDate.AddMilliseconds(Configuration.PollingFrequency * -1.5);

            string jqlQuery;
            var    formattedQueryDate = queryAsOfDate.ToString(QueryDateFormat, CultureInfo.InvariantCulture);

            if (!string.IsNullOrEmpty(project.Query))
            {
                jqlQuery = string.Format(project.Query, formattedQueryDate);
            }
            else
            {
                var queryFilter = string.Format(" and ({0})", string.Join(" or ", project.QueryStates.Select(x => "status = '" + x.Trim() + "'").ToList()));
                if (!string.IsNullOrEmpty(project.ExcludedTypeQuery))
                {
                    queryFilter += project.ExcludedTypeQuery;
                }
                jqlQuery = string.Format("project=\"{0}\" {1} and updated > \"{2}\" order by created asc", project.Identity.Target, queryFilter, formattedQueryDate);
            }

            //https://yoursite.atlassian.net/rest/api/latest/search?jql=project=%22More+Tests%22+and+status=%22open%22+and+created+%3E+%222008/12/31+12:00%22+order+by+created+asc&fields=id,status,priority,summary,description
            var request = new RestRequest("/rest/api/latest/search", Method.GET);

            request.AddParameter("jql", jqlQuery);
            request.AddParameter("fields", "id,status,priority,summary,description,issuetype,type,assignee,duedate,labels");
            request.AddParameter("maxResults", "9999");

            var jiraResp = _restClient.Execute(request);

            if (jiraResp.StatusCode != HttpStatusCode.OK)
            {
                var serializer   = new JsonSerializer <ErrorMessage>();
                var errorMessage = serializer.DeserializeFromString(jiraResp.Content);
                Log.Error(string.Format("Unable to get issues from Jira, Error: {0}. Check your board/project mapping configuration.", errorMessage.Message));
                return;
            }

            var resp = new JsonSerializer <IssuesResponse>().DeserializeFromString(jiraResp.Content);

            Log.Info("\nQueried [{0}] at {1} for changes after {2}", project.Identity.Target, QueryDate, queryAsOfDate.ToString("o"));

            if (resp != null && resp.Issues != null && resp.Issues.Any())
            {
                var issues = resp.Issues;
                foreach (var issue in issues)
                {
                    Log.Info("Issue [{0}]: {1}, {2}, {3}", issue.Key, issue.Fields.Summary, issue.Fields.Status.Name, issue.Fields.Priority.Name);

                    // does this workitem have a corresponding card?
                    var card = LeanKit.GetCardByExternalId(project.Identity.LeanKit, issue.Key);

                    if (card == null || !card.ExternalSystemName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase))
                    {
                        Log.Debug("Create new card for Issue [{0}]", issue.Key);
                        CreateCardFromItem(project, issue);
                    }
                    else
                    {
                        Log.Debug("Previously created a card for Issue [{0}]", issue.Key);
                        if (project.UpdateCards)
                        {
                            IssueUpdated(issue, card, project);
                        }
                        else
                        {
                            Log.Info("Skipped card update because 'UpdateCards' is disabled.");
                        }
                    }
                }
                Log.Info("{0} item(s) queried.\n", issues.Count);
            }
        }
Exemplo n.º 13
0
        private void IssueUpdated(Issue issue, Card card, BoardMapping boardMapping)
        {
            Log.Info("Issue [{0}] updated, comparing to corresponding card...", issue.Key);

            long boardId = boardMapping.Identity.LeanKit;

            // sync and save those items that are different (of title, description, priority)
            bool saveCard = false;

            if (issue.Fields != null)
            {
                if (issue.Fields.Summary != null && issue.Fields.Summary != card.Title)
                {
                    card.Title = issue.Fields.Summary;
                    saveCard   = true;
                }

                if (issue.Fields.Description != null && issue.Fields.Description.SanitizeCardDescription() != card.Description)
                {
                    card.Description = issue.Fields.Description.SanitizeCardDescription();
                    saveCard         = true;
                }

                var priority = issue.LeanKitPriority();
                if (priority != card.Priority)
                {
                    card.Priority = priority;
                    saveCard      = true;
                }

                if (issue.Fields.Labels != null && issue.Fields.Labels.Count > 0)
                {
                    var tags = string.Join(",", issue.Fields.Labels.Select(x => x));
                    if (card.Tags != tags)
                    {
                        card.Tags = tags;
                        saveCard  = true;
                    }
                }
                else if (!string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = "";
                    saveCard  = true;
                }

                if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && boardMapping.TagCardsWithTargetSystemName)
                {
                    if (string.IsNullOrEmpty(card.Tags))
                    {
                        card.Tags = ServiceName;
                    }
                    else
                    {
                        card.Tags += "," + ServiceName;
                    }
                    saveCard = true;
                }

                if (issue.Fields.DueDate != null && CurrentUser != null)
                {
                    var dateFormat    = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    var dueDateString = issue.Fields.DueDate.Value.ToString(dateFormat, CultureInfo.InvariantCulture);
                    if (card.DueDate != dueDateString)
                    {
                        card.DueDate = dueDateString;
                        saveCard     = true;
                    }
                }
                else if (!string.IsNullOrEmpty(card.DueDate))
                {
                    card.DueDate = "";
                    saveCard     = true;
                }
            }

            if (saveCard)
            {
                Log.Info("Updating card [{0}]", card.Id);
                LeanKit.UpdateCard(boardId, card);
            }

            // check the state of the work item
            // if we have the state mapped to a lane then check to see if the card is in that lane
            // if it is not in that lane then move it to that lane
            if (boardMapping.UpdateCardLanes && issue.Fields != null && issue.Fields.Status != null && !string.IsNullOrEmpty(issue.Fields.Status.Name))
            {
                // if card is already in archive lane then we do not want to move it to the end lane
                // because it is effectively the same thing with respect to integrating with TFS
                if (card.LaneId == boardMapping.ArchiveLaneId)
                {
                    return;
                }

                var laneIds = boardMapping.LanesFromState(issue.Fields.Status.Name);
                if (laneIds.Any())
                {
                    if (!laneIds.Contains(card.LaneId))
                    {
                        // first let's see if any of the lanes are sibling lanes, if so then
                        // we should be using one of them. So we'll limit the results to just siblings
                        if (boardMapping.ValidLanes != null)
                        {
                            var siblingLaneIds = (from siblingLaneId in laneIds
                                                  let parentLane =
                                                      boardMapping.ValidLanes.FirstOrDefault(x =>
                                                                                             x.HasChildLanes &&
                                                                                             x.ChildLaneIds.Contains(siblingLaneId) &&
                                                                                             x.ChildLaneIds.Contains(card.LaneId))
                                                      where parentLane != null
                                                      select siblingLaneId).ToList();
                            if (siblingLaneIds.Any())
                            {
                                laneIds = siblingLaneIds;
                            }
                        }

                        LeanKit.MoveCard(boardMapping.Identity.LeanKit, card.Id, laneIds.First(), 0, "Moved Lane From Jira Issue");
                    }
                }
            }
        }
		private void MapChildLanes(IList<LeanKit.API.Client.Library.TransferObjects.Lane> lanes, LeanKit.API.Client.Library.TransferObjects.Lane parentLane,
		                           LaneModel parentLaneModel, int level)
		{
			parentLaneModel.ChildLanes = new List<LaneModel>();
			parentLaneModel.IsParent = false;
			parentLaneModel.Level = level;

			if (parentLane.ChildLaneIds.Count == 0) return;

			parentLaneModel.IsParent = true;
			level++;

			foreach (var childLaneId in parentLane.ChildLaneIds)
			{
				var childLane = lanes.FirstOrDefault(x => x.Id == childLaneId);
				var childLaneModel = Mapper.Map<LaneModel>(childLane);
				MapChildLanes(lanes, childLane, childLaneModel, level);
				childLaneModel.Level = level;
				parentLaneModel.ChildLanes.Add(childLaneModel);
			}
		}
Exemplo n.º 15
0
        private void WorkItemUpdated(WorkItem workItem, Card card, BoardMapping project)
        {
            Log.Info("WorkItem [{0}] updated, comparing to corresponding card...", workItem.Id);

            var boardId = project.Identity.LeanKit;

            // sync and save those items that are different (of title, description, priority)
            var saveCard = false;

            if (workItem.Title != card.Title)
            {
                card.Title = workItem.Title;
                saveCard   = true;
            }

            var description = workItem.LeanKitDescription(GetTfsVersion());

            if (description != card.Description)
            {
                card.Description = description;
                saveCard         = true;
            }

            var priority = workItem.LeanKitPriority();

            if (priority != card.Priority)
            {
                card.Priority = priority;
                saveCard      = true;
            }

            if (workItem.Fields != null &&
                workItem.Fields.Contains("Tags") &&
                workItem.Fields["Tags"] != null &&
                workItem.Fields["Tags"].Value.ToString() != card.Tags)
            {
                var tfsTags = workItem.Fields["Tags"].Value.ToString();
                // since we cannot set the tags in TFS we cannot blindly overwrite the LK tags
                // with what is in TFS. Instead we can only add TFS tags to LK
                if (!string.IsNullOrEmpty(tfsTags))
                {
                    var tfsTagsArr = tfsTags.Split(',');
                    foreach (var tag in tfsTagsArr)
                    {
                        if (card.Tags.ToLowerInvariant().Contains(tag.ToLowerInvariant()))
                        {
                            continue;
                        }
                        if (card.Tags == string.Empty)
                        {
                            card.Tags = tag;
                        }
                        else
                        {
                            card.Tags += "," + tag;
                        }
                        saveCard = true;
                    }
                }
            }

            if (workItem.Fields != null && (workItem.Fields.Contains("Original Estimate") || workItem.Fields.Contains("Story Points")))
            {
                if (workItem.Fields.Contains("Original Estimate") && workItem.Fields["Original Estimate"] != null && workItem.Fields["Original Estimate"].Value != null)
                {
                    double cardSize;
                    var    isNumber = Double.TryParse(workItem.Fields["Original Estimate"].Value.ToString(), out cardSize);
                    if (isNumber)
                    {
                        var size = (int)cardSize;
                        if (card.Size != size)
                        {
                            card.Size = size;
                            saveCard  = true;
                        }
                    }
                }
                else if (workItem.Fields.Contains("Story Points") && workItem.Fields["Story Points"] != null && workItem.Fields["Story Points"].Value != null)
                {
                    double cardSize;
                    var    isNumber = Double.TryParse(workItem.Fields["Story Points"].Value.ToString(), out cardSize);
                    if (isNumber)
                    {
                        var size = (int)cardSize;
                        if (card.Size != size)
                        {
                            card.Size = size;
                            saveCard  = true;
                        }
                    }
                }
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && project.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
                saveCard = true;
            }

            if (saveCard)
            {
                Log.Info("Updating card [{0}]", card.Id);
                LeanKit.UpdateCard(boardId, card);
            }

            // check the state of the work item
            // if we have the state mapped to a lane then check to see if the card is in that lane
            // if it is not in that lane then move it to that lane
            if (!project.UpdateCardLanes || string.IsNullOrEmpty(workItem.State))
            {
                return;
            }

            // if card is already in archive lane then we do not want to move it to the end lane
            // because it is effectively the same thing with respect to integrating with TFS
            if (card.LaneId == project.ArchiveLaneId)
            {
                return;
            }

            var laneIds = project.LanesFromState(workItem.State);

            if (laneIds.Any())
            {
                if (!laneIds.Contains(card.LaneId))
                {
                    // first let's see if any of the lanes are sibling lanes, if so then
                    // we should be using one of them. So we'll limit the results to just siblings
                    if (project.ValidLanes != null)
                    {
                        var siblingLaneIds = (from siblingLaneId in laneIds
                                              let parentLane =
                                                  project.ValidLanes.FirstOrDefault(x =>
                                                                                    x.HasChildLanes &&
                                                                                    x.ChildLaneIds.Contains(siblingLaneId) &&
                                                                                    x.ChildLaneIds.Contains(card.LaneId))
                                                  where parentLane != null
                                                  select siblingLaneId).ToList();
                        if (siblingLaneIds.Any())
                        {
                            laneIds = siblingLaneIds;
                        }
                    }

                    LeanKit.MoveCard(project.Identity.LeanKit, card.Id, laneIds.First(), 0, "Moved Lane From TFS Work Item");
                }
            }
        }
Exemplo n.º 16
0
        private void IssueUpdated(Issue issue, Card card, BoardMapping boardMapping)
        {
            Log.Info("Issue [{0}] updated, comparing to corresponding card...", issue.Id);

            long boardId = boardMapping.Identity.LeanKit;

            // sync and save those items that are different (of title, description, priority)
            bool saveCard = false;

            if (issue.Title != card.Title)
            {
                card.Title = issue.Title;
                saveCard   = true;
            }

            if (issue.Body.SanitizeCardDescription() != card.Description)
            {
                card.Description = issue.Body.SanitizeCardDescription();
                saveCard         = true;
            }

            var priority = issue.LeanKitPriority();

            if (priority != card.Priority)
            {
                card.Priority = priority;
                saveCard      = true;
            }

            if (issue.Labels != null && issue.Labels.Count > 0)
            {
                var tags = string.Join(",", issue.Labels.Select(x => x.Name));
                if (card.Tags != tags)
                {
                    card.Tags = tags;
                    saveCard  = true;
                }
            }
            else if (!string.IsNullOrEmpty(card.Tags))
            {
                card.Tags = "";
                saveCard  = true;
            }

            if (issue.Milestone != null && issue.Milestone.Due_On != null)
            {
                if (CurrentUser != null)
                {
                    var dateFormat    = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    var dueDateString = issue.Milestone.Due_On.Value.ToString(dateFormat);
                    if (card.DueDate != dueDateString)
                    {
                        card.DueDate = dueDateString;
                        saveCard     = true;
                    }
                }
            }
            else if (!string.IsNullOrEmpty(card.DueDate))
            {
                card.DueDate = "";
                saveCard     = true;
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && boardMapping.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
                saveCard = true;
            }

            var lanes = boardMapping.LanesFromState(issue.State);

            if (lanes.Count > 0 && lanes.All(x => x != card.LaneId))
            {
                card.LaneId = lanes.First();
                saveCard    = true;
            }

            if (saveCard)
            {
                Log.Info("Updating card [{0}]", card.Id);
                LeanKit.UpdateCard(boardId, card);
            }
        }
Exemplo n.º 17
0
        protected override void Synchronize(BoardMapping project)
        {
            Log.Debug("Polling TFS [{0}] for Work Items", project.Identity.TargetName);

            //query a project for new items
            var stateQuery     = string.Format(" AND ({0})", String.Join(" or ", project.QueryStates.Select(x => "[System.State] = '" + x.Trim() + "'").ToList()));
            var iterationQuery = "";

            if (!string.IsNullOrEmpty(project.IterationPath))
            {
                iterationQuery = string.Format(" AND [System.IterationPath] UNDER '{0}' ", project.IterationPath);
            }

            var queryAsOfDate = QueryDate.AddMilliseconds(Configuration.PollingFrequency * -1.5).ToString("o");

            string tfsQuery;

            if (!string.IsNullOrEmpty(project.Query))
            {
                tfsQuery = string.Format(project.Query, queryAsOfDate);
            }
            else
            {
                tfsQuery = String.Format(
                    "[System.TeamProject] = '{0}' {1} {2} {3} and [System.ChangedDate] > '{4}'",
                    project.Identity.TargetName, iterationQuery, stateQuery, project.ExcludedTypeQuery, queryAsOfDate);
            }

            var queryStr = string.Format("SELECT [System.Id], [System.WorkItemType]," +
                                         " [System.State], [System.AssignedTo], [System.Title], [System.Description]" +
                                         " FROM WorkItems " +
                                         " WHERE {0}" +
                                         " ORDER BY [System.TeamProject]", tfsQuery);

            if (_projectCollectionWorkItemStore == null)
            {
                "Reconnecting to TFS...".Info();
                Init();
            }
            Query query;

            try
            {
                query = new Query(_projectCollectionWorkItemStore, queryStr, null, false);
            }
            catch (Exception ex)
            {
                Log.Error("Error creating TFS query. {0} ", ex.Message);
                if (_projectCollectionWorkItemStore == null)
                {
                    Log.Error("Project Collection Work Item Store is null");
                }
                throw;
            }
            var cancelableAsyncResult = query.BeginQuery();

            var changedItems = query.EndQuery(cancelableAsyncResult);

            Log.Info("\nQuery [{0}] for changes after {1}", project.Identity.Target, queryAsOfDate);
            Log.Debug(queryStr);

            foreach (WorkItem item in changedItems)
            {
                Log.Info("Work Item [{0}]: {1}, {2}, {3}",
                         item.Id, item.Title, item.Fields["System.AssignedTo"].Value, item.State);

                // does this workitem have a corresponding card?
                var card = LeanKit.GetCardByExternalId(project.Identity.LeanKit, item.Id.ToString(CultureInfo.InvariantCulture));

                if (card == null || !card.ExternalSystemName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase))
                {
                    Log.Debug("Creating new card for work item [{0}]", item.Id);
                    CreateCardFromWorkItem(project, item);
                }
                // TODO: else if Lane = defined end lane then update it in TFS (i.e. we missed the event)
                // call UpdateStateOfExternalWorkItem()
                else
                {
                    Log.Info("Previously created a card for work item[{0}]", item.Id);
                    if (project.UpdateCards)
                    {
                        WorkItemUpdated(item, card, project);
                    }
                    else
                    {
                        Log.Info("Skipped card update because 'UpdateCards' is disabled.");
                    }
                }
            }
            Log.Info("{0} item(s) queried.\n", changedItems.Count);
        }
Exemplo n.º 18
0
        private void CreateCardFromItem(BoardMapping project, Ticket ticket)
        {
            if (ticket == null)
            {
                return;
            }

            var boardId = project.Identity.LeanKit;

            var mappedCardType = ticket.LeanKitCardType(project);

            var laneId = project.LanesFromState(ticket.Status).First();
            var card   = new Card
            {
                Active             = true,
                Title              = ticket.Summary,
                Description        = ticket.Description.SanitizeCardDescription(),
                Priority           = ticket.LeanKitPriority(),
                TypeId             = mappedCardType.Id,
                TypeName           = mappedCardType.Name,
                LaneId             = laneId,
                ExternalCardID     = ticket.Id.ToString(),
                ExternalSystemName = ServiceName,
                ExternalSystemUrl  = string.Format(_externalUrlTemplate, ticket.Id, project.Identity.Target)
            };

            var assignedUserId = CalculateAssignedUserId(boardId, ticket);

            if (assignedUserId != null)
            {
                card.AssignedUserIds = new[] { assignedUserId.Value }
            }
            ;

            if (ticket.Due_On != null)
            {
                if (CurrentUser != null)
                {
                    var dateFormat = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    card.DueDate = ticket.Due_On.Value.ToString(dateFormat);
                }
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && project.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
            }

            Log.Info("Creating a card of type [{0}] for ticket [{1}] on Board [{2}] on Lane [{3}]", mappedCardType.Name, ticket.Id, boardId, laneId);

            CardAddResult cardAddResult = null;

            int  tries   = 0;
            bool success = false;

            while (tries < 10 && !success)
            {
                if (tries > 0)
                {
                    Log.Error(string.Format("Attempting to create card for ticket [{0}] attempt number [{1}]", ticket.Id, tries));
                    // wait 5 seconds before trying again
                    Thread.Sleep(new TimeSpan(0, 0, 5));
                }

                try
                {
                    cardAddResult = LeanKit.AddCard(boardId, card, "New Card From Unfuddle Ticket");
                    success       = true;
                }
                catch (Exception ex)
                {
                    Log.Error(string.Format("An error occurred: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
                }
                tries++;
            }
            if (cardAddResult != null)
            {
                card.Id = cardAddResult.CardId;
            }

            Log.Info("Created a card [{0}] of type [{1}] for ticket [{2}] on Board [{3}] on Lane [{4}]", card.Id, mappedCardType.Name, ticket.Id, boardId, laneId);
        }
Exemplo n.º 19
0
        protected override void Synchronize(BoardMapping project)
        {
            Log.Debug("Polling Unfuddle for Tickets");

            var queryAsOfDate = QueryDate.AddMilliseconds(Configuration.PollingFrequency * -1.5);

            var unfuddleQuery = !string.IsNullOrEmpty(project.Query)
                                ? string.Format(project.Query, queryAsOfDate.ToString("yyyy/MM/dd hh:mm"))
                                : string.Format("status-eq-{0},created_at-gt-{1}", project.QueryStates[0], queryAsOfDate.ToString("yyyy/MM/dd hh:mm"));

            //http://mysubdomain.unfuddle.com/api/v1/projects/{id}/ticket_reports/dynamic?sort_by=created_at&sort_direction=ASC&conditions_string=status-eq-new,created_at-gt-yyyy/MM/dd hh:mm
            var request = new RestRequest(string.Format("/api/v1/projects/{0}/ticket_reports/dynamic", project.Identity.Target), Method.GET);

            request.AddParameter("sort_by", "created_at");
            request.AddParameter("sort_direction", "ASC");
            request.AddParameter("conditions_string", unfuddleQuery);
            //, "id,status,priority,summary,description,type");
            request.AddParameter("limit", "500");

            var unfuddleResp = _restClient.Execute(request);

            if (unfuddleResp.StatusCode != HttpStatusCode.OK)
            {
                var serializer   = new JsonSerializer <ErrorMessage>();
                var errorMessage = serializer.DeserializeFromString(unfuddleResp.Content);
                Log.Error(string.Format("Unable to get tickets from Unfuddle, Error: {0}. Check your board/project mapping configuration.", errorMessage.Message));
                return;
            }

            var resp = new JsonSerializer <TicketsResponse>().DeserializeFromString(unfuddleResp.Content);

            Log.Info("\nQueried [{0}] at {1} for changes after {2}", project.Identity.Target, QueryDate, queryAsOfDate.ToString("o"));

            if (resp != null && resp.Groups != null && resp.Groups.Any())
            {
                foreach (var group in resp.Groups)
                {
                    if (group != null && group.Tickets != null && group.Tickets.Any())
                    {
                        var tickets = group.Tickets;
                        foreach (var ticket in tickets)
                        {
                            Log.Info("Ticket [{0}]: {1}, {2}, {3}", ticket.Id, ticket.Summary, ticket.Status, ticket.Priority);

                            // does this workitem have a corresponding card?
                            var card = LeanKit.GetCardByExternalId(project.Identity.LeanKit, ticket.Id.ToString());

                            if (card == null || !card.ExternalSystemName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase))
                            {
                                Log.Debug("Create new card for Ticket [{0}]", ticket.Id);
                                CreateCardFromItem(project, ticket);
                            }
                            else
                            {
                                Log.Debug("Previously created a card for Ticket [{0}]", ticket.Id);
                                if (project.UpdateCards)
                                {
                                    TicketUpdated(ticket, card, project);
                                }
                                else
                                {
                                    Log.Info("Skipped card update because 'UpdateCards' is disabled.");
                                }
                            }
                        }
                    }
                }
                Log.Info("{0} item(s) queried.\n", resp.Count);
            }
        }
Exemplo n.º 20
0
        private void TicketUpdated(Ticket ticket, Card card, BoardMapping boardMapping)
        {
            Log.Info("Ticket [{0}] updated, comparing to corresponding card...", ticket.Id);

            long boardId = boardMapping.Identity.LeanKit;

            // sync and save those items that are different (of title, description, priority)
            bool saveCard = false;

            if (ticket.Summary != card.Title)
            {
                card.Title = ticket.Summary;
                saveCard   = true;
            }

            if (ticket.Description.SanitizeCardDescription() != card.Description)
            {
                card.Description = ticket.Description.SanitizeCardDescription();
                saveCard         = true;
            }

            var priority = ticket.LeanKitPriority();

            if (priority != card.Priority)
            {
                card.Priority = priority;
                saveCard      = true;
            }

            if (ticket.Due_On != null)
            {
                if (CurrentUser != null)
                {
                    var dateFormat    = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    var dueDateString = ticket.Due_On.Value.ToString(dateFormat);
                    if (card.DueDate != dueDateString)
                    {
                        card.DueDate = dueDateString;
                        saveCard     = true;
                    }
                }
            }
            else if (!string.IsNullOrEmpty(card.DueDate))
            {
                card.DueDate = "";
                saveCard     = true;
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && boardMapping.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
                saveCard = true;
            }

            if (saveCard)
            {
                Log.Info("Updating card [{0}]", card.Id);
                LeanKit.UpdateCard(boardId, card);
            }
        }
Exemplo n.º 21
0
        protected override void CreateNewItem(Card card, BoardMapping boardMapping)
        {
            var project         = _projectCollectionWorkItemStore.Projects[boardMapping.Identity.TargetName];
            var tfsWorkItemType = GetTfsWorkItemType(boardMapping, project.WorkItemTypes, card.TypeId);
            var workItemType    = project.WorkItemTypes[tfsWorkItemType.Name];

            // Note: using the default state
            var workItem = new WorkItem(workItemType)
            {
                Title       = card.Title,
                Description = card.Description,
            };

            SetWorkItemPriority(workItem, card.Priority);

            if (!string.IsNullOrEmpty(card.DueDate))
            {
                if (workItem.Fields.Contains("Due Date"))
                {
                    workItem.Fields["Due Date"].Value = card.DueDate;
                }
            }

            if (card.AssignedUserIds != null && card.AssignedUserIds.Any())
            {
                SetAssignedUser(workItem, boardMapping.Identity.LeanKit, card.AssignedUserIds[0]);
            }

            if (!string.IsNullOrEmpty(boardMapping.IterationPath))
            {
                workItem.Fields["System.IterationPath"].Value = boardMapping.IterationPath;
            }

            try
            {
                Log.Debug("Attempting to create Work Item from Card [{0}]", card.Id);

                workItem.Save();

                Log.Debug("Created Work Item [{0}] from Card [{1}]", workItem.Id, card.Id);

                card.ExternalCardID     = workItem.Id.ToString(CultureInfo.InvariantCulture);
                card.ExternalSystemName = ServiceName;

                if (_projectHyperlinkService != null)
                {
                    card.ExternalSystemUrl = _projectHyperlinkService.GetWorkItemEditorUrl(workItem.Id).ToString();
                }

                // now that we've created the work item let's try to set it to any matching state defined by lane
                var states = boardMapping.LaneToStatesMap[card.LaneId];
                if (states != null)
                {
                    UpdateStateOfExternalItem(card, states, boardMapping, true);
                }

                LeanKit.UpdateCard(boardMapping.Identity.LeanKit, card);
            }
            catch (ValidationException ex)
            {
                Log.Error("Unable to create WorkItem from Card [{0}]. ValidationException: {1}", card.Id, ex.Message);
            }
            catch (Exception ex)
            {
                Log.Error("Unable to create WorkItem from Card [{0}], Exception: {1}", card.Id, ex.Message);
            }
        }
		// This method is based on method of same name from Kanban.ApplicationServices.BoardService
		private LeanKit.API.Client.Library.TransferObjects.Lane FindFirstChildLane(LeanKit.API.Client.Library.TransferObjects.Lane parentLane, IList<LeanKit.API.Client.Library.TransferObjects.Lane> allLanes)
		{
			if (parentLane == null) return null;
			return (parentLane.ChildLaneIds != null && parentLane.ChildLaneIds.Any())
					   ? FindFirstChildLane(allLanes.Where(x => x.ParentLaneId == parentLane.Id).OrderBy(x => x.Index).FirstOrDefault(), allLanes)
					   : parentLane;
		}
        private void CreateCardFromItem(BoardMapping project, Pull pull)
        {
            if (pull == null)
            {
                return;
            }

            var boardId = project.Identity.LeanKit;

            var mappedCardType = pull.LeanKitCardType(project);
            var laneId         = project.LanesFromState(pull.State).First();
            var card           = new Card
            {
                Active             = true,
                Title              = pull.Title,
                Description        = pull.Body.SanitizeCardDescription(),
                Priority           = pull.LeanKitPriority(),
                TypeId             = mappedCardType.Id,
                TypeName           = mappedCardType.Name,
                LaneId             = laneId,
                ExternalCardID     = pull.Id.ToString() + "|" + pull.Number.ToString(),
                ExternalSystemName = ServiceName,
                ExternalSystemUrl  = string.Format(_externalUrlTemplate, project.Identity.Target, pull.Number)
            };

            var assignedUserId = pull.LeanKitAssignedUser(boardId, LeanKit);

            if (assignedUserId != null)
            {
                card.AssignedUserIds = new[] { assignedUserId.Value }
            }
            ;

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && project.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
            }

            Log.Info("Creating a card of type [{0}] for Pull Request [{1}] on Board [{2}] on Lane [{3}]", mappedCardType.Name, pull.Number, boardId, laneId);

            CardAddResult cardAddResult = null;

            int  tries   = 0;
            bool success = false;

            while (tries < 10 && !success)
            {
                if (tries > 0)
                {
                    Log.Error(string.Format("Attempting to create card for Pull Request [{0}] attempt number [{1}]", pull.Id,
                                            tries));
                    // wait 5 seconds before trying again
                    Thread.Sleep(new TimeSpan(0, 0, 5));
                }

                try {
                    cardAddResult = LeanKit.AddCard(boardId, card, "New Card From GitHub Pull Request");
                    success       = true;
                } catch (Exception ex) {
                    Log.Error(string.Format("An error occurred: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
                }
                tries++;
            }
            if (cardAddResult != null)
            {
                card.Id = cardAddResult.CardId;
            }

            Log.Info("Created a card [{0}] of type [{1}] for Pull Request [{2}] on Board [{3}] on Lane [{4}]", card.Id, mappedCardType.Name, pull.Number, boardId, laneId);
        }
Exemplo n.º 24
0
        private void CreateCardFromItem(BoardMapping project, Issue issue)
        {
            if (issue == null)
            {
                return;
            }
            if (!project.CreateCards)
            {
                Log.Debug("CreateCards is disabled, skipping card creation.");
                return;
            }

            var boardId = project.Identity.LeanKit;

            var mappedCardType = issue.LeanKitCardType(project);
            var laneId         = project.LanesFromState(issue.State).First();
            var card           = new Card
            {
                Active             = true,
                Title              = issue.Title,
                Description        = issue.Body.SanitizeCardDescription(),
                Priority           = issue.LeanKitPriority(),
                TypeId             = mappedCardType.Id,
                TypeName           = mappedCardType.Name,
                LaneId             = laneId,
                ExternalCardID     = issue.Id + "|" + issue.Number,
                ExternalSystemName = ServiceName,
                ExternalSystemUrl  = string.Format(_externalUrlTemplate, project.Identity.Target, issue.Number),
                Index              = 9999
            };

            var assignedUserId = issue.LeanKitAssignedUserId(boardId, LeanKit);

            if (assignedUserId != null)
            {
                card.AssignedUserIds = new[] { assignedUserId.Value }
            }
            ;

            if (issue.Milestone != null && issue.Milestone.Due_On != null)
            {
                if (CurrentUser != null)
                {
                    var dateFormat = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                    card.DueDate = issue.Milestone.Due_On.Value.ToString(dateFormat);
                }
            }

            if (issue.Labels != null && issue.Labels.Any())
            {
                card.Tags = string.Join(",", issue.Labels.Select(x => x.Name).ToList());
            }

            if ((card.Tags == null || !card.Tags.Contains(ServiceName)) && project.TagCardsWithTargetSystemName)
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
            }

            Log.Info("Creating a card of type [{0}] for Issue [{1}] on Board [{2}] on Lane [{3}]", mappedCardType.Name, issue.Number, boardId, laneId);

            CardAddResult cardAddResult = null;

            int  tries   = 0;
            bool success = false;

            while (tries < 10 && !success)
            {
                if (tries > 0)
                {
                    Log.Error(string.Format("Attempting to create card for issue [{0}] attempt number [{1}]", issue.Id,
                                            tries));
                    // wait 5 seconds before trying again
                    Thread.Sleep(new TimeSpan(0, 0, 5));
                }

                try {
                    cardAddResult = LeanKit.AddCard(boardId, card, "New Card From GitHub Issue");
                    success       = true;
                } catch (Exception ex) {
                    Log.Error(string.Format("An error occurred: {0} - {1} - {2}", ex.GetType(), ex.Message, ex.StackTrace));
                }
                tries++;
            }
            card.Id = cardAddResult.CardId;

            Log.Info("Created a card [{0}] of type [{1}] for Issue [{2}] on Board [{3}] on Lane [{4}]", card.Id, mappedCardType.Name, issue.Number, boardId, laneId);
        }
Exemplo n.º 25
0
        private void CreateCardFromWorkItem(BoardMapping project, WorkItem workItem)
        {
            if (workItem == null)
            {
                return;
            }

            var boardId = project.Identity.LeanKit;

            var mappedCardType = workItem.LeanKitCardType(project);

            var laneId = project.LanesFromState(workItem.State).First();
            var card   = new Card
            {
                Active             = true,
                Title              = workItem.Title,
                Description        = workItem.LeanKitDescription(GetTfsVersion()),
                Priority           = workItem.LeanKitPriority(),
                TypeId             = mappedCardType.Id,
                TypeName           = mappedCardType.Name,
                LaneId             = laneId,
                ExternalCardID     = workItem.Id.ToString(CultureInfo.InvariantCulture),
                ExternalSystemName = ServiceName
            };

            if (workItem.Fields.Contains("Tags") && workItem.Fields["Tags"] != null && workItem.Fields["Tags"].Value != null)
            {
                card.Tags = workItem.Fields["Tags"].Value.ToString();
            }

            if (project.TagCardsWithTargetSystemName && (card.Tags == null || !card.Tags.Contains(ServiceName)))
            {
                if (string.IsNullOrEmpty(card.Tags))
                {
                    card.Tags = ServiceName;
                }
                else
                {
                    card.Tags += "," + ServiceName;
                }
            }

            if (_projectHyperlinkService != null)
            {
                card.ExternalSystemUrl = _projectHyperlinkService.GetWorkItemEditorUrl(workItem.Id).ToString();
            }

            if (workItem.Fields != null && workItem.Fields.Contains("Assigned To"))
            {
                if (workItem.Fields["Assigned To"] != null && workItem.Fields["Assigned To"].Value != null)
                {
                    var assignedUserId = CalculateAssignedUserId(boardId, workItem.Fields["Assigned To"].Value.ToString());
                    if (assignedUserId != null)
                    {
                        card.AssignedUserIds = new[] { assignedUserId.Value }
                    }
                    ;
                }
            }

            if (workItem.Fields != null && workItem.Fields.Contains("Due Date"))
            {
                if (workItem.Fields["Due Date"] != null && workItem.Fields["Due Date"].Value != null)
                {
                    DateTime tfsDueDate;
                    var      isDate = DateTime.TryParse(workItem.Fields["Due Date"].Value.ToString(), out tfsDueDate);
                    if (isDate)
                    {
                        if (CurrentUser != null)
                        {
                            var dateFormat = CurrentUser.DateFormat ?? "MM/dd/yyyy";
                            card.DueDate = tfsDueDate.ToString(dateFormat);
                        }
                    }
                }
            }

            if (workItem.Fields != null && (workItem.Fields.Contains("Original Estimate") || workItem.Fields.Contains("Story Points")))
            {
                if (workItem.Fields.Contains("Original Estimate") && workItem.Fields["Original Estimate"] != null && workItem.Fields["Original Estimate"].Value != null)
                {
                    double cardSize;
                    var    isNumber = Double.TryParse(workItem.Fields["Original Estimate"].Value.ToString(), out cardSize);
                    if (isNumber)
                    {
                        card.Size = (int)cardSize;
                    }
                }
                else if (workItem.Fields.Contains("Story Points") && workItem.Fields["Story Points"] != null && workItem.Fields["Story Points"].Value != null)
                {
                    double cardSize;
                    var    isNumber = Double.TryParse(workItem.Fields["Story Points"].Value.ToString(), out cardSize);
                    if (isNumber)
                    {
                        card.Size = (int)cardSize;
                    }
                }
            }

            Log.Info("Creating a card of type [{0}] for work item [{1}] on Board [{2}] on Lane [{3}]", mappedCardType.Name, workItem.Id, boardId, laneId);

            CardAddResult cardAddResult = null;

            var tries   = 0;
            var success = false;

            while (tries < 10 && !success)
            {
                if (tries > 0)
                {
                    Log.Warn(String.Format("Attempting to create card for work item [{0}] attempt number [{1}]", workItem.Id,
                                           tries));
                    // wait 5 seconds before trying again
                    Thread.Sleep(new TimeSpan(0, 0, 5));
                }

                try
                {
                    cardAddResult = LeanKit.AddCard(boardId, card, "New Card From TFS Work Item");
                    success       = true;
                }
                catch (Exception ex)
                {
                    Log.Error(ex, string.Format("An error occurred creating a new card for work item [{0}]", workItem.Id));
                }
                tries++;
            }
            card.Id = cardAddResult.CardId;

            Log.Info("Created a card [{0}] of type [{1}] for work item [{2}] on Board [{3}] on Lane [{4}]", card.Id, mappedCardType.Name, workItem.Id, boardId, laneId);
        }