Esempio n. 1
0
        public GitArtifactLinkDetails(WorkItemRelation artifactLink, int linkIndex)
        {
            Url   = artifactLink.Url;
            Index = linkIndex;
            if (Url.Contains("Git"))
            {
                string[] ids = WebUtility.UrlDecode(Url).Split('/');

                if (ids[4] == "Commit")
                {
                    IsGitLink    = true;
                    CommitID     = ids[7];
                    RepositoryID = Guid.Parse(ids[6]);
                    ProjectId    = Guid.Parse(ids[5]);
                    LinkType     = GitLinkType.Commit;
                }
                else if (ids[4] == "PullRequestId")
                {
                    IsGitLink     = true;
                    ProjectId     = Guid.Parse(ids[5]);
                    LinkType      = GitLinkType.PullRequest;
                    RepositoryID  = Guid.Parse(ids[6]);
                    PullRequestID = int.Parse(ids[7]);
                }
                //we don't handle the other cases as for now like 'Ref'links to branches
                //else
                //{
                //    throw new ArgumentException("Link Type not recognized!");
                //}
            }
        }
Esempio n. 2
0
        public static bool IsRelationHyperlinkToSourceWorkItem(IContext context, WorkItemRelation relation, int sourceId)
        {
            // only hyperlinks can contain the link to the source work item
            if (relation.Rel.Equals(Constants.Hyperlink, StringComparison.OrdinalIgnoreCase))
            {
                var hyperlinkToSourceWorkItem = context.WorkItemIdsUris[sourceId];

                var sourceParts = Regex.Split(hyperlinkToSourceWorkItem, "/_apis/wit/workitems/", RegexOptions.IgnoreCase);
                var targetParts = Regex.Split(relation.Url, "/_apis/wit/workitems/", RegexOptions.IgnoreCase);

                if (sourceParts.Length == 2 && targetParts.Length == 2)
                {
                    var sourceIdPart = sourceParts.Last();
                    var targetIdPart = targetParts.Last();

                    var sourceAccountPart = sourceParts.First().Split("/", StringSplitOptions.RemoveEmptyEntries);
                    var targetAccountPart = targetParts.First().Split("/", StringSplitOptions.RemoveEmptyEntries);

                    // url of the work item can contain project which we want to ignore since the url we generate does not include project
                    // and we just need to verify the ids are the same and the account are the same.
                    if (sourceAccountPart.Length > 1 &&
                        targetAccountPart.Length > 1 &&
                        string.Equals(sourceIdPart, targetIdPart, StringComparison.OrdinalIgnoreCase) &&
                        string.Equals(sourceAccountPart[1], targetAccountPart[1], StringComparison.OrdinalIgnoreCase))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public static JsonPatchOperation AddLink(this JsonPatchDocument source, string linkType, string targetUrl)
        {
            var relation = new WorkItemRelation()
            {
                Rel = linkType, Url = targetUrl
            };

            return(AddLink(source, relation));
        }
Esempio n. 4
0
 internal WorkItemRelationWrapper(WorkItemWrapper item, string type, string url, string comment)
 {
     _item     = item;
     _relation = new WorkItemRelation()
     {
         Rel        = type,
         Url        = url,
         Attributes = { { "comment", comment } }
     };
 }
Esempio n. 5
0
        public static JsonPatchOperation GetRelationAddOperation(WorkItemRelation relation)
        {
            JsonPatchOperation jsonPatchOperation = new JsonPatchOperation();

            jsonPatchOperation.Operation = Operation.Add;
            jsonPatchOperation.Path      = $"/{Constants.Relations}/-";
            jsonPatchOperation.Value     = relation;

            return(jsonPatchOperation);
        }
Esempio n. 6
0
        public static int GetItemId(this WorkItemRelation o)
        {
            int id = 0;

            if (!string.IsNullOrWhiteSpace(o.Url))
            {
                int.TryParse(o.Url.Split('/').Last(), out id);
            }
            return(id);
        }
        internal static WorkItemRelationWrapper GetInstance()
        {
            WorkItemRelation real = default(WorkItemRelation);

            RealInstanceFactory(ref real);
            WorkItemRelationWrapper instance = WorkItemRelationWrapper.GetWrapper(real);

            InstanceFactory(ref instance);
            return(instance);
        }
        public static JsonPatchOperation AddLink(this JsonPatchDocument source, WorkItemRelation relation)
        {
            var op = new JsonPatchOperation()
            {
                Operation = Operation.Add, Path = "/relations/-", Value = relation
            };

            source.Add(op);

            return(op);
        }
Esempio n. 9
0
 internal WorkItemRelationWrapper(string type, string url, string comment) : this(url)
 {
     _relation = new WorkItemRelation()
     {
         Rel        = type,
         Url        = url,
         Attributes = new Dictionary <string, object> {
             { "comment", comment }
         }
     };
 }
Esempio n. 10
0
 private bool IsRelationWorkItemLink(IMigrationContext migrationContext, WorkItemRelation relation)
 {
     if (migrationContext.ValidatedWorkItemLinkRelationTypes.Contains(relation.Rel))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Esempio n. 11
0
 public static string GetCommentFromAttributes(WorkItemRelation relation)
 {
     if (relation.Attributes != null && relation.Attributes.ContainsKeyIgnoringCase(Constants.RelationAttributeComment))
     {
         // get the key even if its letter case is different but it matches otherwise
         string commentKeyFromFields = relation.Attributes.GetKeyIgnoringCase(Constants.RelationAttributeComment);
         return(relation.Attributes[Constants.RelationAttributeComment].ToString());
     }
     else
     {
         return(string.Empty);
     }
 }
 private object GetIdFromAttributes(WorkItemRelation relation)
 {
     if (relation.Attributes != null && relation.Attributes.ContainsKeyIgnoringCase(Constants.RelationAttributeId))
     {
         // get the key even if its letter case is different but it matches otherwise
         string idKeyFromFields = relation.Attributes.GetKeyIgnoringCase(Constants.RelationAttributeId);
         return(relation.Attributes[idKeyFromFields]);
     }
     else
     {
         return(null);
     }
 }
        public async Task <IEnumerable <JsonPatchOperation> > Process(IMigrationContext migrationContext, IBatchMigrationContext batchContext, WorkItem sourceWorkItem, WorkItem targetWorkItem)
        {
            IList <JsonPatchOperation> jsonPatchOperations = new List <JsonPatchOperation>();

            if (sourceWorkItem.Relations == null)
            {
                return(jsonPatchOperations);
            }

            IEnumerable <WorkItemRelation> sourceAttachmentWorkItemRelations = GetAttachmentWorkItemRelations(sourceWorkItem.Relations);

            if (sourceAttachmentWorkItemRelations.Any())
            {
                foreach (WorkItemRelation sourceAttachmentWorkItemRelation in sourceAttachmentWorkItemRelations)
                {
                    WorkItemRelation targetAttachmentRelation = GetAttachmentIfExistsOnTarget(targetWorkItem, sourceAttachmentWorkItemRelation);

                    if (targetAttachmentRelation != null) // is on target
                    {
                        JsonPatchOperation attachmentAddOperation = MigrationHelpers.GetRelationAddOperation(targetAttachmentRelation);
                        jsonPatchOperations.Add(attachmentAddOperation);
                    }
                    else // is not on target
                    {
                        AttachmentLink attachmentLink = await UploadAttachmentFromSourceRelation(migrationContext, batchContext, sourceWorkItem, sourceAttachmentWorkItemRelation, migrationContext.Config.MaxAttachmentSize);

                        if (attachmentLink != null)
                        {
                            WorkItemRelation newAttachmentWorkItemRelation = new WorkItemRelation();
                            newAttachmentWorkItemRelation.Rel        = sourceAttachmentWorkItemRelation.Rel;
                            newAttachmentWorkItemRelation.Url        = attachmentLink.AttachmentReference.Url;
                            newAttachmentWorkItemRelation.Attributes = new Dictionary <string, object>();
                            newAttachmentWorkItemRelation.Attributes[Constants.RelationAttributeName]         = attachmentLink.FileName;
                            newAttachmentWorkItemRelation.Attributes[Constants.RelationAttributeResourceSize] = attachmentLink.ResourceSize;
                            newAttachmentWorkItemRelation.Attributes[Constants.RelationAttributeComment]      = attachmentLink.Comment;

                            JsonPatchOperation attachmentAddOperation = MigrationHelpers.GetRelationAddOperation(newAttachmentWorkItemRelation);
                            jsonPatchOperations.Add(attachmentAddOperation);
                        }
                    }
                }
            }

            return(jsonPatchOperations);
        }
        /// <summary>
        /// Deeps the copy.
        /// </summary>
        /// <param name="wir">The Work Item Relationship</param>
        /// <returns>A clone of the input work item relationship</returns>
        private static WorkItemRelation DeepCopy(this WorkItemRelation wir)
        {
            var newWorkItemRelation = new WorkItemRelation
            {
                Attributes = new Dictionary <string, object>(),
                Rel        = wir.Rel,
                Title      = wir.Title,
                Url        = wir.Url
            };

            if (wir.Attributes != null && wir.Attributes?.Count > 0)
            {
                foreach (var item in wir.Attributes)
                {
                    newWorkItemRelation.Attributes.Add(item.Key, item.Value);
                }
            }

            return(newWorkItemRelation);
        }
        public async Task <IEnumerable <JsonPatchOperation> > Process(IMigrationContext migrationContext, IBatchMigrationContext batchContext, WorkItem sourceWorkItem, WorkItem targetWorkItem)
        {
            IList <JsonPatchOperation>     jsonPatchOperations           = new List <JsonPatchOperation>();
            IEnumerable <WorkItemRelation> sourceGitCommitLinksRelations = GetGitLinksRelationsFromWorkItem(sourceWorkItem, Constants.RelationArtifactLink, migrationContext.Config.SourceConnection.Account);

            if (sourceGitCommitLinksRelations.Any())
            {
                foreach (WorkItemRelation sourceGitCommitLinkRelation in sourceGitCommitLinksRelations)
                {
                    string           adjustedUrl = ConvertGitCommitLinkToHyperLink(sourceWorkItem.Id.Value, sourceGitCommitLinkRelation.Url, migrationContext.Config.SourceConnection.Account);
                    WorkItemRelation targetGitCommitHyperlinkRelation = GetGitCommitHyperlinkIfExistsOnTarget(targetWorkItem, adjustedUrl);

                    if (targetGitCommitHyperlinkRelation != null) // is on target
                    {
                        JsonPatchOperation gitCommitHyperlinkAddOperation = MigrationHelpers.GetRelationAddOperation(targetGitCommitHyperlinkRelation);
                        jsonPatchOperations.Add(gitCommitHyperlinkAddOperation);
                    }
                    else // is not on target
                    {
                        string comment = string.Empty;
                        if (sourceGitCommitLinkRelation.Attributes.ContainsKey(Constants.RelationAttributeComment))
                        {
                            comment = $"{sourceGitCommitLinkRelation.Attributes[Constants.RelationAttributeComment]}";
                        }

                        string adjustedComment = $"{Constants.RelationAttributeGitCommitCommentValue}{comment}";

                        WorkItemRelation newGitCommitLinkRelation = new WorkItemRelation();
                        newGitCommitLinkRelation.Rel        = Constants.Hyperlink;
                        newGitCommitLinkRelation.Url        = adjustedUrl;
                        newGitCommitLinkRelation.Attributes = new Dictionary <string, object>();
                        newGitCommitLinkRelation.Attributes[Constants.RelationAttributeComment] = adjustedComment;

                        JsonPatchOperation gitCommitHyperlinkAddOperation = MigrationHelpers.GetRelationAddOperation(newGitCommitLinkRelation);
                        jsonPatchOperations.Add(gitCommitHyperlinkAddOperation);
                    }
                }
            }

            return(jsonPatchOperations);
        }
Esempio n. 16
0
        /// <summary>Gets the Guid of the related item.</summary>
        /// <param name="source">The source.</param>
        /// <returns>The Guid of the related item or 0 if it cannot be found.</returns>
        /// <remarks>
        /// The related Guid isn't available directly but has to be determined by parsing the URL. Only work items are supported right now.
        /// </remarks>
        public static Guid GetRelatedGuid(this WorkItemRelation source)
        {
            //Parse the URL, the Guid is the last value
            var url = source.Url;

            if (!String.IsNullOrEmpty(url))
            {
                //Skip to the last value
                var idStringIndex = url.LastIndexOf('/');
                if (idStringIndex >= 0)
                {
                    var idString = url.Substring(idStringIndex + 1);
                    if (Guid.TryParse(idString, out var guid))
                    {
                        return(guid);
                    }
                }
            }

            return(Guid.Empty);
        }
Esempio n. 17
0
        public async Task <IEnumerable <JsonPatchOperation> > Process(IMigrationContext migrationContext, IBatchMigrationContext batchContext, WorkItem sourceWorkItem, WorkItem targetWorkItem)
        {
            IList <JsonPatchOperation>     jsonPatchOperations = new List <JsonPatchOperation>();
            IEnumerable <WorkItemRelation> sourceRemoteLinks   = sourceWorkItem.Relations?.Where(r => RelationHelpers.IsRemoteLinkType(migrationContext, r.Rel));

            if (sourceRemoteLinks != null && sourceRemoteLinks.Any())
            {
                foreach (WorkItemRelation sourceRemoteLink in sourceRemoteLinks)
                {
                    string           url = ConvertRemoteLinkToHyperlink(sourceRemoteLink.Url);
                    WorkItemRelation targetRemoteLinkHyperlinkRelation = GetHyperlinkIfExistsOnTarget(targetWorkItem, url);

                    if (targetRemoteLinkHyperlinkRelation != null) // is on target
                    {
                        JsonPatchOperation remoteLinkHyperlinkAddOperation = MigrationHelpers.GetRelationAddOperation(targetRemoteLinkHyperlinkRelation);
                        jsonPatchOperations.Add(remoteLinkHyperlinkAddOperation);
                    }
                    else // is not on target
                    {
                        string comment = string.Empty;
                        if (sourceRemoteLink.Attributes.ContainsKey(Constants.RelationAttributeComment))
                        {
                            comment = $"{sourceRemoteLink.Attributes[Constants.RelationAttributeComment]}";
                        }

                        WorkItemRelation newRemoteLinkHyperlinkRelation = new WorkItemRelation();
                        newRemoteLinkHyperlinkRelation.Rel        = Constants.Hyperlink;
                        newRemoteLinkHyperlinkRelation.Url        = url;
                        newRemoteLinkHyperlinkRelation.Attributes = new Dictionary <string, object>();
                        newRemoteLinkHyperlinkRelation.Attributes[Constants.RelationAttributeComment] = comment;

                        JsonPatchOperation remoteLinkHyperlinkAddOperation = MigrationHelpers.GetRelationAddOperation(newRemoteLinkHyperlinkRelation);
                        jsonPatchOperations.Add(remoteLinkHyperlinkAddOperation);
                    }
                }
            }

            return(jsonPatchOperations);
        }
Esempio n. 18
0
        /// <summary>Gets the ID of the related item.</summary>
        /// <param name="source">The source.</param>
        /// <returns>The ID of the related item or 0 if it cannot be found.</returns>
        /// <remarks>
        /// The related ID isn't available directly but has to be determined by parsing the URL. Only work items are supported right now.
        /// </remarks>
        public static int GetRelatedId(this WorkItemRelation source)
        {
            //Parse the URL, the ID is the last value
            var url = source.Url;

            if (!String.IsNullOrEmpty(url))
            {
                //Skip to the last value
                var idStringIndex = url.LastIndexOf('/');
                if (idStringIndex >= 0)
                {
                    var idString = url.Substring(idStringIndex + 1);
                    if (Int32.TryParse(idString, out var id))
                    {
                        return(id);
                    }
                }
                ;
            }
            ;

            return(0);
        }
        private async Task MigrateWorkItemGitCommitLinkAsync(MigrationContext context, IEnumerable <WorkItemRelation> relations, WorkItem targetItem, CancellationToken cancellationToken)
        {
            var   doc = new JsonPatchDocument();
            var   targetRepositories = Settings.Repositories.ToDictionary(x => x.Source, x => x.Target);
            Regex regexSplitGitUrl   = new Regex(@"^vstfs:\/\/\/git\/commit\/(?<projectId>[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})\/(?<repositoryId>[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12})\/(?<commitId>[a-f0-9]{40})$", RegexOptions.IgnoreCase);

            var sourceGitCommitRelations = relations.Where(r => r.IsGitCommit());

            foreach (var sourceGitCommit in sourceGitCommitRelations)
            {
                var gitCommitUrl = Uri.UnescapeDataString(sourceGitCommit.Url);
                var match        = regexSplitGitUrl.Match(gitCommitUrl);

                if (match.Success && targetRepositories.TryGetValue(match.Groups["repositoryId"].Value, out string targetRepositoryId))
                {
                    var targetProject = await context.GetTargetProjectAsync(cancellationToken);

                    var targetgitCommitUrl           = regexSplitGitUrl.Replace(gitCommitUrl, m => $"Vstfs:///Git/Commit/{targetProject.Id}/{targetRepositoryId}/{m.Groups["commitId"].Value}");
                    WorkItemRelation targetGitCommit = new WorkItemRelation
                    {
                        Rel        = sourceGitCommit.Rel,
                        Attributes = sourceGitCommit.Attributes,
                        Url        = targetgitCommitUrl
                    };

                    Logger.Debug($"Adding Git commit link {targetgitCommitUrl}");
                    doc.AddLink(targetGitCommit);
                }
            }

            //If we have made any changes then update the target
            if (doc.Any())
            {
                await context.TargetService.UpdateWorkItemUnrestrictedAsync(targetItem, doc, cancellationToken).ConfigureAwait(false);
            }
        }
Esempio n. 20
0
        private void ProcessUpdatedSourceWorkItem(WorkItem targetWorkItem, WorkItemMigrationState workItemMigrationState, WorkItemRelation hyperlinkToSourceRelation)
        {
            //get the source rev from the revision dictionary - populated by PostValidateWorkitems
            int    sourceId  = workItemMigrationState.SourceId;
            int    sourceRev = ValidationContext.SourceWorkItemRevision[sourceId];
            string sourceUrl = ValidationContext.WorkItemIdsUris[sourceId];
            int    targetRev = GetRev(this.ValidationContext, targetWorkItem, sourceId, hyperlinkToSourceRelation);

            if (IsDifferenceInRevNumbers(sourceId, targetWorkItem, hyperlinkToSourceRelation, targetRev))
            {
                Logger.LogInformation(LogDestination.File, $"Source workItem {sourceId} Rev {sourceRev} Target workitem {targetWorkItem.Id} Rev {targetRev}");
                this.sourceWorkItemIdsThatHaveBeenUpdated.Add(sourceId);
                workItemMigrationState.Requirement |= WorkItemMigrationState.RequirementForExisting.UpdatePhase1;
                workItemMigrationState.Requirement |= WorkItemMigrationState.RequirementForExisting.UpdatePhase2;
            }
            else if (IsPhase2UpdateRequired(workItemMigrationState, targetWorkItem))
            {
                workItemMigrationState.Requirement |= WorkItemMigrationState.RequirementForExisting.UpdatePhase2;
            }
            else
            {
                workItemMigrationState.Requirement |= WorkItemMigrationState.RequirementForExisting.None;
            }
        }
Esempio n. 21
0
        private void StoreTargetRelationPhaseStatusHyperlinkDataFromWorkItem(WorkItemMigrationState workItemMigrationState, WorkItemRelation hyperlinkToSourceRelation)
        {
            var targetAttributes = hyperlinkToSourceRelation.Attributes;

            targetAttributes.TryGetValue(Constants.RelationAttributeComment, out string targetRelationPhaseStatus);

            workItemMigrationState.RevAndPhaseStatus = new RevAndPhaseStatus(targetRelationPhaseStatus);
        }
        private WorkItemRelation GetAttachmentIfExistsOnTarget(WorkItem targetWorkItem, WorkItemRelation sourceRelation)
        {
            if (targetWorkItem.Relations == null)
            {
                return(null);
            }

            foreach (WorkItemRelation targetRelation in targetWorkItem.Relations)
            {
                if (targetRelation.Rel.Equals(Constants.AttachedFile) && targetRelation.Url.Equals(sourceRelation.Url, StringComparison.OrdinalIgnoreCase))
                {
                    return(targetRelation);
                }
            }

            return(null);
        }
        Staging FillSyncAllStagingTable(SystemToDbViewModel syncAllViewModel, WorkItem workItem, int systemId)
        {
            Staging staging = new Staging
            {
                RecordDateCreated = DateTime.Now,
                SystemId          = systemId,
                ChangedFields     = "all",
                RecordDateUpdated = DateTime.Now,
                RecordState       = RecordStateConst.New,
                WebHookEvent      = "syncAll"
            };

            if (workItem.Fields.ContainsKey("System.TeamProject"))
            {
                staging.ProjectId   = (string)workItem.Fields["System.TeamProject"];
                staging.ProjectKey  = (string)workItem.Fields["System.TeamProject"];
                staging.ProjectName = (string)workItem.Fields["System.TeamProject"];
            }
            staging.IssueId  = workItem.Id?.ToString();
            staging.IssueKey = workItem.Id?.ToString();
            if (workItem.Fields.ContainsKey("System.WorkItemType"))
            {
                staging.IssueTypeId   = workItem.Fields["System.WorkItemType"].ToString();
                staging.IssueTypeName = workItem.Fields["System.WorkItemType"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.Title"))
            {
                staging.IssueName = workItem.Fields["System.Title"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.IterationId"))
            {
                staging.ParentVersionId = workItem.Fields["System.IterationId"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.IterationLevel2"))
            {
                staging.ParentVersionName = workItem.Fields["System.IterationLevel2"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.AssignedTo"))
            {
                if (workItem.Fields["System.AssignedTo"] != null)
                {
                    staging.Assignee = workItem.Fields["System.AssignedTo"].ToString()
                                       .Substring(workItem.Fields["System.AssignedTo"].ToString()
                                                  .IndexOf("<", StringComparison.Ordinal)).Trim('<', '>');
                }
            }
            if (workItem.Relations != null)
            {
                WorkItemRelation relationCrt = workItem.Relations
                                               .FirstOrDefault(x => x.Rel == "System.LinkTypes.Hierarchy-Reverse");
                if (relationCrt != null)
                {
                    string  parentKey     = relationCrt.Url.Substring(relationCrt.Url.LastIndexOf("/", StringComparison.Ordinal) + 1);
                    Staging parentStaging = syncAllViewModel.StagingsToInsert.FirstOrDefault(x => x.IssueKey == parentKey);
                    if (parentStaging != null)
                    {
                        if (parentStaging.IssueTypeName == "Epic")
                        {
                            staging.ParentEpicId  = parentKey;
                            staging.ParentEpicKey = parentKey;
                        }
                        else
                        {
                            staging.ParentIssueId  = parentKey;
                            staging.ParentIssueKey = parentKey;
                        }
                    }
                }
                else
                {
                    staging.ParentIssueId  = null;
                    staging.ParentIssueKey = null;
                }
            }

            syncAllViewModel.StagingsToInsert.Add(staging);
            return(staging);
        }
        private async Task <AttachmentLink> UploadAttachmentFromSourceRelation(IMigrationContext migrationContext, IBatchMigrationContext batchContext, WorkItem sourceWorkItem, WorkItemRelation sourceRelation, int maxAttachmentSize)
        {
            //Attachments are of type Rel = "AttachedFile"
            if (sourceRelation.Rel == Constants.AttachedFile)
            {
                string filename     = null;
                string comment      = null;
                long   resourceSize = 0;
                //get the file name and comment
                if (sourceRelation.Attributes.ContainsKey(Constants.RelationAttributeName))
                {
                    filename = sourceRelation.Attributes[Constants.RelationAttributeName].ToString();
                }
                if (sourceRelation.Attributes.ContainsKey(Constants.RelationAttributeComment))
                {
                    comment = sourceRelation.Attributes[Constants.RelationAttributeComment].ToString();
                }
                //get the guid from the url
                Guid attachmentId;
                if (Guid.TryParse(sourceRelation.Url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(), out attachmentId))
                {
                    Stream stream = null;
                    try
                    {
                        Logger.LogTrace(LogDestination.File, $"Reading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                        stream = await WorkItemTrackingHelpers.GetAttachmentAsync(migrationContext.SourceClient.WorkItemTrackingHttpClient, attachmentId);

                        Logger.LogTrace(LogDestination.File, $"Completed reading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                    }
                    catch (Exception e)
                    {
                        Logger.LogError(LogDestination.File, e, $"Unable to download attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                        ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentDownloadError, batchContext.WorkItemMigrationState);
                        return(null);
                    }

                    AttachmentReference aRef = null;
                    using (MemoryStream memstream = new MemoryStream())
                    {
                        using (stream)
                        {
                            try
                            {
                                Logger.LogTrace(LogDestination.File, $"Downloading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                                await ClientHelpers.CopyStreamAsync(stream, memstream);

                                Logger.LogTrace(LogDestination.File, $"Completed downloading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                            }
                            catch (Exception e)
                            {
                                Logger.LogError(LogDestination.File, e, $"Unable to read downloaded attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                                ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentDownloadError, batchContext.WorkItemMigrationState);
                                return(null);
                            }
                        }

                        resourceSize = memstream.Length;
                        if (resourceSize > maxAttachmentSize)
                        {
                            Logger.LogWarning(LogDestination.File, $"Attachment of source work item with id {sourceWorkItem.Id} and url {sourceRelation.Url} exceeded the maximum attachment size of {maxAttachmentSize} bytes." +
                                              $" Skipping creating the attachment in target account.");
                            return(null);
                        }
                        memstream.Position = 0;
                        //upload the attachment to the target
                        try
                        {
                            Logger.LogTrace(LogDestination.File, $"Uploading attachment {filename} of {resourceSize} bytes for source work item {sourceWorkItem.Id} from the source account");
                            aRef = await WorkItemTrackingHelpers.CreateAttachmentChunkedAsync(migrationContext.TargetClient.WorkItemTrackingHttpClient, migrationContext.TargetClient.Connection, memstream, migrationContext.Config.AttachmentUploadChunkSize);

                            Logger.LogTrace(LogDestination.File, $"Completed uploading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
                        }
                        catch (Exception e)
                        {
                            Logger.LogError(LogDestination.File, e, $"Unable to upload attachment {filename} for source work item {sourceWorkItem.Id} to the target account");
                            ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentUploadError, batchContext.WorkItemMigrationState);
                        }
                    }
                    if (aRef != null)
                    {
                        return(new AttachmentLink(filename, aRef, resourceSize, comment));
                    }
                }
                else
                {
                    Logger.LogError(LogDestination.File, $"Attachment link is incorrect for {sourceWorkItem.Id} {sourceRelation.Url}. Skipping creating the attachment in target account.");
                    ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentUploadError, batchContext.WorkItemMigrationState);
                }
            }

            return(null);
        }
 private bool IsRelationAttachedFile(WorkItemRelation relation)
 {
     return(relation.Rel.Equals(Constants.AttachedFile, StringComparison.OrdinalIgnoreCase));
 }
        Master FillSyncAllMasterTable(SystemToDbViewModel syncAllViewModel, WorkItem workItem, int systemId)
        {
            Master master = new Master
            {
                RecordDateCreated = DateTime.Now,
                SystemId          = systemId,
                RecordDateUpdated = DateTime.Now
            };


            if (workItem.Fields.ContainsKey("System.TeamProject"))
            {
                master.ProjectId   = (string)workItem.Fields["System.TeamProject"];
                master.ProjectKey  = (string)workItem.Fields["System.TeamProject"];
                master.ProjectName = (string)workItem.Fields["System.TeamProject"];
            }
            master.IssueId  = workItem.Id?.ToString();
            master.IssueKey = workItem.Id?.ToString();
            if (workItem.Fields.ContainsKey("System.WorkItemType"))
            {
                master.IssueTypeId   = workItem.Fields["System.WorkItemType"].ToString();
                master.IssueTypeName = workItem.Fields["System.WorkItemType"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.Title"))
            {
                master.IssueName = workItem.Fields["System.Title"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.IterationId"))
            {
                master.ParentVersionId = workItem.Fields["System.IterationId"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.IterationLevel2"))
            {
                master.ParentVersionName = workItem.Fields["System.IterationLevel2"].ToString();
            }
            if (workItem.Fields.ContainsKey("System.AssignedTo"))
            {
                if (workItem.Fields["System.AssignedTo"] != null)
                {
                    master.Assignee = workItem.Fields["System.AssignedTo"].ToString()
                                      .Substring(workItem.Fields["System.AssignedTo"].ToString()
                                                 .IndexOf("<", StringComparison.Ordinal)).Trim('<', '>');
                }
            }
            if (workItem.Relations != null)
            {
                WorkItemRelation relationCrt = workItem.Relations
                                               .FirstOrDefault(x => x.Rel == "System.LinkTypes.Hierarchy-Reverse");
                if (relationCrt != null)
                {
                    if (workItem.Fields["System.WorkItemType"].ToString().ToLower().Equals("feature"))
                    {
                        master.ParentEpicId  = relationCrt.Url.Substring(relationCrt.Url.LastIndexOf("/", StringComparison.Ordinal) + 1);
                        master.ParentEpicKey = relationCrt.Url.Substring(relationCrt.Url.LastIndexOf("/", StringComparison.Ordinal) + 1);
                    }
                    else
                    {
                        master.ParentIssueId  = relationCrt.Url.Substring(relationCrt.Url.LastIndexOf("/", StringComparison.Ordinal) + 1);
                        master.ParentIssueKey = relationCrt.Url.Substring(relationCrt.Url.LastIndexOf("/", StringComparison.Ordinal) + 1);
                    }
                }
                else
                {
                    master.ParentIssueId  = null;
                    master.ParentIssueKey = null;
                }
            }

            syncAllViewModel.MastersToInsert.Add(master);
            return(master);
        }
Esempio n. 27
0
 internal WorkItemRelationWrapper(WorkItemRelation relation) : this(relation.Url)
 {
     _relation = relation;
 }
Esempio n. 28
0
        private bool IsDifferenceInRevNumbers(int sourceWorkItemId, WorkItem targetWorkItem, WorkItemRelation hyperlinkToSourceRelation, int targetRev)
        {
            int sourceRev        = ValidationContext.SourceWorkItemRevision[sourceWorkItemId];
            int targetWorkItemId = targetWorkItem.Id.Value;

            return(sourceRev != targetRev);
        }
Esempio n. 29
0
        public async Task <IActionResult> Post([FromBody] JObject payload)
        {
            PayloadViewModel vm = BuildPayloadViewModel(payload);

            //make sure pat is not empty, if it is, pull from appsettings
            vm.pat = _appSettings.Value.PersonalAccessToken;

            //if the event type is something other the updated, then lets just return an ok
            if (vm.eventType != "workitem.updated")
            {
                return(new OkResult());
            }

            // create our azure devops connection
            Uri baseUri = new Uri("https://dev.azure.com/" + vm.organization);

            VssCredentials clientCredentials = new VssCredentials(new VssBasicCredential("username", vm.pat));
            VssConnection  vssConnection     = new VssConnection(baseUri, clientCredentials);

            // load the work item posted
            WorkItem workItem = await _workItemRepo.GetWorkItem(vssConnection, vm.workItemId);

            // this should never happen, but if we can't load the work item from the id, then exit with error
            if (workItem == null)
            {
                return(new StandardResponseObjectResult("Error loading workitem '" + vm.workItemId + "'", StatusCodes.Status500InternalServerError));
            }

            // get the related parent
            WorkItemRelation parentRelation = workItem.Relations.Where <WorkItemRelation>(x => x.Rel.Equals("System.LinkTypes.Hierarchy-Reverse")).FirstOrDefault();

            // if we don't have any parents to worry about, then just abort
            if (parentRelation == null)
            {
                return(new OkResult());
            }

            Int32    parentId       = _helper.GetWorkItemIdFromUrl(parentRelation.Url);
            WorkItem parentWorkItem = await _workItemRepo.GetWorkItem(vssConnection, parentId);

            if (parentWorkItem == null)
            {
                return(new StandardResponseObjectResult("Error loading parent work item '" + parentId.ToString() + "'", StatusCodes.Status500InternalServerError));
            }

            string parentState = parentWorkItem.Fields["System.State"] == null ? string.Empty : parentWorkItem.Fields["System.State"].ToString();

            // load rules for updated work item
            RulesModel rulesModel = _rulesRepo.ListRules(vm.workItemType);

            //loop through each rule
            foreach (var rule in rulesModel.Rules)
            {
                if (rule.IfChildState.Equals(vm.state))
                {
                    if (!rule.AllChildren)
                    {
                        if (!rule.NotParentStates.Contains(parentState))
                        {
                            await _workItemRepo.UpdateWorkItemState(vssConnection, parentWorkItem, rule.SetParentStateTo);

                            return(new OkResult());
                        }
                    }
                    else
                    {
                        // get a list of all the child items to see if they are all closed or not
                        List <WorkItem> childWorkItems = await _workItemRepo.ListChildWorkItemsForParent(vssConnection, parentWorkItem);

                        // check to see if any of the child items are not closed, if so, we will get a count > 0
                        int count = childWorkItems.Where(x => !x.Fields["System.State"].ToString().Equals(rule.IfChildState)).ToList().Count;

                        if (count.Equals(0))
                        {
                            await _workItemRepo.UpdateWorkItemState(vssConnection, parentWorkItem, rule.SetParentStateTo);
                        }

                        return(new OkResult());
                    }
                }
            }

            return(new StandardResponseObjectResult("success", StatusCodes.Status200OK));
        }
Esempio n. 30
0
        private int GetRev(IValidationContext context, WorkItem targetWorkItem, int sourceWorkItemId, WorkItemRelation hyperlinkToSourceRelation)
        {
            var targetAttributes = hyperlinkToSourceRelation.Attributes;

            targetAttributes.TryGetValue(Constants.RelationAttributeComment, out string targetRelationPhaseStatus);

            string revNumberString = targetRelationPhaseStatus.SplitBySemicolonToHashSet().First();

            return(Convert.ToInt32(revNumberString));
        }