public void AddToListInListInvalidPositionTooLarge()
        {
            var doc = new SimpleDTOWithNestedDTO()
            {
                ListOfSimpleDTO = new List<SimpleDTO>()
                {
                     new SimpleDTO()
                     {
                        IntegerList = new List<int>() { 1, 2, 3 }
                     }
                }
            };
            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("ListOfSimpleDTO/20/IntegerList/0", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "The property at path '/ListOfSimpleDTO/20/IntegerList/0' could not be added.",
                exception.Message);
        }
        public void Add_InvalidPath_ThrowsJsonPatchParseException()
        {
            //Arrange
            var patchDocument = new JsonPatchDocument<SimpleEntity>();

            //Act
            patchDocument.Add("FooMissing", "bar");
        }
示例#3
0
        public async Task CreateAServiceOnAkamai_UsingDefaults()
        {
            Trace.WriteLine("Looking for a CDN flavor provided by Akamai...");
            var flavors = await _cdnService.ListFlavorsAsync();
            var flavor = flavors.FirstOrDefault(x => x.Providers.Any(p => string.Equals(p.Name, "Akamai", StringComparison.OrdinalIgnoreCase)));
            Assert.NotNull(flavor);
            var akamaiFlavor = flavor.Id;
            Trace.WriteLine(string.Format("Found the {0} flavor", akamaiFlavor));

            Trace.WriteLine("Creating a CDN service using defaults for anything I can omit...");
            var domains = new[] {new ServiceDomain("mirror.example.com")};
            var origins = new[] {new ServiceOrigin("example.com")};
            var serviceDefinition = new ServiceDefinition("ci-test", akamaiFlavor, domains, origins);
            var serviceId = await _cdnService.CreateServiceAsync(serviceDefinition);
            Trace.WriteLine(string.Format("Service was created: {0}", serviceId));

            try
            {
                Trace.WriteLine("Waiting for the service to be deployed...");
                var service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => Trace.WriteLine("...")));

                Trace.WriteLine("Verifying service matches the requested definition...");
                Assert.Equal("ci-test", service.Name);
                Assert.Equal(serviceDefinition.FlavorId, service.FlavorId);

                Assert.Equal(serviceDefinition.Origins.Count, service.Origins.Count());
                Assert.Equal(serviceDefinition.Origins.First().Origin, service.Origins.First().Origin);

                Assert.Equal(serviceDefinition.Domains.Count, service.Domains.Count());
                Assert.Equal(serviceDefinition.Domains.First().Domain, service.Domains.First().Domain);

                Trace.WriteLine("Updating the service...");
                var patch = new JsonPatchDocument<ServiceDefinition>();
                patch.Replace(x => x.Name, "ci-test2");
                var intranetOnly = new ServiceRestriction("intranet", new[] {new ServiceRestrictionRule("intranet", "intranet.example.com")});
                patch.Add(x => x.Restrictions, intranetOnly, 0);
                await _cdnService.UpdateServiceAsync(serviceId, patch);

                Trace.WriteLine("Waiting for the service changes to be deployed...");
                service = await _cdnService.WaitForServiceDeployedAsync(serviceId, progress: new Progress<bool>(x => Trace.WriteLine("...")));

                Trace.WriteLine("Verifying service matches updated definition...");
                Assert.Equal("ci-test2", service.Name);
                Assert.Equal(JsonConvert.SerializeObject(intranetOnly), JsonConvert.SerializeObject(service.Restrictions.First()));

                Trace.WriteLine("Purging all assets on service");
                await _cdnService.PurgeCachedAssetsAsync(serviceId);
            }
            finally
            {
                Trace.WriteLine("Cleaning up any test data...");

                Trace.WriteLine("Removing the service...");
                _cdnService.DeleteService(serviceId);
                _cdnService.WaitForServiceDeleted(serviceId);
                Trace.WriteLine("The service was cleaned up sucessfully.");
            }
        }
示例#4
0
 public void InvalidPathWithDotShouldThrowException()
 {
     JsonPatchDocument patchDoc = new JsonPatchDocument();
     var exception = Assert.Throws<JsonPatchException>(() =>
     {
         patchDoc.Add("NewInt.Test", 1);
     });
     Assert.Equal(
        "The provided string 'NewInt.Test' is an invalid path.",
         exception.Message);
 }
        public void Add_ValidPath_OperationAdded()
        {
            //Arrange
            var patchDocument = new JsonPatchDocument<SimpleEntity>();

            //Act
            patchDocument.Add("Foo", "bar");

            //Assert
            Assert.AreEqual(1, patchDocument.Operations.Count);
            Assert.AreEqual(JsonPatchOperationType.add, patchDocument.Operations.Single().Operation);
        }
示例#6
0
        public void AddToList()
        {
            var doc = new SimpleDTO()
            {
                IntegerList = new List<int>() { 1, 2, 3 }
            };

            // create patch
            JsonPatchDocument<SimpleDTO> patchDoc = new JsonPatchDocument<SimpleDTO>();
            patchDoc.Add<int>(o => o.IntegerList, 4, 0);

            patchDoc.ApplyTo(doc);

            Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.IntegerList);
        }
示例#7
0
        public void AddNewProperty()
        {
            dynamic obj = new ExpandoObject();
            obj.Test = 1;

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("NewInt", 1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(obj);

            Assert.Equal(1, obj.NewInt);
            Assert.Equal(1, obj.Test);
        }
示例#8
0
        public void AddResultsShouldReplace()
        {
            var doc = new SimpleDTO()
            {
                StringProperty = "A"
            };

            // create patch
            JsonPatchDocument<SimpleDTO> patchDoc = new JsonPatchDocument<SimpleDTO>();
            patchDoc.Add<string>(o => o.StringProperty, "B");

            patchDoc.ApplyTo(doc);

            var s = new Operations.Operation();

            Assert.Equal("B", doc.StringProperty);
          
        }
示例#9
0
        public void AddResultsShouldReplace()
        {
            // Arrange
            var doc = new SimpleDTO()
            {
                StringProperty = "A"
            };

            // create patch
            var patchDoc = new JsonPatchDocument<SimpleDTO>();
            patchDoc.Add<string>(o => o.StringProperty, "B");

            // Act
            patchDoc.ApplyTo(doc);

            // Assert
            Assert.Equal("B", doc.StringProperty);
        }
示例#10
0
        public void AddResultsShouldReplaceWithSerialization()
        {
            var doc = new SimpleDTO()
            {
                StringProperty = "A"
            };

            // create patch
            JsonPatchDocument<SimpleDTO> patchDoc = new JsonPatchDocument<SimpleDTO>();
            patchDoc.Add<string>(o => o.StringProperty, "B");


            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTO>>(serialized);
            
            deserialized.ApplyTo(doc);

            Assert.Equal("B", doc.StringProperty);

        }
        public void AddToListNegativePosition()
        {
            var doc = new SimpleDTO()
            {
                IntegerList = new List<int>() { 1, 2, 3 }
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("IntegerList/-1", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
               "For operation 'add' on array property at path '/IntegerList/-1', the index is negative.",
                exception.Message);
        }
示例#12
0
        public void AddNewPropertyShouldFailIfRootIsNotAnExpandoObject()
        {
            dynamic doc = new
            {
                Test = 1
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("NewInt", 1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "The property at path '/NewInt' could not be added.",
                exception.Message);
        }
示例#13
0
        public void AddToListInList()
        {
            var doc = new SimpleDTOWithNestedDTO()
            {
                ListOfSimpleDTO = new List<SimpleDTO>()
                {
                     new SimpleDTO()
                     {
                         IntegerList = new List<int>() { 1, 2, 3 }
                     }
                }
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("ListOfSimpleDTO/0/IntegerList/0", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);
            Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.ListOfSimpleDTO[0].IntegerList);
        }
示例#14
0
        public void AddResultsInReplaceWithSerialization()
        {
            // Arrange
            var doc = new SimpleDTOWithNestedDTO()
            {
                SimpleDTO = new SimpleDTO()
                {
                    StringProperty = "A"
                }
            };

            // create patch
            var patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
            patchDoc.Add<string>(o => o.SimpleDTO.StringProperty, "B");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTOWithNestedDTO>>(serialized);

            // Act
            deserialized.ApplyTo(doc);

            // Assert
            Assert.Equal("B", doc.SimpleDTO.StringProperty);
        }
示例#15
0
        public void AddNewPropertyToAnonymousObjectShouldFail()
        {
            dynamic doc = new
            {
                Test = 1
            };

            dynamic valueToAdd = new { IntValue = 1, StringValue = "test", GuidValue = Guid.NewGuid() };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("ComplexProperty", valueToAdd);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "The property at path '/ComplexProperty' could not be added.",
                exception.Message);
        }
        public void AddToListInvalidPositionTooSmallWithSerialization()
        {

            var doc = new SimpleDTOWithNestedDTO()
            {
                SimpleDTO = new SimpleDTO()
                {
                    IntegerList = new List<int>() { 1, 2, 3 }
                }
            };


            // create patch
            JsonPatchDocument<SimpleDTOWithNestedDTO> patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
            patchDoc.Add<int>(o => o.SimpleDTO.IntegerList, 4, -1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTOWithNestedDTO>>(serialized);



            Assert.Throws<JsonPatchException>(() => { deserialized.ApplyTo(doc); });

        }
示例#17
0
        public JsonPatchDocument GetPatches(V1Deployment deployment)
        {
            if (deployment is null)
            {
                throw new ArgumentNullException(nameof(deployment));
            }

            logger.LogInformation(
                "Got deployment named {DeploymentName} in namespace {Namespace}.",
                deployment.Metadata.Name,
                deployment.Metadata.NamespaceProperty ?? "default");
            logger.LogInformation("Got template: {}", Newtonsoft.Json.JsonConvert.SerializeObject(deployment.Spec.Template));

            foreach (var annotation in deployment.Spec.Template.Metadata.Annotations)
            {
                logger.LogInformation("Got annotation {AnnotationKey}={AnnotationValue}", annotation.Key, annotation.Value);
            }

            var patches = new JsonPatchDocument();
            var hasLogOverrideEnabled = false;

            if (deployment.Spec.Template.Metadata.Annotations.TryGetValue("opulence.dotnet.io/enablelogoverride", out var value) &&
                string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase))
            {
                hasLogOverrideEnabled = true;
            }

            logger.LogInformation("Deployment {DeploymentName} has opulence.dotnet.io/enablelogoverride = {LogOverrideEnabled}.", deployment.Metadata.Name, hasLogOverrideEnabled);
            if (!hasLogOverrideEnabled)
            {
                return(patches);
            }

            var foundVolume = false;
            var volumes     = deployment.Spec.Template.Spec?.Volumes ?? Array.Empty <V1Volume>();

            for (var i = 0; i < volumes.Count; i++)
            {
                var volume = volumes[i];
                if (volume.Name == VolumeName)
                {
                    foundVolume = true;
                    logger.LogInformation("Deployment already has volume {VolumeName}.", VolumeName);
                    break;
                }
            }

            if (!foundVolume)
            {
                logger.LogInformation("Adding volume {VolumnName}.", VolumeName);

                if (volumes.Count == 0)
                {
                    patches.Add("/spec/template/spec/volumes", Array.Empty <object>());
                }

                patches.Add("/spec/template/spec/volumes/-", new V1Volume()
                {
                    Name      = VolumeName,
                    ConfigMap = new V1ConfigMapVolumeSource()
                    {
                        Name     = ConfigMapName,
                        Optional = true,
                        Items    = new List <V1KeyToPath>()
                        {
                            new V1KeyToPath()
                            {
                                Key  = $"{deployment.Metadata.Name}.json",
                                Path = $"config.json",
                            }
                        },
                    },
                });
            }

            var containers = deployment.Spec.Template.Spec.Containers;

            for (var i = 0; i < containers.Count; i++)
            {
                var container = containers[i];

                var foundMount = false;
                container.VolumeMounts ??= new List <V1VolumeMount>();
                for (var j = 0; j < container.VolumeMounts.Count; i++)
                {
                    var mount = container.VolumeMounts[j];
                    if (mount.Name == VolumeName)
                    {
                        foundMount = true;
                        logger.LogInformation("Found volume mount {VolumneName} for container {ContainerName}.");
                        break;
                    }
                }

                if (foundMount)
                {
                    continue;
                }

                logger.LogInformation("Adding volumne mount {VolumeName} to {ContainerName}.", "opulence-logoverride", container.Name);

                if (container.VolumeMounts.Count == 0)
                {
                    patches.Add($"/spec/template/spec/containers/{i}/volumeMounts", Array.Empty <object>());
                }

                patches.Add($"/spec/template/spec/containers/{i}/volumeMounts/-", new V1VolumeMount()
                {
                    Name             = "opulence-logoverride",
                    MountPath        = "/var/opulence.dotnet.io/logoverride",
                    ReadOnlyProperty = true,
                });
            }

            return(patches);
        }
示例#18
0
        // Returns workitem URL.
        public static string CreateSupportTicket(SupportTicket ticket)
        {
            VssConnection connection             = new VssConnection(new Uri(collectionUri), new VssBasicCredential("", pat));
            WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            //add fields and their values to your patch document
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = "Support ticket by user: "******"/fields/System.Description",
                Value     = ticket.Description
            }
                );
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/agile2.Area",
                Value     = ticket.AreaOfProblem
            }
                );
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/agile2.Category",
                Value     = ticket.CategoryOfProblem
            }
                );
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/agile2.UserAccount",
                Value     = ticket.AccountUrl
            }
                );
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/agile2.Useremail",
                Value     = ticket.EmailAddress
            }
                );

            try
            {
                WorkItem result = witClient.CreateWorkItemAsync(patchDocument, project, "SupportTicket").Result;
                return(collectionUri + project + "/_workitems/edit/" + result.Id);
            }
            catch (AggregateException ex)
            {
                Console.WriteLine("Error creating the support ticket: {0}", ex.InnerException.Message);
                return(null);
            }
        }
示例#19
0
        public async Task <WorkItemModel> CreateWorkitem(CreateWorkItem workItem)
        {
            WorkItemModel        workItemModel = new WorkItemModel();
            DevOpsConnectionPool poolObj       = _builderPool.Get();

            try
            {
                List <Params> ListParams = new List <Params>();
                //VssCredentials creds = new VssBasicCredential(string.Empty, personalaccesstoken);
                //VssConnection connection = new VssConnection(new Uri(c_collectionUri), creds);
                //ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();

                var workItemTrackingClient = poolObj.VssConnection.GetClient <WorkItemTrackingHttpClient>();

                JsonPatchDocument patchDocument = new JsonPatchDocument();
                Fields            field         = null;

                string title       = $"error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}";
                string bugtest     = $"error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}. \n see attachment file for full error log.";
                string description = $"error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}. \n see attachment file for full error log.";

                switch (workItem.type.ToLower())
                {
                case "bug":
                    field = new Fields()
                    {
                        AssignedTo = workItem.assignedTo,
                        BugText    = bugtest, //workItem.bugtest,
                        Priority   = "2",
                        Title      = title,   //workItem.title,
                        Severity   = "2 - High"
                    };
                    ListParams.AddRange(GetBugFields(field));
                    break;

                default:    //Issue,Feature,Task
                    field = new Fields()
                    {
                        AssignedTo  = workItem.assignedTo,
                        Description = description,    //workItem.description,
                        Priority    = "2",
                        Title       = title,
                        Severity    = "2 - High"
                    };
                    ListParams.AddRange(GetTaskIssueFeatureFields(field));
                    break;
                }

                foreach (var item in ListParams)
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                        Path      = item.Path,
                        Value     = item.Value,
                    }
                        );
                }

                var workitem = await workItemTrackingClient.CreateWorkItemAsync(patchDocument, workItem.projectid, workItem.type);

                if (workitem != null)
                {
                    workItemModel.Id  = workitem.Id.Value;
                    workItemModel.url = workitem.Url;
                }
            }
            catch (Exception)
            {
            }
            finally
            {
                _builderPool.Return(poolObj);
            }
            return(workItemModel);
        }
        public static bool EditProduct(Product product)
        {
            var    categories         = _a.GetResourceAsync <List <Category> >(Api.CategoryApi).Result;
            bool   edited             = false;
            string uriString          = $"{Api.ProductApi}/{product.Id}";
            Uri    patchApiForProduct = new Uri(uriString);

            Clear();
            WriteLine(
                "Press Esc to when done editing. To add or remove a category add the id.".PadRight(Program.WindowWidth,
                                                                                                   '#'));
            WriteLine("".PadRight(Program.WindowWidth, '#'));


            Coordinates productPropertiesCoordinates =
                new Coordinates(ContentCursorPosLeft - 3, ContentCursorPosTop);

            int propertyAndValueSpacing = 15;

            product.PrintPropertiesWithValues(productPropertiesCoordinates, new PrintSettings
            {
                ChosenListProperty         = "Id",
                PrintFlatList              = true,
                PropertiesAndValuesSpacing = propertyAndValueSpacing,
                PropertiesSpacing          = 2,
            });

            OptionsPrinter("        ");


            PrintCategories(categories);


            List <string>  propertyNames = productPropertiesCoordinates.SavedCoordinates.Keys.ToList();
            int            moveCursor    = 1;
            bool           shouldNotExit = true;
            ConsoleKeyInfo consoleKeyInfo;
            Dictionary <string, string> changes = new Dictionary <string, string>();
            List <int> oldProductCategoryIds    = product.Categories.Select(c => c.Id).ToList();
            List <int> newProductCategoryIds    = oldProductCategoryIds;
            bool       correctKey;


            while (shouldNotExit)
            {
                SetCursorPosition(
                    productPropertiesCoordinates.SavedCoordinates[propertyNames[moveCursor]].X + propertyAndValueSpacing,
                    productPropertiesCoordinates.SavedCoordinates[propertyNames[moveCursor]].Y);

                do
                {
                    consoleKeyInfo = ReadKey(true);

                    correctKey = !(consoleKeyInfo.Key == ConsoleKey.UpArrow ||
                                   consoleKeyInfo.Key == ConsoleKey.DownArrow ||
                                   consoleKeyInfo.Key == ConsoleKey.Escape || consoleKeyInfo.Key == ConsoleKey.Enter);
                } while (correctKey);


                switch (consoleKeyInfo.Key)
                {
                case ConsoleKey.UpArrow:

                    if (moveCursor > 1)
                    {
                        moveCursor--;
                    }

                    break;

                case ConsoleKey.DownArrow:

                    if (moveCursor < propertyNames.Count - 1)
                    {
                        moveCursor++;
                    }

                    break;

                case ConsoleKey.Enter:

                    string currentProperty = propertyNames[moveCursor];

                    if (!currentProperty.ToUpper().Contains("ID"))
                    {
                        if (currentProperty.ToUpper().Contains("CATEGORIES"))
                        {
                            EraseOldText(35);

                            int categoryId = Convert.ToInt32(ReadLine());

                            if (categories.Any(ca => ca.Id == categoryId))
                            {
                                if (newProductCategoryIds == oldProductCategoryIds)
                                {
                                    newProductCategoryIds = product.Categories.Select(c => c.Id).ToList();
                                }

                                if (newProductCategoryIds.Contains(categoryId))
                                {
                                    SetCursorPosition(
                                        productPropertiesCoordinates.SavedCoordinates["Categories"].X +
                                        propertyAndValueSpacing,
                                        productPropertiesCoordinates.SavedCoordinates["Categories"].Y);
                                    EraseOldText(35);
                                    Write("Category removed.");
                                    newProductCategoryIds.Remove(categoryId);
                                }
                                else
                                {
                                    SetCursorPosition(
                                        productPropertiesCoordinates.SavedCoordinates["Categories"].X +
                                        propertyAndValueSpacing,
                                        productPropertiesCoordinates.SavedCoordinates["Categories"].Y);
                                    EraseOldText(35);
                                    Write("Category sucessfully added added.");
                                    newProductCategoryIds.Add(categoryId);
                                }

                                string productCategoryIdsString = string.Join(", ", newProductCategoryIds);

                                SetCursorPosition(
                                    productPropertiesCoordinates.SavedCoordinates["Categories"].X +
                                    propertyAndValueSpacing,
                                    productPropertiesCoordinates.SavedCoordinates["Categories"].Y);
                                EraseOldText(35);
                                WriteLine(productCategoryIdsString);
                            }
                            else
                            {
                                SetCursorPosition(
                                    productPropertiesCoordinates.SavedCoordinates["Categories"].X +
                                    propertyAndValueSpacing,
                                    productPropertiesCoordinates.SavedCoordinates["Categories"].Y);
                                EraseOldText(35);
                                Write("Invalid category Id.");
                                Thread.Sleep(1000);
                            }
                        }
                        else
                        {
                            EraseOldText(35);

                            string input = ReadLine();

                            bool added = changes.TryAdd(currentProperty, input);

                            if (!added)
                            {
                                changes[currentProperty] = input;
                            }
                        }
                    }


                    break;

                case ConsoleKey.Escape:
                    shouldNotExit = false;

                    break;
                }


                SetCursorPosition(
                    productPropertiesCoordinates.SavedCoordinates[propertyNames[moveCursor]].X + propertyAndValueSpacing,
                    productPropertiesCoordinates.SavedCoordinates[propertyNames[moveCursor]].Y);
            }


            bool isUnchanged = changes.Count <= 0 && newProductCategoryIds == oldProductCategoryIds;

            if (isUnchanged)
            {
                return(edited);
            }

            bool b;

            JsonPatchDocument jsonPatchDocument = new JsonPatchDocument();

            OptionsPrinter("Apply edits? (Y)es (N)o");
            do
            {
                consoleKeyInfo = ReadKey(true);

                b = !(consoleKeyInfo.Key == ConsoleKey.Y || consoleKeyInfo.Key == ConsoleKey.N);
            } while (b);

            switch (consoleKeyInfo.Key)
            {
            case ConsoleKey.Y:
            {
                foreach (var change in changes)
                {
                    bool canConvert = decimal.TryParse(change.Value, out var price);

                    if (canConvert)
                    {
                        jsonPatchDocument.Replace(change.Key, price);
                    }
                    else
                    {
                        jsonPatchDocument.Replace(change.Key, change.Value);

                        if (change.Key.ToUpper().Contains("NAME"))
                        {
                            string urlSulg = change.Value.ToLower().Replace(" ", "-");


                            jsonPatchDocument.Replace("UrlSlug", urlSulg);
                        }
                    }
                }

                foreach (var categoryId in oldProductCategoryIds)
                {
                    if (!newProductCategoryIds.Contains(categoryId))
                    {
                        jsonPatchDocument.Remove($"Categories/{oldProductCategoryIds.IndexOf(categoryId)}");
                    }
                }

                foreach (var categoryId in newProductCategoryIds)
                {
                    if (!oldProductCategoryIds.Contains(categoryId))
                    {
                        ProductCategory productCategory = new ProductCategory();

                        productCategory.CategoryId = categoryId;

                        jsonPatchDocument.Add($"Categories/-", productCategory);
                    }
                }


                var stringContent = new StringContent(JsonConvert.SerializeObject(jsonPatchDocument), Encoding.UTF8,
                                                      "application/json");

                var response = _a.PatchResourceAsync(patchApiForProduct, stringContent).Result;

                if (response.IsSuccessStatusCode)
                {
                    Clear();
                    SetCursorPosition(MenuCursorPosLeft, MenuCursorPosTop);
                    WriteLine("Changes Sucessfully applied");
                    Thread.Sleep(1500);
                    edited = true;
                }
                else
                {
                    Clear();
                    SetCursorPosition(MenuCursorPosLeft, MenuCursorPosTop);
                    WriteLine("Something went wrong with applying the changes.");
                    Thread.Sleep(1500);
                }

                break;
            }

            case ConsoleKey.N:
                Clear();
                SetCursorPosition(MenuCursorPosLeft, MenuCursorPosTop);
                WriteLine("No changes applied");
                Thread.Sleep(1500);
                break;
            }


            return(edited);
        }
示例#21
0
        private WorkItem ReplayRevisions(List <RevisionItem> revisionsToMigrate, WorkItem sourceWorkItem, WorkItem targetWorkItem, Project destProject, WorkItemStoreContext sourceStore,
                                         int current,
                                         WorkItemStoreContext targetStore)
        {
            try
            {
                var skipToFinalRevisedWorkItemType = _config.SkipToFinalRevisedWorkItemType;

                var last = sourceStore.GetRevision(sourceWorkItem, revisionsToMigrate.Last().Number);

                string finalDestType = last.Type.Name;

                if (skipToFinalRevisedWorkItemType && me.TypeDefinitionMaps.Items.ContainsKey(finalDestType))
                {
                    finalDestType =
                        me.TypeDefinitionMaps.Items[finalDestType].Map();
                }

                //If work item hasn't been created yet, create a shell
                if (targetWorkItem == null)
                {
                    targetWorkItem = CreateWorkItem_Shell(destProject, sourceWorkItem, skipToFinalRevisedWorkItemType ? finalDestType : sourceStore.GetRevision(sourceWorkItem, revisionsToMigrate.First().Number).Type.Name);
                }

                if (_config.CollapseRevisions)
                {
                    var data = revisionsToMigrate.Select(rev => sourceStore.GetRevision(sourceWorkItem, rev.Number)).Select(rev => new
                    {
                        rev.Id,
                        rev.Rev,
                        rev.RevisedDate,
                        Fields = rev.Fields.AsDictionary()
                    });

                    var fileData = JsonConvert.SerializeObject(data, new JsonSerializerSettings {
                        PreserveReferencesHandling = PreserveReferencesHandling.None
                    });
                    var filePath = Path.Combine(Path.GetTempPath(), $"{sourceWorkItem.Id}_PreMigrationHistory.json");

                    File.WriteAllText(filePath, fileData);
                    targetWorkItem.Attachments.Add(new Attachment(filePath, "History has been consolidated into the attached file."));

                    revisionsToMigrate = revisionsToMigrate.GetRange(revisionsToMigrate.Count - 1, 1);

                    TraceWriteLine(LogEventLevel.Information, " Attached a consolidated set of {RevisionCount} revisions.",
                                   new Dictionary <string, object>()
                    {
                        { "RevisionCount", data.Count() }
                    });
                }

                foreach (var revision in revisionsToMigrate)
                {
                    var currentRevisionWorkItem = sourceStore.GetRevision(sourceWorkItem, revision.Number);

                    TraceWriteLine(LogEventLevel.Information, " Processing Revision [{RevisionNumber}]",
                                   new Dictionary <string, object>()
                    {
                        { "RevisionNumber", revision.Number }
                    });

                    // Decide on WIT
                    string destType = currentRevisionWorkItem.Type.Name;
                    if (me.TypeDefinitionMaps.Items.ContainsKey(destType))
                    {
                        destType =
                            me.TypeDefinitionMaps.Items[destType].Map();
                    }

                    //If the work item already exists and its type has changed, update its type. Done this way because there doesn't appear to be a way to do this through the store.
                    if (!skipToFinalRevisedWorkItemType && targetWorkItem.Type.Name != finalDestType)

                    {
                        Debug.WriteLine($"Work Item type change! '{targetWorkItem.Title}': From {targetWorkItem.Type.Name} to {destType}");
                        var typePatch = new JsonPatchOperation()
                        {
                            Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                            Path      = "/fields/System.WorkItemType",
                            Value     = destType
                        };
                        var datePatch = new JsonPatchOperation()
                        {
                            Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                            Path      = "/fields/System.ChangedDate",
                            Value     = currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedDate"].Value
                        };

                        var patchDoc = new JsonPatchDocument();
                        patchDoc.Add(typePatch);
                        patchDoc.Add(datePatch);
                        _witClient.UpdateWorkItemAsync(patchDoc, targetWorkItem.Id, bypassRules: true).Wait();
                    }

                    PopulateWorkItem(currentRevisionWorkItem, targetWorkItem, destType);
                    me.FieldMaps.ApplyFieldMappings(currentRevisionWorkItem.ToWorkItemData(), targetWorkItem.ToWorkItemData());

                    targetWorkItem.Fields["System.ChangedBy"].Value =
                        currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedBy"].Value;

                    targetWorkItem.Fields["System.History"].Value =
                        currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value;
                    //Debug.WriteLine("Discussion:" + currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value);


                    var fails = targetWorkItem.Validate();

                    foreach (Field f in fails)
                    {
                        TraceWriteLine(LogEventLevel.Information,
                                       "{Current} - Invalid: {CurrentRevisionWorkItemId}-{CurrentRevisionWorkItemTypeName}-{FieldReferenceName}-{SourceWorkItemTitle} Value: {FieldValue}",
                                       new Dictionary <string, object>()
                        {
                            { "Current", current },
                            { "CurrentRevisionWorkItemId", currentRevisionWorkItem.Id },
                            { "CurrentRevisionWorkItemTypeName", currentRevisionWorkItem.Type.Name },
                            { "FieldReferenceName", f.ReferenceName },
                            { "SourceWorkItemTitle", sourceWorkItem.Title },
                            { "FieldValue", f.Value }
                        });
                    }
                    //if (fails.Count > 0) // TODO Do we want to stop or continue?
                    //{
                    //    contextLog.Error("Unable to save revission due to the error in validation");
                    //    break;
                    //}

                    targetWorkItem.Save();
                    TraceWriteLine(LogEventLevel.Information,
                                   " Saved TargetWorkItem {TargetWorkItemId}. Replayed revision {RevisionNumber} of {RevisionsToMigrateCount}",
                                   new Dictionary <string, object>()
                    {
                        { "TargetWorkItemId", targetWorkItem.Id },
                        { "RevisionNumber", revision.Number },
                        { "RevisionsToMigrateCount", revisionsToMigrate.Count }
                    });
                }

                if (targetWorkItem != null)
                {
                    ProcessWorkItemAttachments(sourceWorkItem, targetWorkItem, false);
                    ProcessWorkItemLinks(sourceStore, targetStore, sourceWorkItem, targetWorkItem);
                    string reflectedUri = sourceStore.CreateReflectedWorkItemId(sourceWorkItem);
                    if (targetWorkItem.Fields.Contains(me.Target.Config.ReflectedWorkItemIDFieldName))
                    {
                        targetWorkItem.Fields[me.Target.Config.ReflectedWorkItemIDFieldName].Value = reflectedUri;
                    }
                    var history = new StringBuilder();
                    history.Append(
                        $"This work item was migrated from a different project or organization. You can find the old version at <a href=\"{reflectedUri}\">{reflectedUri}</a>.");
                    targetWorkItem.History = history.ToString();
                    this.SaveWorkItem(targetWorkItem);

                    attachmentEnricher.CleanUpAfterSave();
                    TraceWriteLine(LogEventLevel.Information, "...Saved as {TargetWorkItemId}", new Dictionary <string, object> {
                        { "TargetWorkItemId", targetWorkItem.Id }
                    });
                }
            }
            catch (Exception ex)
            {
                TraceWriteLine(LogEventLevel.Information, "...FAILED to Save");

                if (targetWorkItem != null)
                {
                    foreach (Field f in targetWorkItem.Fields)
                    {
                        TraceWriteLine(LogEventLevel.Information, "{FieldReferenceName} ({FieldName}) | {FieldValue}", new Dictionary <string, object>()
                        {
                            { "FieldReferenceName", f.ReferenceName }, { "FieldName", f.Name }, { "FieldValue", f.Value }
                        });
                    }
                }
                Log.Error(ex.ToString(), ex);
            }

            return(targetWorkItem);
        }
示例#22
0
        private JsonPatchDocument BuildADOIssuePatchDocumentFromV1DefectAssetdto(V1DefectAssetDto v1DefectAssetDto)
        {
            JsonPatchDocument patchDocument = null;

            if (v1DefectAssetDto != null)
            {
                patchDocument = new JsonPatchDocument();

                if (!string.IsNullOrEmpty(v1DefectAssetDto.ScopeName) ||
                    !string.IsNullOrEmpty(v1DefectAssetDto.ItemNumber) ||
                    !string.IsNullOrEmpty(v1DefectAssetDto.ItemName))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/System.Title",
                        Value     = string.Format("PROJECT: {0}, ITEM NUMBER: {1}, ITEM NAME: {2}", v1DefectAssetDto.ScopeName, v1DefectAssetDto.ItemNumber, v1DefectAssetDto.ItemName)
                    }
                        );
                }

                if (!string.IsNullOrEmpty(v1DefectAssetDto.EstimatedPoints))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.Scheduling.StoryPoints",
                        Value     = v1DefectAssetDto.EstimatedPoints
                    }
                        );
                }

                //if (!string.IsNullOrEmpty(v1DefectAssetDto.StatusName)
                //    || !string.IsNullOrEmpty(v1DefectAssetDto.AssetState))
                //{
                //    patchDocument.Add(
                //        new JsonPatchOperation()
                //        {
                //            Operation = Operation.Add,
                //            Path = "/fields/System.State",
                //            Value = string.Format("STATUS NAME: {0}, ASSET STATE: {1}", v1DefectAssetDto.StatusName, v1DefectAssetDto.AssetState)
                //        }
                //    );
                //}

                //if (!string.IsNullOrEmpty(v1DefectAssetDto.PriorityName))
                //{
                //    patchDocument.Add(
                //        new JsonPatchOperation()
                //        {
                //            Operation = Operation.Add,
                //            Path = "/fields/Microsoft.VSTS.Common.Priority",
                //            Value = v1DefectAssetDto.PriorityName
                //        }
                //    );
                //}

                if (!string.IsNullOrEmpty(v1DefectAssetDto.TaggedWith))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/System.Tags",
                        Value     = v1DefectAssetDto.TaggedWith
                    }
                        );
                }

                if (!string.IsNullOrEmpty(v1DefectAssetDto.Description))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/System.Description",
                        Value     = v1DefectAssetDto.Description
                    }
                        );
                }

                if (!string.IsNullOrEmpty(v1DefectAssetDto.SourceName) ||
                    !string.IsNullOrEmpty(v1DefectAssetDto.VersionAffected) ||
                    !string.IsNullOrEmpty(v1DefectAssetDto.FoundBy) ||
                    !string.IsNullOrEmpty(v1DefectAssetDto.ProductArea))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.TCM.SystemInfo",
                        Value     = string.Format("SOURCE: {0}, VERSION AFFECTED: {1}, FOUND BY: {2}, PRODUCT AREA: {3}", v1DefectAssetDto.SourceName, v1DefectAssetDto.VersionAffected, v1DefectAssetDto.FoundBy, v1DefectAssetDto.ProductArea)
                    }
                        );
                }

                if (!string.IsNullOrEmpty(v1DefectAssetDto.ReportingSite))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.Build.FoundIn",
                        Value     = v1DefectAssetDto.ReportingSite
                    }
                        );
                }

                //if (!string.IsNullOrEmpty(v1DefectAssetDto.Severity))
                //{
                //    patchDocument.Add(
                //        new JsonPatchOperation()
                //        {
                //            Operation = Operation.Add,
                //            Path = "/fields/Microsoft.VSTS.Common.Severity",
                //            Value = v1DefectAssetDto.Severity
                //        }
                //    );
                //}

                if (!string.IsNullOrEmpty(v1DefectAssetDto.ResolutionDetails))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.Common.ResolvedReason",
                        Value     = v1DefectAssetDto.ResolutionDetails
                    }
                        );
                }

                //if (!string.IsNullOrEmpty(v1DefectAssetDto.OwnersName))
                //{
                //    patchDocument.Add(
                //        new JsonPatchOperation()
                //        {
                //            Operation = Operation.Add,
                //            Path = "/fields/System.AssignedTo",
                //            Value = v1DefectAssetDto.OwnersName
                //        }
                //    );
                //}
            }
            return(patchDocument);
        }
示例#23
0
        public WorkItem CreateAndLinkToWorkItem()
        {
            string title       = "My new work item with links";
            string description = "This is a new work item that has a link also created on it.";
            string linkUrl     = "https://integrate.visualstudio.com";

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = title
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Scheduling.RemainingWork",
                Value     = "4"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Description",
                Value     = description
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.History",
                Value     = "Jim has the most context around this."
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "System.LinkTypes.Hierarchy-Reverse",
                    url        = linkUrl,
                    attributes = new
                    {
                        comment = "decomposition of work"
                    }
                }
            }
                );

            VssConnection connection = Context.Connection;
            WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient <WorkItemTrackingHttpClient>();

            // Get the project to create the sample work item in
            TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context);

            WorkItem result = workItemTrackingClient.CreateWorkItemAsync(patchDocument, project.Name, "Task").Result;

            return(result);
        }
示例#24
0
        public WorkItem CreateWorkItemWithWorkItemLink(string projectName, string linkUrl)
        {
            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = "JavaScript implementation for Microsoft Account"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Scheduling.RemainingWork",
                Value     = "4"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Description",
                Value     = "Follow the code samples from MSDN"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.History",
                Value     = "Jim has the most context around this."
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/relations/-",
                Value     = new
                {
                    rel        = "System.LinkTypes.Hierarchy-Reverse",
                    url        = linkUrl,
                    attributes = new
                    {
                        comment = "decomposition of work"
                    }
                }
            }
                );

            VssConnection connection = new VssConnection(_uri, _credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();
            WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, projectName, "Task").Result;

            return(result);
        }
示例#25
0
        /// <summary>
        /// Create a bug using the .NET client library
        /// </summary>
        /// <returns>Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItem</returns>
        public WorkItem CreateBugUsingClientLib(string subject)
        {
            Uri    uri = new Uri(_uri);
            string personalAccessToken = _personalAccessToken;
            string project             = _project;

            VssBasicCredential credentials   = new VssBasicCredential("", _personalAccessToken);
            JsonPatchDocument  patchDocument = new JsonPatchDocument();

            //add fields and their values to your patch document
            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = subject
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.TCM.ReproSteps",
                Value     = "Our authorization logic needs to allow for users with Microsoft accounts (formerly Live Ids) - http:// msdn.microsoft.com/en-us/library/live/hh826547.aspx"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Common.Priority",
                Value     = "1"
            }
                );

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Common.Severity",
                Value     = "2 - High"
            }
                );
            VssConnection connection = new VssConnection(uri, credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();

            try
            {
                WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Task").Result;

                Console.WriteLine("Bug Successfully Created: Bug #{0}", result.Id);

                return(result);
            }
            catch (AggregateException ex)
            {
                Console.WriteLine("Error creating bug: {0}", ex.InnerException.Message);
                return(null);
            }
        }
示例#26
0
        static void Main(string[] args)
        {
            // provide collection url of tfs
            var            collectionUri = "http://*****:*****@"C: \Users\pankagar\Downloads\Canvas.png", FileMode.Open, FileAccess.Read);
            var        attachmentObject = _witClient.CreateAttachmentAsync(uploadStream, "Canvas.png", "Simple").Result;

            // create a patchdocument object
            JsonPatchDocument json = new JsonPatchDocument();

            // create a new patch operation for title field
            JsonPatchOperation patchDocument1 = new JsonPatchOperation();

            patchDocument1.Operation = Operation.Add;
            patchDocument1.Path      = "/fields/System.Title";
            patchDocument1.Value     = "Testing Rest Api";
            json.Add(patchDocument1);

            // create a new patch operation for priority field
            JsonPatchOperation patchDocument2 = new JsonPatchOperation();

            patchDocument2.Operation = Operation.Add;
            patchDocument2.Path      = "/fields/Microsoft.VSTS.Common.Priority";
            patchDocument2.Value     = "2";
            json.Add(patchDocument2);


            // create testbasehelper object
            TestBaseHelper helper = new TestBaseHelper();
            // create testbase object to utilize teststep helpers
            ITestBase tb = helper.Create();

            // create 2 test steps ts1 and ts2
            ITestStep ts1 = tb.CreateTestStep();
            ITestStep ts2 = tb.CreateTestStep();

            ts1.Title          = "title -> title1";
            ts2.Title          = "title -> title2";
            ts1.ExpectedResult = "expected1";
            ts2.ExpectedResult = "expected2";
            ts1.Description    = "description1";
            ts2.Description    = "description2";
            // adding attachment to step1
            ts1.Attachments.Add(ts1.CreateAttachment(attachmentObject.Url, "CanvasImage"));

            // add your steps actions to testbase object
            tb.Actions.Add(ts1);
            tb.Actions.Add(ts2);

            // update json based on all actions (including teststeps and teststep attachemnts)
            json = tb.SaveActions(json);

            var xml = "";

            /* getting xml for teststeps
             * xml = tb.GenerateXmlFromActions();
             */

            // create Test Case work item using all test steps: ts1 and ts2
            var testCaseObject = _witClient.CreateWorkItemAsync(json, projectName, "Test Case").Result;
            int testCaseId     = Convert.ToInt32(testCaseObject.Id);

            // get Test Case using all relations
            testCaseObject = _witClient.GetWorkItemAsync(testCaseId, null, null, WorkItemExpand.Relations).Result;

            // update Test Case
            if (testCaseObject.Fields.ContainsKey("Microsoft.VSTS.TCM.Steps"))
            {
                xml = testCaseObject.Fields["Microsoft.VSTS.TCM.Steps"].ToString();
                tb  = helper.Create();

                // create tcmattachemntlink object from workitem relation, teststep helper will use this
                IList <TestAttachmentLink> tcmlinks = new List <TestAttachmentLink>();
                foreach (WorkItemRelation rel in testCaseObject.Relations)
                {
                    TestAttachmentLink tcmlink = new TestAttachmentLink();
                    tcmlink.Url        = rel.Url;
                    tcmlink.Attributes = rel.Attributes;
                    tcmlink.Rel        = rel.Rel;
                    tcmlinks.Add(tcmlink);
                }

                // load teststep xml and attachemnt links
                tb.LoadActions(xml, tcmlinks);

                ITestStep ts;
                //updating 1st test step
                ts                = (ITestStep)tb.Actions[0];
                ts.Title          = "title -> title11";
                ts.ExpectedResult = "expected11";

                //removing 2ns test step
                tb.Actions.RemoveAt(1);

                //adding new test step
                ITestStep ts3 = tb.CreateTestStep();
                ts3.Title          = "title -> title3";
                ts3.ExpectedResult = "expected3";
                tb.Actions.Add(ts3);

                JsonPatchDocument json2 = new JsonPatchDocument();
                // update json based on all new changes ( updated step xml and attachments)
                json2 = tb.SaveActions(json2);

                // update testcase wit using new json
                testCaseObject = _witClient.UpdateWorkItemAsync(json2, testCaseId).Result;

                /* Note : If you want to remove attachment then create new patchOperation, details are available here :
                 *        https://www.visualstudio.com/en-us/docs/integrate/api/wit/work-items#remove-an-attachment
                 */
            }
        }
示例#27
0
 public override bool Add(string path, object value)
 {
     newDoc.Add(path, value);
     return(true);
 }
示例#28
0
        /// <summary>
        /// Configures the passed JSON Patch so that it yields modified when applied to original
        /// - Adding fields to the patch present in modified, missing from original
        /// - Setting fields to the patch present in modified and original with different values
        /// - Delete fields present in original, missing from modified through
        /// - IFF map field - set to nil in patch ???
        /// - IFF list of maps && merge strategy - use deleteDirective for the elements ???
        /// - IFF list of primitives && merge strategy - use parallel deletion list ???
        /// - IFF list of maps or primitives with replace strategy (default) - set patch value to the value in modified ???
        /// - Build $retainKeys directive for fields with retainKeys patch strategy ???
        /// </summary>
        /// <param name="original">The original object</param>
        /// <param name="modified">The modified object</param>
        /// <param name="type">The type that original and modified represent (even if they are not actually that type, but a PSObject)</param>
        /// <param name="path">The JSON pointer to the currently inspected values</param>
        /// <param name="mergeStrategy">The strategy to use for patching (replace or merge with mergeKey)</param>
        public void CreateTwoWayPatch(object original, object modified, Type type, JsonPatchDocument patch, string path = "", MergeStrategyAttribute mergeStrategy = null, bool ignoreDeletions = false, bool ignoreAdditionsAndModifications = false)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (patch == null)
            {
                throw new ArgumentNullException(nameof(patch));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            logger.LogTrace($"Path: {path}");
            if (modified == null && original == null)
            {
                return;
            }
            if (modified == null && original != null)
            {
                if (!ignoreDeletions)
                {
                    patch.Replace(path, modified);
                }
                return;
            }
            if (original == null && modified != null)
            {
                if (!ignoreAdditionsAndModifications)
                {
                    patch.Replace(path, modified);
                }
                return;
            }

            // From this point, original and modified are known to be non-null

            logger.LogTrace($"Type: original {original?.GetType().Name} modified {modified?.GetType().Name} expected {type?.Name}");

            // string, int, float, bool, enum, DateTime
            if (modified is string || type.IsValueType)
            {
                logger.LogTrace($"Is value type, comparing {original} <-> {modified}");
                // Replace if changed, otherwise do nothing
                // We NEED to use Equals() here instead of != because the static type is object, meaning the scalar is boxed.
                // Since operators are resolved at compile time, this would use the == implementation for object,
                // while Equals() is dynamically dispatched on the real boxed type.
                if (!original.Equals(modified))
                {
                    patch.Replace(path, modified);
                }
                return;
            }

            // From this point, original and modified are known to be reference types

            if (System.Object.ReferenceEquals(original, modified))
            {
                // Same object, short cut
                return;
            }

            if (modified is IList)
            {
                logger.LogTrace("Is List");
                Type valueType = type.GetGenericArguments()[0];
                // Handle lists
                // Really just casting to generic IEnumerable get access to more LINQ. It's all object anyway.
                IEnumerable <object> originalEnumerable = ((IList)original).Cast <object>();
                IEnumerable <object> modifiedEnumerable = ((IList)modified).Cast <object>();
                // Check if the list property has a strategic merge strategy attribute
                if (mergeStrategy != null)
                {
                    if (mergeStrategy.Key != null)
                    {
                        logger.LogTrace("List is unordered set keyed by merge key");
                        // The lists are to be treated like dictionaries, keyed by Key
                        logger.LogTrace($"Merge key: {mergeStrategy.Key}");
                        Func <object, object> keySelector = listElement => {
                            PropertyInfo mergeProperty = ModelHelpers.FindJsonProperty(valueType, mergeStrategy.Key);
                            object       value         = listElement.GetDynamicPropertyValue(mergeProperty.Name);
                            if (value == null)
                            {
                                throw new Exception($"Merge key {mergeProperty} on type {valueType.FullName} cannot be null");
                            }
                            logger.LogTrace($"Merge property value: {value}");
                            return(value);
                        };
                        // The merge key value is *not* guaranteed to be string,
                        // for example ContainerPortV1 has the merge key ContainerPort which is type int
                        Dictionary <object, object> originalDict = originalEnumerable.ToDictionary(keySelector);
                        Dictionary <object, object> modifiedDict = modifiedEnumerable.ToDictionary(keySelector);
                        var removeOperations = new List <Action>();
                        int index            = 0;
                        foreach (var originalElement in originalEnumerable)
                        {
                            object elementKey  = originalElement.GetDynamicPropertyValue(ModelHelpers.FindJsonProperty(valueType, mergeStrategy.Key).Name);
                            string elementPath = path + "/" + index;
                            if (!modifiedDict.ContainsKey(elementKey))
                            {
                                if (!ignoreDeletions)
                                {
                                    // Entry removed in modified
                                    // Check that the value at the given index is really the value we want to modify,
                                    // to make sure indexes were not modified on the server
                                    // Queue these up because they shift array indexes around and for simplicity we want to get the modifications add first
                                    // This makes the patch easier to reason about.
                                    removeOperations.Add(() => patch.Test(elementPath + "/" + escapeJsonPointer(mergeStrategy.Key), elementKey));
                                    removeOperations.Add(() => patch.Remove(elementPath));
                                }
                            }
                            else
                            {
                                // Entry present in both, merge recursively
                                patch.Test(elementPath + "/" + escapeJsonPointer(mergeStrategy.Key), elementKey);
                                var countBefore = patch.Operations.Count;
                                CreateTwoWayPatch(
                                    original: originalElement,
                                    modified: modifiedDict[elementKey],
                                    type: valueType,
                                    patch: patch,
                                    path: elementPath,
                                    ignoreDeletions: ignoreDeletions,
                                    ignoreAdditionsAndModifications: ignoreAdditionsAndModifications
                                    );
                                if (patch.Operations.Count == countBefore)
                                {
                                    // Test was not needed, element was not modified
                                    patch.Operations.RemoveAt(patch.Operations.Count - 1);
                                }
                            }
                            index++;
                        }
                        // Modifications are done, add remove operations
                        foreach (var action in removeOperations)
                        {
                            action();
                        }
                        if (!ignoreAdditionsAndModifications)
                        {
                            // Entries added in modified
                            foreach (var modifiedEntry in modifiedDict)
                            {
                                if (!originalDict.ContainsKey(modifiedEntry.Key))
                                {
                                    // An element that was added in modified
                                    patch.Add(path + "/-", modifiedEntry.Value);
                                }
                            }
                        }
                    }
                    else
                    {
                        logger.LogTrace("List is unordered set");
                        // Lists are to be treated like unordered sets
                        HashSet <object> originalSet = originalEnumerable.ToHashSet();
                        HashSet <object> modifiedSet = modifiedEnumerable.ToHashSet();
                        // The index to adress the element on the server after applying every operation in the patch so far.
                        int index = 0;
                        foreach (var originalElement in originalEnumerable)
                        {
                            string elementPath = path + "/" + index;
                            if (!modifiedSet.Contains(originalElement))
                            {
                                // Deleted from modified
                                if (!ignoreDeletions)
                                {
                                    // When patching indexes, make sure elements didn't get moved around on the server
                                    // Can directly add them here because unordered sets do not use replace operations,
                                    // only remove and adding to the end
                                    patch.Test(elementPath, originalElement);
                                    patch.Remove(elementPath);
                                }
                            }
                            // Present in both: do nothing
                            index++;
                        }
                        if (!ignoreAdditionsAndModifications)
                        {
                            foreach (var modifiedElement in modifiedSet)
                            {
                                if (!originalSet.Contains(modifiedElement))
                                {
                                    // Added in modified
                                    patch.Add(path + "/-", modifiedElement);
                                }
                            }
                        }
                    }
                }
                else
                {
                    logger.LogTrace("List is ordered list");
                    // List is to be treated as an ordered list, e.g. ContainerV1.Command
                    List <object> originalList     = originalEnumerable.ToList();
                    List <object> modifiedList     = modifiedEnumerable.ToList();
                    var           removeOperations = new List <Action>();
                    int           index            = 0;
                    foreach (var originalElement in originalList.Take(modifiedList.Count))
                    {
                        string elementPath = path + "/" + index;
                        if (index >= modifiedList.Count)
                        {
                            // Not present in modified, remove
                            if (!ignoreDeletions)
                            {
                                removeOperations.Add(() => patch.Test(elementPath, originalElement));
                                removeOperations.Add(() => patch.Remove(elementPath));
                            }
                        }
                        else
                        {
                            // Present in both, merge recursively
                            // Add a test to check that indexes were not moved on the server
                            patch.Test(elementPath, originalElement);
                            int countBefore = patch.Operations.Count;
                            CreateTwoWayPatch(
                                original: originalElement,
                                modified: modifiedList[index],
                                type: valueType,
                                patch: patch,
                                path: elementPath,
                                ignoreDeletions: ignoreDeletions,
                                ignoreAdditionsAndModifications: ignoreAdditionsAndModifications
                                );
                            if (patch.Operations.Count == countBefore)
                            {
                                // Test was not needed, element was not modified
                                patch.Operations.RemoveAt(patch.Operations.Count - 1);
                            }
                        }
                        index++;
                    }
                    // Modifications are done, register remove operations
                    foreach (var action in removeOperations)
                    {
                        action();
                    }
                    // Continue on modifiedList (if it's longer) to add added elements
                    for (; index < modifiedList.Count; index++)
                    {
                        // Added in modifiedList
                        object addedElement = modifiedList[index];
                        patch.Add(path + "/-", addedElement);
                    }
                }
            }
            else if (modified is IDictionary)
            {
                logger.LogTrace("Is Dictionary");
                Type valueType = type.GetGenericArguments()[1];
                // Handle maps (e.g. KubeResourceV1.Annotations)
                IDictionary originalDict = (IDictionary)original;
                IDictionary modifiedDict = (IDictionary)modified;
                // Always merge maps
                foreach (DictionaryEntry originalEntry in originalDict)
                {
                    string entryKey   = (string)originalEntry.Key;
                    object entryValue = (object)originalEntry.Value;
                    string entryPath  = path + "/" + escapeJsonPointer(entryKey);
                    if (!modifiedDict.Contains(originalEntry.Key))
                    {
                        if (!ignoreDeletions)
                        {
                            // Entry removed in modified
                            patch.Remove(entryPath);
                        }
                    }
                    else
                    {
                        // Entry present in both, merge recursively
                        CreateTwoWayPatch(
                            original: entryValue,
                            modified: modifiedDict[originalEntry.Key],
                            type: valueType,
                            patch: patch,
                            path: entryPath,
                            ignoreDeletions: ignoreDeletions,
                            ignoreAdditionsAndModifications: ignoreAdditionsAndModifications
                            );
                    }
                }
                if (!ignoreAdditionsAndModifications)
                {
                    // Entries added in modified
                    foreach (DictionaryEntry modifiedEntry in modifiedDict)
                    {
                        string entryKey   = (string)modifiedEntry.Key;
                        object entryValue = (object)modifiedEntry.Value;
                        if (!originalDict.Contains(entryKey))
                        {
                            // An element that was added in modified
                            patch.Add(path + "/" + escapeJsonPointer(entryKey), entryValue);
                        }
                    }
                }
            }
            else
            {
                logger.LogTrace("Is other object");
                // resourceVersion: a string that identifies the internal version of this object that can be used by
                // clients to determine when objects have changed. This value MUST be treated as opaque by clients
                // and passed unmodified back to the server.
                // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata
                // Add this test before traversing into other properties
                if (type.IsSubclassOf(typeof(KubeResourceV1)))
                {
                    var resourceVersion = (string)original.GetDynamicPropertyValue("Metadata")?.GetDynamicPropertyValue("ResourceVersion");
                    if (!String.IsNullOrEmpty(resourceVersion))
                    {
                        patch.Test(path + "/metadata/resourceVersion", resourceVersion);
                    }
                }
                // Warn if properties were passed that are not recognized to highlight mistakes
                foreach (var propName in modified.GetDynamicPropertyNames().Where(name => type.GetProperty(name) == null))
                {
                    logger.LogWarning($"Unknown property \"{propName}\" on {type.Name} at path \"{path}\"");
                }
                // KubeObjects, compare properties recursively
                foreach (PropertyInfo prop in type.GetProperties())
                {
                    logger.LogTrace($"Property {prop.Name}");

                    // Ignore properties that are not part of modified
                    if (modified is PSObject psObject && psObject.Properties[prop.Name] == null)
                    {
                        continue;
                    }

                    JsonPropertyAttribute jsonAttribute = (JsonPropertyAttribute)prop.GetCustomAttribute(typeof(JsonPropertyAttribute));
                    string propPath = path + "/" + escapeJsonPointer(jsonAttribute.PropertyName);

                    object originalValue = original.GetDynamicPropertyValue(prop.Name);
                    object modifiedValue = modified.GetDynamicPropertyValue(prop.Name);

                    if (!isPropertyUpdateable(type, prop))
                    {
                        continue;
                    }

                    // Pass patch strategy attribute to diff function for the property we're looking at
                    MergeStrategyAttribute attribute = (MergeStrategyAttribute)Attribute.GetCustomAttribute(prop, typeof(MergeStrategyAttribute));
                    CreateTwoWayPatch(
                        original: originalValue,
                        modified: modifiedValue,
                        type: prop.PropertyType,
                        patch: patch,
                        path: propPath,
                        mergeStrategy: attribute,
                        ignoreDeletions: ignoreDeletions,
                        ignoreAdditionsAndModifications: ignoreAdditionsAndModifications
                        );
                }
            }
        }
示例#29
0
        private WorkItem CreateWorkItem_ReplayRevisions(WorkItem sourceWorkItem, Project destProject, WorkItemStoreContext sourceStore,
                                                        int current,
                                                        WorkItemStoreContext targetStore)
        {
            WorkItem newwit = null;

            try
            {
                // just to make sure, we replay the events in the same order as they appeared
                // maybe, the Revisions collection is not sorted according to the actual Revision number
                var sortedRevisions = sourceWorkItem.Revisions.Cast <Revision>().Select(x =>
                                                                                        new
                {
                    x.Index,
                    Number = Convert.ToInt32(x.Fields["System.Rev"].Value)
                }
                                                                                        )
                                      .OrderBy(x => x.Number)
                                      .ToList();

                Trace.WriteLine($"...Replaying {sourceWorkItem.Revisions.Count} revisions of work item {sourceWorkItem.Id}", Name);

                foreach (var revision in sortedRevisions)
                {
                    var currentRevisionWorkItem = sourceStore.GetRevision(sourceWorkItem, revision.Number);

                    // Decide on WIT
                    if (me.WorkItemTypeDefinitions.ContainsKey(currentRevisionWorkItem.Type.Name))
                    {
                        var destType =
                            me.WorkItemTypeDefinitions[currentRevisionWorkItem.Type.Name].Map(currentRevisionWorkItem);
                        //If work item hasn't been created yet, create a shell
                        if (newwit == null)
                        {
                            newwit = CreateWorkItem_Shell(destProject, currentRevisionWorkItem, destType);
                        }
                        //If the work item already exists and its type has changed, update its type. Done this way because there doesn't appear to be a way to do this through the store.
                        else if (newwit.Type.Name != destType)
                        {
                            Debug.WriteLine($"Work Item type change! '{newwit.Title}': From {newwit.Type.Name} to {destType}");
                            var typePatch = new JsonPatchOperation()
                            {
                                Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                                Path      = "/fields/System.WorkItemType",
                                Value     = destType
                            };
                            var datePatch = new JsonPatchOperation()
                            {
                                Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                                Path      = "/fields/System.ChangedDate",
                                Value     = currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedDate"].Value
                            };

                            var patchDoc = new JsonPatchDocument();
                            patchDoc.Add(typePatch);
                            patchDoc.Add(datePatch);
                            _witClient.UpdateWorkItemAsync(patchDoc, newwit.Id, bypassRules: true).Wait();
                        }

                        PopulateWorkItem(currentRevisionWorkItem, newwit, destType);
                        me.ApplyFieldMappings(currentRevisionWorkItem, newwit);

                        newwit.Fields["System.ChangedBy"].Value =
                            currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedBy"].Value;

                        newwit.Fields["System.History"].Value =
                            currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value;
                        Debug.WriteLine("Discussion:" + currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value);


                        var fails = newwit.Validate();

                        foreach (Field f in fails)
                        {
                            Trace.WriteLine(
                                $"{current} - Invalid: {currentRevisionWorkItem.Id}-{currentRevisionWorkItem.Type.Name}-{f.ReferenceName}-{sourceWorkItem.Title} Value: {f.Value}", Name);
                        }



                        newwit.Save();
                        Trace.WriteLine(
                            $" ...Saved as {newwit.Id}. Replayed revision {revision.Number} of {sourceWorkItem.Revisions.Count}",
                            Name);
                    }
                    else
                    {
                        Trace.WriteLine(string.Format("...the WITD named {0} is not in the list provided in the configuration.json under WorkItemTypeDefinitions. Add it to the list to enable migration of this work item type.", currentRevisionWorkItem.Type.Name), Name);
                        break;
                    }
                }

                if (newwit != null)
                {
                    string reflectedUri = sourceStore.CreateReflectedWorkItemId(sourceWorkItem);
                    if (newwit.Fields.Contains(me.Target.Config.ReflectedWorkItemIDFieldName))
                    {
                        newwit.Fields["System.ChangedBy"].Value = "Migration";
                        newwit.Fields[me.Target.Config.ReflectedWorkItemIDFieldName].Value = reflectedUri;
                    }
                    var history = new StringBuilder();
                    history.Append(
                        $"This work item was migrated from a different project or organization. You can find the old version at <a href=\"{reflectedUri}\">{reflectedUri}</a>.");
                    newwit.History = history.ToString();

                    newwit.Save();

                    Trace.WriteLine($"...Saved as {newwit.Id}", Name);

                    if (_config.UpdateSourceReflectedId && sourceWorkItem.Fields.Contains(me.Source.Config.ReflectedWorkItemIDFieldName))
                    {
                        sourceWorkItem.Fields[me.Source.Config.ReflectedWorkItemIDFieldName].Value =
                            targetStore.CreateReflectedWorkItemId(newwit);
                        sourceWorkItem.Save();
                        Trace.WriteLine($"...and Source Updated {sourceWorkItem.Id}", Name);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("...FAILED to Save", Name);

                if (newwit != null)
                {
                    foreach (Field f in newwit.Fields)
                    {
                        Trace.WriteLine($"{f.ReferenceName} ({f.Name}) | {f.Value}", Name);
                    }
                }
                Trace.WriteLine(ex.ToString(), Name);
            }
            return(newwit);
        }
示例#30
0
        private static async Task CreateBugAsync(string collectionUri, string teamProjectName, string team, string url, string severity, string title, string description, string solution, string areaPath, string iterationPath, string personalAccessToken)
        {
            var connection = GetConnection(collectionUri, personalAccessToken);

            var witClient  = connection.GetClient <WorkItemTrackingHttpClient>();
            var workClient = connection.GetClient <WorkHttpClient>();

            string fullTitle = severity + " - " + title + " in " + url;


            // Check to see if bug exists for team and is current open
            var wiql = new Wiql();

            wiql.Query = "SELECT [System.Title] FROM WorkItems WHERE [System.TeamProject] = '" + teamProjectName + "' AND [System.WorkItemType] = 'Bug' AND [System.Title] CONTAINS '" + fullTitle + "' AND [System.State] <> 'Closed' AND [System.State] <> 'Removed' AND [System.AreaPath] UNDER '" + areaPath + "' AND [System.IterationPath] UNDER '" + iterationPath + "'";

            var results = await witClient.QueryByWiqlAsync(wiql);

            string severityValue = severity == "High" ? "2 - High" : severity == "Low" ? "4 - Low" : "3 - Medium";

            if (results.WorkItems.Count() == 0)
            {
                // create new bug

                var doc = new JsonPatchDocument();
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/System.Title",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = fullTitle
                });
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/Microsoft.VSTS.TCM.ReproSteps",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = description + " " + solution
                });
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/Microsoft.VSTS.Common.Severity",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = severityValue
                });
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/System.AreaPath",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = areaPath
                });
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/System.IterationPath",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = iterationPath
                });
                doc.Add(
                    new JsonPatchOperation()
                {
                    Path      = "/fields/System.Tags",
                    Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                    Value     = "OWASP"
                });

                var witCreated = await witClient.CreateWorkItemAsync(doc, teamProjectName, "Bug");

                System.Console.WriteLine("Bug created");
            }
            else
            {
                // if bug was created and resolved but bug was still found, move back to active
                var bug       = results.WorkItems.First();
                var bugDetail = await witClient.GetWorkItemAsync(bug.Id);

                string state = bugDetail.Fields.First(w => w.Key == "System.State").Value.ToString();

                if (state.ToString() == "resolved")
                {
                    var doc = new JsonPatchDocument();
                    doc.Add(
                        new JsonPatchOperation()
                    {
                        Path      = "/fields/System.State",
                        Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Replace,
                        Value     = "Active"
                    });
                    await witClient.UpdateWorkItemAsync(doc, bug.Id);

                    System.Console.WriteLine("Bug is not fixed.  Moving to active.");
                }
                else
                {
                    System.Console.WriteLine("Bug is already active");
                }
            }
        }
示例#31
0
        public AzureTestCase CreatTestCase(AzureTestCase testCase)
        {
            var uri = new Uri(_uri);

            var credentials   = new VssBasicCredential(string.Empty, _personalAccessToken);
            var patchDocument = new JsonPatchDocument();

            patchDocument.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = testCase.Title,
            });

            patchDocument.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Common.Priority",
                Value     = testCase.Priority,
            });

            if (!string.IsNullOrEmpty(testCase.AreaPath))
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.AreaPath",
                    Value     = testCase.AreaPath,
                });
            }

            if (!string.IsNullOrEmpty(testCase.IterationPath))
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.IterationPath",
                    Value     = testCase.IterationPath,
                });
            }

            if (!string.IsNullOrEmpty(testCase.Description))
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.Description",
                    Value     = testCase.Description,
                });
            }

            if (!string.IsNullOrEmpty(TestStepsService.GenerateTestStepsHtml(testCase.TestSteps)) || !string.IsNullOrEmpty(testCase.TestStepsHtml))
            {
                if (testCase.TestSteps.Any())
                {
                    patchDocument.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.TCM.Steps",
                        Value     = TestStepsService.GenerateTestStepsHtml(testCase.TestSteps),
                    });
                }
                else
                {
                    patchDocument.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/fields/Microsoft.VSTS.TCM.Steps",
                        Value     = testCase.TestStepsHtml,
                    });
                }
            }

            patchDocument.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestName",
                Value     = testCase.AutomatedTestName,
            });

            patchDocument.Add(new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestStorage",
                Value     = testCase.AutomatedTestStorage,
            });

            if (!string.IsNullOrEmpty(testCase.RequirementUrl))
            {
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/relations/-",
                    Value     = new
                    {
                        rel        = "System.LinkTypes.Hierarchy-Reverse",
                        url        = testCase.RequirementUrl,
                        attributes = new Dictionary <string, object>()
                        {
                            { "isLocked", false },
                            { "name", "Parent" },
                            { "comment", "added automatically" },
                        },
                    },
                });
            }

            VssConnection connection = new VssConnection(uri, credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();

            try
            {
                WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, _project, "Test Case").Result;
                return(ConvertWorkItemToAzureTestCase(result));
            }
            catch (AggregateException ex)
            {
                Debug.WriteLine("Error creating test case: {0}", ex.InnerException.Message);
                return(null);
            }
        }
示例#32
0
        public static async Task <JsonPatchDocument> GetChangesAsync(this Item item, QueryDb queryDb, WorkItemTrackingHttpClient itemClient, PodioAPI.Podio podio, PodioApp app, bool ignoreRequirements, string currentIterationName)
        {
            var patchDocument = new JsonPatchDocument();
            var podioType     = item.GetPodioType(app.PodioTypeExternalId);
            var appId         = item.App.AppId;

            var mappings = queryDb.TypeMappings
                           .Include(x => x.FieldMappings)
                           .ThenInclude(x => x.CategoryMappings)
                           .Where(x => x.PodioType == podioType)
                           .SelectMany(x => x.FieldMappings)
                           .ToList();

            if (!ignoreRequirements)
            {
                foreach (var categoryField in mappings.Where(x => x.FieldType == FieldType.Category))
                {
                    var requiredValue = categoryField.CategoryMappings.SingleOrDefault(x => x.Required);
                    if (requiredValue != null)
                    {
                        var field = item.Fields
                                    .SingleOrDefault(x => x.ExternalId == categoryField.PodioFieldName);
                        if (field == null)
                        {
                            throw new ArgumentException("Rules dictate this item should not be synced");
                        }
                        var podioValueField = field.Values.ToObject <PodioValue[]>();
                        var fieldValue      = podioValueField.FirstOrDefault()?.Value?.Text;
                        if (!requiredValue.PodioValue.Equals(fieldValue, StringComparison.InvariantCultureIgnoreCase))
                        {
                            throw new ArgumentException("Rules dictate this item should not be synced");
                        }
                    }
                }
            }
            var revision = queryDb.Links.SingleOrDefault(x => x.PodioId == item.ItemId)?.PodioRevision;
            var fieldIds = revision.HasValue ? (await podio.ItemService.GetItemRevisionDifference(item.ItemId, revision.Value, item.CurrentRevision.Revision)).Select(x => x.ExternalId) : item.Fields.Select(x => x.ExternalId);

            foreach (var field in item.Fields.Where(x => fieldIds.Contains(x.ExternalId)))
            {
                var mapping = mappings.SingleOrDefault(x => x.PodioFieldName == field.ExternalId);
                if (mapping == null || (string.IsNullOrWhiteSpace(mapping.AzureFieldName) && !(mapping.FieldType == FieldType.Image || mapping.FieldType == FieldType.User)))
                {
                    continue;
                }

                switch (mapping.FieldType)
                {
                case FieldType.Image:
                    foreach (var file in item.Field <ImageItemField>(field.ExternalId)?.Images.ToList())
                    {
                        FileResponse fileResponse = await podio.FileService.DownloadFile(file);

                        using (var stream = new MemoryStream(fileResponse.FileContents))
                        {
                            var imgReference = await itemClient.CreateAttachmentAsync(stream);

                            patchDocument.Add(
                                new JsonPatchOperation()
                            {
                                Operation = Operation.Add,
                                Path      = "/relations/-",
                                Value     = new
                                {
                                    rel        = "AttachedFile",
                                    url        = imgReference.Url,
                                    attributes = new { name = file.Name }
                                }
                            }
                                );
                        }
                    }
                    break;

                case FieldType.User:
                    var    userField   = item.Field <ContactItemField>(field.ExternalId);
                    var    contact     = userField.Contacts.FirstOrDefault();
                    string commentText = "";
                    if (!queryDb.Links.Any(x => x.PodioId == item.ItemId))
                    {
                        commentText = $"Created by {contact.Name}</br>Podio url: <a href=\"{item.Link}\" target=\"_blank\">{item.Link}</a>";
                        patchDocument.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/System.History",
                            Value     = commentText
                        }
                            );
                    }
                    break;

                case FieldType.Category:
                    var categoryValue = field.Values.ToObject <PodioValue[]>();
                    var mappedValue   = mapping.CategoryMappings.FirstOrDefault(x => x.PodioValue == categoryValue[0].Value.Text)?.AzureValue;
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = mappedValue
                    }
                        );
                    break;

                case FieldType.Boolean:
                    break;

                case FieldType.Int:
                    var numberValue = field.Values.First().Value <string>("value");
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = numberValue
                    }
                        );
                    break;

                case FieldType.String:
                    var stringValue = field.Values.First().Value <string>("value");
                    var existing    = patchDocument.SingleOrDefault(x => x.Path == $"/fields/{mapping.AzureFieldName}");
                    if (existing != null)
                    {
                        existing.Value += mapping.PrefixValue + stringValue;
                    }
                    else
                    {
                        patchDocument.Add(
                            new JsonPatchOperation()
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/{mapping.AzureFieldName}",
                            Value     = mapping.PrefixValue + stringValue
                        }
                            );
                    }
                    break;

                case FieldType.Date:
                    var dateField = item.Field <DateItemField>(field.ExternalId);
                    var dateValue = dateField.Start.HasValue ? dateField.Start.Value : dateField.End.HasValue ? dateField.End.Value : DateTime.UtcNow;
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{mapping.AzureFieldName}",
                        Value     = dateValue
                    }
                        );
                    break;
                }
            }

            // TODO should only attach files if they are not allready attached to Azure item
            // Handle files
            foreach (var file in item.Files)
            {
                var podioFile = await podio.FileService.DownloadFile(file);

                using (var stream = new MemoryStream(podioFile.FileContents))
                {
                    var fileReference = await itemClient.CreateAttachmentAsync(stream);

                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "AttachedFile",
                            url        = fileReference.Url,
                            attributes = new { name = file.Name }
                        }
                    }
                        );
                }
            }

            // Set to current iteration if it's a bug and it has priority 1
            if (patchDocument.Any(x => x.Path == "/fields/Microsoft.VSTS.Common.Priority" && x.Value.ToString() == "1") &&
                string.Equals(item.GetAzureType(app), "bug", StringComparison.CurrentCultureIgnoreCase))
            {
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = $"/fields/System.IterationPath",
                    Value     = currentIterationName
                });
            }
            return(patchDocument);
        }
示例#33
0
        private WorkItem ReplayRevisions(List <RevisionItem> revisionsToMigrate, WorkItem sourceWorkItem, WorkItem targetWorkItem, Project destProject, WorkItemStoreContext sourceStore,
                                         int current,
                                         WorkItemStoreContext targetStore)
        {
            try
            {
                foreach (var revision in revisionsToMigrate)
                {
                    var currentRevisionWorkItem = sourceStore.GetRevision(sourceWorkItem, revision.Number);
                    TraceWriteLine(currentRevisionWorkItem, $" Processing Revision[{revision.Number}");
                    // Decide on WIT
                    string destType = currentRevisionWorkItem.Type.Name;
                    if (me.WorkItemTypeDefinitions.ContainsKey(destType))
                    {
                        destType =
                            me.WorkItemTypeDefinitions[destType].Map(currentRevisionWorkItem);
                    }
                    //If work item hasn't been created yet, create a shell
                    if (targetWorkItem == null)
                    {
                        targetWorkItem = CreateWorkItem_Shell(destProject, currentRevisionWorkItem, destType);
                    }
                    //If the work item already exists and its type has changed, update its type. Done this way because there doesn't appear to be a way to do this through the store.
                    else if (targetWorkItem.Type.Name != destType)
                    {
                        Debug.WriteLine($"Work Item type change! '{targetWorkItem.Title}': From {targetWorkItem.Type.Name} to {destType}");
                        var typePatch = new JsonPatchOperation()
                        {
                            Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                            Path      = "/fields/System.WorkItemType",
                            Value     = destType
                        };
                        var datePatch = new JsonPatchOperation()
                        {
                            Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                            Path      = "/fields/System.ChangedDate",
                            Value     = currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedDate"].Value
                        };

                        var patchDoc = new JsonPatchDocument();
                        patchDoc.Add(typePatch);
                        patchDoc.Add(datePatch);
                        _witClient.UpdateWorkItemAsync(patchDoc, targetWorkItem.Id, bypassRules: true).Wait();
                    }

                    PopulateWorkItem(currentRevisionWorkItem, targetWorkItem, destType);
                    me.ApplyFieldMappings(currentRevisionWorkItem, targetWorkItem);

                    targetWorkItem.Fields["System.ChangedBy"].Value =
                        currentRevisionWorkItem.Revisions[revision.Index].Fields["System.ChangedBy"].Value;

                    targetWorkItem.Fields["System.History"].Value =
                        currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value;
                    //Debug.WriteLine("Discussion:" + currentRevisionWorkItem.Revisions[revision.Index].Fields["System.History"].Value);


                    var fails = targetWorkItem.Validate();

                    foreach (Field f in fails)
                    {
                        TraceWriteLine(currentRevisionWorkItem,
                                       $"{current} - Invalid: {currentRevisionWorkItem.Id}-{currentRevisionWorkItem.Type.Name}-{f.ReferenceName}-{sourceWorkItem.Title} Value: {f.Value}");
                    }

                    targetWorkItem.Save();
                    TraceWriteLine(currentRevisionWorkItem,
                                   $" Saved TargetWorkItem {targetWorkItem.Id}. Replayed revision {revision.Number} of {currentRevisionWorkItem.Revisions.Count}");
                }

                if (targetWorkItem != null)
                {
                    ProcessWorkItemAttachments(sourceWorkItem, targetWorkItem, false);
                    ProcessWorkItemLinks(sourceStore, targetStore, sourceWorkItem, targetWorkItem, false);
                    string reflectedUri = sourceStore.CreateReflectedWorkItemId(sourceWorkItem);
                    if (targetWorkItem.Fields.Contains(me.Target.Config.ReflectedWorkItemIDFieldName))
                    {
                        targetWorkItem.Fields[me.Target.Config.ReflectedWorkItemIDFieldName].Value = reflectedUri;
                    }
                    var history = new StringBuilder();
                    history.Append(
                        $"This work item was migrated from a different project or organization. You can find the old version at <a href=\"{reflectedUri}\">{reflectedUri}</a>.");
                    targetWorkItem.History = history.ToString();
                    SaveWorkItem(targetWorkItem);

                    attachmentOMatic.CleanUpAfterSave(targetWorkItem);
                    TraceWriteLine(sourceWorkItem, $"...Saved as {targetWorkItem.Id}");

                    if (_config.UpdateSourceReflectedId && sourceWorkItem.Fields.Contains(me.Source.Config.ReflectedWorkItemIDFieldName))
                    {
                        sourceWorkItem.Fields[me.Source.Config.ReflectedWorkItemIDFieldName].Value =
                            targetStore.CreateReflectedWorkItemId(targetWorkItem);
                        SaveWorkItem(sourceWorkItem);
                        TraceWriteLine(sourceWorkItem, $"...and Source Updated {sourceWorkItem.Id}");
                    }
                }
            }
            catch (Exception ex)
            {
                TraceWriteLine(sourceWorkItem, "...FAILED to Save");

                if (targetWorkItem != null)
                {
                    foreach (Field f in targetWorkItem.Fields)
                    {
                        TraceWriteLine(sourceWorkItem, $"{f.ReferenceName} ({f.Name}) | {f.Value}");
                    }
                }
                TraceWriteLine(sourceWorkItem, ex.ToString());
            }
            return(targetWorkItem);
        }
示例#34
0
        public void AddResultsShouldReplaceInNestedInDynamic()
        {
            dynamic doc = new ExpandoObject();
            doc.Nested = new NestedDTO();
            doc.Nested.DynamicProperty = new ExpandoObject();
            doc.Nested.DynamicProperty.InBetweenFirst = new ExpandoObject();
            doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond = new ExpandoObject();
            doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty = "A";

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("/Nested/DynamicProperty/InBetweenFirst/InBetweenSecond/StringProperty", "B");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal("B", doc.Nested.DynamicProperty.InBetweenFirst.InBetweenSecond.StringProperty);
        }
示例#35
0
        protected override WebApiWorkItem DoSetItem()
        {
            var wi              = GetItem <WebApiWorkItem>();
            var tpc             = GetCollection();
            var fields          = GetParameter <Hashtable>(nameof(SetWorkItem.Fields), new Hashtable());
            var bypassRules     = GetParameter <bool>(nameof(SetWorkItem.BypassRules));
            var boardColumn     = GetParameter <string>(nameof(SetWorkItem.BoardColumn));
            var boardColumnDone = GetParameter <bool>(nameof(SetWorkItem.BoardColumnDone));
            var boardLane       = GetParameter <string>(nameof(SetWorkItem.BoardLane));

            foreach (var argName in _parameterMap.Keys.Where(f => HasParameter(f) && !fields.ContainsKey(f)))
            {
                fields.Add(_parameterMap[argName], GetParameter <object>(argName));
            }

            if (fields.Count > 0)
            {
                var patch = new JsonPatchDocument()
                {
                    new JsonPatchOperation()
                    {
                        Operation = Operation.Test,
                        Path      = "/rev",
                        Value     = wi.Rev
                    }
                };

                foreach (DictionaryEntry field in fields)
                {
                    patch.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{field.Key}",
                        Value     = field.Value is IEnumerable <string>?
                                    string.Join(";", (IEnumerable <string>)field.Value) :
                                        field.Value
                    });
                }

                var client = GetClient <WorkItemTrackingHttpClient>();

                wi = client.UpdateWorkItemAsync(patch, (int)wi.Id, false, bypassRules)
                     .GetResult("Error updating work item");
            }

            // Change board status

            if (HasParameter(nameof(SetWorkItem.BoardColumn)) ||
                HasParameter(nameof(SetWorkItem.BoardColumnDone)) ||
                HasParameter(nameof(SetWorkItem.BoardLane)))
            {
                var patch = new JsonPatchDocument()
                {
                    new JsonPatchOperation()
                    {
                        Operation = Operation.Test,
                        Path      = "/rev",
                        Value     = wi.Rev
                    }
                };

                var(_, tp, t) = GetCollectionProjectAndTeam();
                var board = FindBoard((string)wi.Fields["System.WorkItemType"], tpc, tp, t);

                if (HasParameter(nameof(SetWorkItem.BoardColumn)))
                {
                    patch.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{board.Fields.ColumnField.ReferenceName}",
                        Value     = GetParameter <string>(nameof(SetWorkItem.BoardColumn))
                    });
                }

                if (HasParameter(nameof(SetWorkItem.BoardLane)))
                {
                    patch.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{board.Fields.RowField.ReferenceName}",
                        Value     = GetParameter <string>(nameof(SetWorkItem.BoardLane))
                    });
                }

                if (HasParameter(nameof(SetWorkItem.BoardColumnDone)))
                {
                    patch.Add(new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{board.Fields.DoneField.ReferenceName}",
                        Value     = GetParameter <bool>(nameof(SetWorkItem.BoardColumnDone))
                    });
                }

                var client = GetClient <WorkItemTrackingHttpClient>();

                wi = client.UpdateWorkItemAsync(patch, (int)wi.Id, false, bypassRules)
                     .GetResult("Error updating work item");
            }

            return(wi);
        }
示例#36
0
        public void AddToListAtEndWithSerialization()
        {
            var doc = new
            {
                IntegerList = new List<int>() { 1, 2, 3 }
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("IntegerList/3", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.IntegerList);
        }
示例#37
0
        public static async Task CreateTask(VssConnection connection)
        {
            WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();


            try
            {
                JsonPatchDocument patchDocument = new JsonPatchDocument();
                // título da solicitação
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.Title",
                    Value     = "titulo"
                }
                    );

                // descrição da solicitação
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.c474834f-4b08-42ac-aaa3-1bcf80e3ae66",
                    Value     = "descricao"
                }
                    );
                // razão social do cliente
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.ClienteLista",
                    Value     = "XCLIENTE DE TESTE - NÃO APAGAR"
                }
                    );
                // responsável pelo cadastro
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.Contato",
                    Value     = "PAULO"
                }
                    );
                // protocolo
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.ProtocoloManager",
                    Value     = "999999"
                }
                    );
                // sistema/produto
                //https://dev.azure.com/gruposym/_apis/projects?api-version=5.1
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.Produto",
                    Value     = "NEFRODATA ACD"
                }
                    );
                //prioridade
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Custom.Prioridade",
                    Value     = "2 - Médio"
                }
                    );

                WorkItem workitem = await witClient.CreateWorkItemAsync(patchDocument, "Nefrodata", "Erro");
            }
            catch (AggregateException aex)
            {
                VssServiceException vssex = aex.InnerException as VssServiceException;
                if (vssex != null)
                {
                    Console.WriteLine(vssex.Message);
                }
            }
        }
        public void AddToListAppendWithSerialization()
        {
            var doc = new SimpleDTOWithNestedDTO()
            {
                SimpleDTO = new SimpleDTO()
                {
                    IntegerList = new List<int>() { 1, 2, 3 }
                }
            };


            // create patch
            JsonPatchDocument<SimpleDTOWithNestedDTO> patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
            patchDoc.Add<int>(o => o.SimpleDTO.IntegerList, 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument<SimpleDTOWithNestedDTO>>(serialized);



            deserialized.ApplyTo(doc);

            Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList);

        }
示例#39
0
        public async Task <WorkItemModel> CreateLinkedWorkitem(CreateWorkItem workItem)
        {
            WorkItemModel        workItemModel = new WorkItemModel();
            DevOpsConnectionPool poolObj       = _builderPool.Get();

            try
            {
                List <Params> ListParams = new List <Params>();
                //VssCredentials creds = new VssBasicCredential(string.Empty, personalaccesstoken);
                //VssConnection connection = new VssConnection(new Uri(c_collectionUri), creds);
                //ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();

                var workItemTrackingClient = poolObj.VssConnection.GetClient <WorkItemTrackingHttpClient>();

                JsonPatchDocument patchDocument = new JsonPatchDocument();
                Fields            field         = null;
                string            title         = $"Error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}.";
                string            bugtest       = $"Error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}. \n See attachment file for full error log.";
                string            description   = $"Error deploying solution {workItem.crmsolutioname} in {workItem.crmorgurl}. \n See attachment file for full error log.";

                switch (workItem.type.ToLower())
                {
                case "bug":
                    field = new Fields()
                    {
                        AssignedTo = workItem.assignedTo,
                        BugText    = bugtest,
                        Priority   = "2",
                        Title      = title,
                        Severity   = "2 - High"
                    };
                    ListParams.AddRange(GetBugFields(field));
                    break;

                default:    //Issue,Feature,Task
                    field = new Fields()
                    {
                        AssignedTo  = workItem.assignedTo,
                        Description = description,
                        Priority    = "2",
                        Title       = title,
                        Severity    = "2 - High"
                    };
                    ListParams.AddRange(GetTaskIssueFeatureFields(field));
                    break;
                }

                foreach (var item in ListParams)//there will be one type of witalways
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                        Path      = item.Path,
                        Value     = item.Value,
                    }
                        );
                }

                if (workItem.parentWit > 0)
                {
                    /* patchDocument.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
                     * {
                     *   Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                     *   Path = "/fields/System.Title",
                     *   Value = "childWIT"
                     * });*/
                    patchDocument.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
                    {
                        Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel = "System.LinkTypes.Hierarchy-Reverse",
                            url = poolObj.VssConnection.Uri.AbsoluteUri + "/" + workItem.projectname + "/_apis/wit/workItems/" + workItem.parentWit
                        }
                    });
                }

                var workitem = await workItemTrackingClient.CreateWorkItemAsync(patchDocument, workItem.projectid, workItem.type);

                if (workitem != null)
                {
                    workItemModel.Id  = workitem.Id.Value;
                    workItemModel.url = workitem.Url;
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                _builderPool.Return(poolObj);
            }
            return(workItemModel);
        }
示例#40
0
        public void AddNewPropertyToExpandoOjectInTypedObject()
        {
            var doc = new NestedDTO()
            {
                DynamicProperty = new ExpandoObject()
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("DynamicProperty/NewInt", 1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal(1, doc.DynamicProperty.NewInt);
        }
        public void AddToListInvalidPositionTooSmall()
        {

            var doc = new SimpleDTOWithNestedDTO()
          {
              SimpleDTO = new SimpleDTO()
              {
                  IntegerList = new List<int>() { 1, 2, 3 }
              }
          };


            // create patch
            JsonPatchDocument<SimpleDTOWithNestedDTO> patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
            patchDoc.Add<int>(o => o.SimpleDTO.IntegerList, 4, -1);

            Assert.Throws<JsonPatchException>(() => { patchDoc.ApplyTo(doc); });

        }
示例#42
0
        public void AddResultsReplaceShouldFailOnAnonymousDueToNoSetter()
        {
            var doc = new
            {
                StringProperty = "A"
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("StringProperty", "B");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "The property at path '/StringProperty' could not be updated.",
                exception.Message);
        }
        public void AddToListAppend()
        {
            var doc = new SimpleDTOWithNestedDTO()
                {
                    SimpleDTO = new SimpleDTO()
                  {
                      IntegerList = new List<int>() { 1, 2, 3 }
                  }
                };


            // create patch
            JsonPatchDocument<SimpleDTOWithNestedDTO> patchDoc = new JsonPatchDocument<SimpleDTOWithNestedDTO>();
            patchDoc.Add<int>(o => o.SimpleDTO.IntegerList, 4);

            patchDoc.ApplyTo(doc);

            Assert.Equal(new List<int>() { 1, 2, 3, 4 }, doc.SimpleDTO.IntegerList);

        }
示例#44
0
 public void btnStart_Click(object sender, EventArgs e)
 {
     try
     {
         VssConnection connection             = new VssConnection(new Uri("http://vmlvktfs1.dev.haav.com/DefaultCollection"), new VssCredentials());
         WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>();
         List <int> testcasesid = new List <int>();
         string[]   fileData    = File.ReadAllLines(txtPath.Text);
         foreach (string line in fileData)
         {
             testcasesid.Add(Convert.ToInt32(line));
         }
         lblStatus.Text = "Loading all work items";
         List <WorkItem> workitems = witClient.GetWorkItemsAsync(testcasesid).Result;
         lblStatus.Text = "All work items loaded successfully";
         if (chkIterationPath.Checked)
         {
             if (txtiteration.Text != "")
             {
                 foreach (var workitem in workitems)
                 {
                     //if (workitem.Fields["System.State"].ToString() == "Not Implemented")
                     //{
                     int itemID = Convert.ToInt32(workitem.Id);
                     lblStatus.Text = "Started Operation on Test Case " + itemID;
                     JsonPatchDocument patchDocument = new JsonPatchDocument();
                     patchDocument.Add(
                         new JsonPatchOperation()
                     {
                         Operation = Operation.Add,
                         Path      = "/fields/System.IterationPath",
                         Value     = txtiteration.Text
                     }
                         );
                     WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, itemID).Result;
                     lblStatus.Text = "Test Case with ID " + itemID + " Ieration path has been Updated";
                     ///System.Threading.Thread.Sleep(60000);
                     //Console.WriteLine(" {0}: {1}", workitem.Id, workitem.Fields["System.Title"]);
                     //}
                 }
             }
         }
         else if (chkAssignedTo.Checked)
         {
             if (txtassignedTo.Text != "")
             {
                 foreach (var workitem in workitems)
                 {
                     //if (workitem.Fields["System.State"].ToString() == "Not Implemented")
                     //{
                     int itemID = Convert.ToInt32(workitem.Id);
                     lblStatus.Text = "Started Operation on Test Case " + itemID;
                     JsonPatchDocument patchDocument = new JsonPatchDocument();
                     patchDocument.Add(
                         new JsonPatchOperation()
                     {
                         Operation = Operation.Add,
                         Path      = "/fields/System.AssignedTo",
                         Value     = txtassignedTo.Text
                     }
                         );
                     WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, itemID).Result;
                     lblStatus.Text = "Test Case with ID " + itemID + " Assigned To has been Updated";
                     ///System.Threading.Thread.Sleep(60000);
                     //Console.WriteLine(" {0}: {1}", workitem.Id, workitem.Fields["System.Title"]);
                     //}
                 }
             }
         }
         else if (chkrhtxtbox.Checked)
         {
             //string[] RichTextBoxLines = rchtxtbox.Lines;
             if (rchtxtbox.Text != "")
             {
                 foreach (var workitem in workitems)
                 {
                     //if (workitem.Fields["System.State"].ToString() == "Not Implemented")
                     //{
                     string description = "";
                     if (workitem.Fields.ContainsKey("System.Description"))
                     {
                         description = workitem.Fields["System.Description"].ToString();
                     }
                     description = rchtxtbox.Text + description;
                     int itemID = Convert.ToInt32(workitem.Id);
                     lblStatus.Text = "Started Operation on Test Case " + itemID;
                     JsonPatchDocument patchDocument = new JsonPatchDocument();
                     patchDocument.Add(
                         new JsonPatchOperation()
                     {
                         Operation = Operation.Add,
                         Path      = "/fields/System.Description",
                         Value     = description
                     }
                         );
                     WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, itemID).Result;
                     lblStatus.Text = "Test Case with ID " + itemID + " Description path has been Updated";
                     ///System.Threading.Thread.Sleep(60000);
                     //Console.WriteLine(" {0}: {1}", workitem.Id, workitem.Fields["System.Title"]);
                     //}
                 }
             }
         }
         else if (chkareapath.Checked)
         {
             //string[] RichTextBoxLines = rchtxtbox.Lines;
             if (txtarepath.Text != "")
             {
                 foreach (var workitem in workitems)
                 {
                     int itemID = Convert.ToInt32(workitem.Id);
                     lblStatus.Text = "Started Operation on Test Case " + itemID;
                     JsonPatchDocument patchDocument = new JsonPatchDocument();
                     patchDocument.Add(
                         new JsonPatchOperation()
                     {
                         Operation = Operation.Add,
                         Path      = "/fields/System.AreaPath",
                         Value     = txtarepath.Text
                     }
                         );
                     WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, itemID).Result;
                     lblStatus.Text = "Test Case with ID " + itemID + " Area path has been Updated";
                     ///System.Threading.Thread.Sleep(60000);
                     //Console.WriteLine(" {0}: {1}", workitem.Id, workitem.Fields["System.Title"]);
                     //}
                 }
             }
         }
         else
         {
             foreach (var workitem in workitems)
             {
                 if (workitem.Fields["System.State"].ToString() == "Not Implemented")
                 {
                     int itemID = Convert.ToInt32(workitem.Id);
                     lblStatus.Text = "Started Operation on Test Case " + itemID;
                     JsonPatchDocument patchDocument = new JsonPatchDocument();
                     patchDocument.Add(
                         new JsonPatchOperation()
                     {
                         Operation = Operation.Add,
                         Path      = "/fields/System.State",
                         Value     = "Ready for Test"
                     }
                         );
                     WorkItem result = witClient.UpdateWorkItemAsync(patchDocument, itemID).Result;
                     lblStatus.Text = "Test Case with ID " + itemID + " Status has been Updated";
                     ///System.Threading.Thread.Sleep(60000);
                     //Console.WriteLine(" {0}: {1}", workitem.Id, workitem.Fields["System.Title"]);
                 }
             }
         }
         lblStatus.Text = "All Test Cases Updated Successfully";
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.ToString());
     }
 }
        public async Task <TestRunResponse> RecordTestRunEndAsync(TestCaseInfo testCase, TestRunOutcome outcome,
                                                                  string errorMessage, IEnumerable <string> impactFiles, IEnumerable <string> impactMethods)
        {
            var patch = new JsonPatchDocument <TestRunRequest>();

            patch.Add(r => r.State, TestRunState.Finished);
            patch.Add(r => r.Outcome, outcome);
            patch.Add(r => r.FinishTime, DateTime.Now);
            patch.Add(r => r.ErrorMessage, errorMessage);
            var runResponse = await _client.PatchTestRunAsync(_session.Id, testCase.TestRunId, patch);

            _logger.Info("Test run finished: " + ObjToString(runResponse));

            List <CodeSignature> codeSignatures = new List <CodeSignature>();

            if (impactFiles != null)
            {
                codeSignatures.AddRange(
                    impactFiles.Select(f => new CodeSignature(f, CodeSignatureUtils.CalculateSignature(f), CodeSignatureType.File)));
            }
            if (impactMethods != null)
            {
                codeSignatures.AddRange(
                    impactMethods.Select(f => new CodeSignature(f, CodeSignatureUtils.CalculateSignature(f), CodeSignatureType.Method)));
            }

            var impactRequest = new TestCaseImpactUpdateRequest()
            {
                ProductLine    = _productLine,
                CodeSignatures = codeSignatures
            };

            var impactDataCount = codeSignatures.Count;

            LogDebug("Updating test impact information. Number of files/methods (code signatures): " + impactDataCount);
            if (impactDataCount == 0)
            {
                LogDebug("(No impact data is available)");
            }

            Exception impactUpdateException = null;

            try
            {
                await _client.UpdateTestImpactAsync(testCase.Id, impactRequest);
            }
            catch (Exception ex)
            {
                impactUpdateException = ex;
                _logger.Error("Updating test case impact data failed:\r\n" + ex.ToString());
            }

            var lastStateRequest = new TestLastStateUpdateRequest()
            {
                ProductLine      = _productLine,
                TestRunSessionId = _session.Id,
                Outcome          = outcome
            };

            if (impactUpdateException != null)
            {
                lastStateRequest.DictatedRunReason = RunReason.ImpactUpdateFailed;
                _logger.Warn("Test case will be run again next time.");
            }

            LogDebug($"Updating test last state. Azure Test Case Id: {testCase.AzureTestCaseId}, Outcome: {outcome}");

            await _client.UpdateTestLastStateAsync(testCase.Id, lastStateRequest);

            return(runResponse);
        }
示例#46
0
        public void ShouldNotBeAbleToAddToNonExistingPropertyThatIsNotTheRoot()
        {
            //Adding to a Nonexistent Target
            //
            //   An example target JSON document:
            //   { "foo": "bar" }
            //   A JSON Patch document:
            //   [
            //        { "op": "add", "path": "/baz/bat", "value": "qux" }
            //      ]
            //   This JSON Patch document, applied to the target JSON document above,
            //   would result in an error (therefore, it would not be applied),
            //   because the "add" operation's target location that references neither
            //   the root of the document, nor a member of an existing object, nor a
            //   member of an existing array.

            var doc = new NestedDTO()
            {
                DynamicProperty = new ExpandoObject()
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("DynamicProperty/OtherProperty/IntProperty", 1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "The property at path '/DynamicProperty/OtherProperty/IntProperty' could not be added.",
                exception.Message);
        }
示例#47
0
        public void AddNewPropertyToTypedObjectInExpandoObject()
        {
            dynamic dynamicProperty = new ExpandoObject();
            dynamicProperty.StringProperty = "A";

            var doc = new NestedDTO()
            {
                DynamicProperty = dynamicProperty
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("DynamicProperty/StringProperty", "B");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal("B", doc.DynamicProperty.StringProperty);
        }
示例#48
0
        private static async Task CreateWorkItem(
            WorkItemTrackingHttpClient client,
            string type,
            Issue jira,
            string parentKey,
            string title,
            string description,
            string state,
            params JsonPatchOperation[] fields)
        {
            // Short-circuit if we've already processed this item.
            if (Migrated.ContainsKey(jira.Key.Value))
            {
                return;
            }

            var vsts = new JsonPatchDocument
            {
                new JsonPatchOperation
                {
                    Path  = "/fields/System.State",
                    Value = state
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.CreatedBy",
                    Value = ResolveUser(jira.Reporter)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.CreatedDate",
                    Value = jira.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.ChangedBy",
                    Value = ResolveUser(jira.Reporter)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.ChangedDate",
                    Value = jira.Created.Value.ToUniversalTime()
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.Title",
                    Value = title
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.Description",
                    Value = description
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.Priority",
                    Value = ResolvePriority(jira.Priority)
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ClosedDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.FinishDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ResolvedDate",
                    Value = jira.ResolutionDate
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Common.ResolvedReason",
                    Value = jira.Resolution?.Name
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.IterationPath",
                    Value = ResolveIteration(jira.CustomFields["Sprint"]?.Values, config["AzureDevOps:Project"])
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.StoryPoints",
                    Value = jira.CustomFields["Story Points"]?.Values[0]
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/Microsoft.VSTS.Scheduling.Effort",
                    Value = jira.CustomFields["Story Points"]?.Values[0]
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.AreaPath",
                    Value = ResolveAreaPath(jira.CustomFields["DC Team"]?.Values[0], config["AzureDevOps:Project"])
                },
                new JsonPatchOperation
                {
                    Path  = "/fields/System.AssignedTo",
                    Value = ResolveUser(jira.Assignee)
                }
            }
            ;

            if (parentKey != null)
            {
                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/relations/-",
                    Value = new WorkItemRelation
                    {
                        Rel = "System.LinkTypes.Hierarchy-Reverse",
                        Url = $"https://{config["AzureDevOps:Url"]}/_apis/wit/workItems/{Migrated[parentKey]}"
                    }
                });
            }

            if (jira.Labels.Any())
            {
                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/fields/System.Tags",
                    Value = jira.Labels.Aggregate("", (l, r) => $"{l};{r}").Trim(';', ' ')
                });
            }

            foreach (var attachment in await jira.GetAttachmentsAsync())
            {
                var path = Path.GetTempFileName();
                attachment.Download(path);

                await using var stream = new MemoryStream(await File.ReadAllBytesAsync(path));

                var uploaded = await client.CreateAttachmentAsync(stream, config["AzureDevOps:Project"], fileName : attachment.FileName);

                vsts.Add(new JsonPatchOperation
                {
                    Path  = "/relations/-",
                    Value = new WorkItemRelation
                    {
                        Rel = "AttachedFile",
                        Url = uploaded.Url
                    }
                });

                File.Delete(path);
            }

            var all = vsts.Concat(fields)
                      .Where(p => p.Value != null)
                      .ToList();

            vsts = new JsonPatchDocument();
            vsts.AddRange(all);
            var workItem = await client.CreateWorkItemAsync(vsts, config["AzureDevOps:Project"], type, bypassRules : true);

            AddMigrated(jira.Key.Value, workItem.Id.Value);

            await CreateComments(client, workItem.Id.Value, jira);

            Console.WriteLine($"Added {type}: {jira.Key}{title}");
        }
示例#49
0
        /// <summary>
        /// Creates a JSON PatchDocument to update the state of the server-side WorkItem.
        /// </summary>
        /// <returns>JSON document</returns>
        internal JsonPatchDocument CreatePatchDocument()
        {
            var document = new JsonPatchDocument();

            ProcessFieldProperties((fieldInfo, initialValue, currentValue, changed) =>
            {
                if (changed)
                {
                    JsonPatchOperation operation;
                    if (currentValue == null)
                    {
                        operation = new JsonPatchOperation
                        {
                            Operation = Operation.Remove,
                            Path      = $"/fields/{fieldInfo.FieldName}"
                        };
                    }
                    else if (initialValue == null)
                    {
                        operation = new JsonPatchOperation
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/{fieldInfo.FieldName}",
                            Value     = currentValue.ToString()
                        };
                    }
                    else
                    {
                        operation = new JsonPatchOperation
                        {
                            Operation = Operation.Replace,
                            Path      = $"/fields/{fieldInfo.FieldName}",
                            Value     = currentValue.ToString()
                        };
                    }
                    document.Add(operation);
                }
                return(true);
            });

            if (addComments != null)
            {
                document.Add(new JsonPatchOperation
                {
                    Operation = Operation.Add,
                    Path      = $"/fields/System.History",
                    Value     = addComments.ToString()
                });
            }

            if (document.Count > 0)
            {
                if (witModel != null)
                {
                    document.Insert(0, new JsonPatchOperation
                    {
                        Operation = Operation.Test,
                        Path      = "/rev",
                        Value     = Revision
                    });
                }
                return(document);
            }

            return(null);
        }
示例#50
0
        public static WorkItem CreateBug(string title, string stepsToReproduce, string description, List <string> filePathsToBeAttached = null)
        {
            var credentials = new VssBasicCredential(string.Empty, _personalAccessToken);

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.Title",
                Value     = title,
            });

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.TCM.SystemInfo",
                Value     = description,
            });

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.TCM.ReproSteps",
                Value     = stepsToReproduce,
            });

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Common.Priority",
                Value     = ConfigurationService.GetSection <AzureDevOpsBugReportingSettings>().DefaultPriority,
            });

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/Microsoft.VSTS.Common.Severity",
                Value     = ConfigurationService.GetSection <AzureDevOpsBugReportingSettings>().DefaultSeverity,
            });

            try
            {
                using var httpClient = new WorkItemTrackingHttpClient(new Uri(_uri), credentials);
                var attachments = CreateAttachments(httpClient, filePathsToBeAttached);
                AddAttachmentRelationships(patchDocument, attachments);

                WorkItem result = httpClient.CreateWorkItemAsync(patchDocument, _project, "Bug").Result;
                return(result);
            }
            catch
            {
                return(null);
            }

            return(null);
        }
示例#51
0
        public void AddToExistingPropertyOnNestedObject()
        {
            dynamic doc = new
            {
                Test = 1,
                nested = new NestedDTO()
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("Nested/StringProperty", "A");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal("A", doc.nested.StringProperty);
            Assert.Equal(1, doc.Test);
        }
        public async Task <bool> CreateIssue(Event <LogEventData> evt)
        {
            if (evt == null) //Not sure when or if this could happen?
            {
                return(false);
            }

            //If the event level is defined and it is not in the list do not log it
            if ((LogEventLevelList?.Count ?? 0) > 0 && !LogEventLevelList.Contains(evt.Data.Level))
            {
                return(false);
            }

            _step = "Beginning process";
            LogIfDebug(_step);
            var description = evt.Data.Exception ?? evt.Data.RenderedMessage;
            //var messageId = ComputeId(description);

            var connection = new VssConnection(new Uri(AzureDevOpsUrl), new VssBasicCredential(string.Empty, PersonalAccessToken));

            var workitemClient = await connection.GetClientAsync <WorkItemTrackingHttpClient>();

            WorkItemQueryResult workItemQueryResult = null;

            // Try to match an existing work item
            if (!string.IsNullOrEmpty(SeqEventField))
            {
                _step = "Querying existing work item";
                LogIfDebug(_step);
                Wiql wiql = new Wiql()
                {
                    Query = "Select [State], [Title] " +
                            "From WorkItems " +
                            "Where [" + SeqEventField + "] = '" + evt.Id + "' " +
                            "And [System.TeamProject] = '" + Project + "' " +
                            //"And [System.State] <> 'Closed' " +
                            "Order By [State] Asc, [Changed Date] Desc"
                };

                //execute the query to get the list of work items in teh results
                workItemQueryResult = await workitemClient.QueryByWiqlAsync(wiql);

                if (workItemQueryResult.WorkItems.Count() != 0)
                {
                    Log.Information("Duplicate DevOps item creation prevented for event id {id}", evt.Id);
                    return(false);
                }
            }

            _step = "Adding fields";
            LogIfDebug(_step);
            var document = new JsonPatchDocument();

            _step = "Adding title";
            string title = $"SEQ Event - {evt.Data.RenderedMessage}".TruncateWithEllipsis(255); //DevOps has max 255 character length for title

            if (!string.IsNullOrEmpty(Title))                                                   //User has defined their own title parsing
            {
                title = GetSeqMappedPropertyString(Title, evt).TruncateWithEllipsis(255);
            }
            document.Add(
                new JsonPatchOperation()
            {
                Path      = "/fields/System.Title",
                Operation = Operation.Add,
                Value     = title
            });

            document.Add(
                new JsonPatchOperation()
            {
                Path      = "/fields/System.AssignedTo",
                Operation = Operation.Add,
                Value     = AssignedTo ?? string.Empty
            });

            if (!ParentWorkItemLinkUrl.IsNullOrEmpty())
            {
                document.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/relations/-",
                    Value     = new
                    {
                        rel        = "System.LinkTypes.Hierarchy-Reverse",
                        url        = ParentWorkItemLinkUrl,
                        attributes = new
                        {
                            comment = "Seq Event Auto-Parent Link"
                        }
                    }
                }
                    );
            }

            if (!string.IsNullOrEmpty(SeqEventField))
            {
                _step = "Adding Seq ID mapping";
                LogIfDebug(_step);
                document.Add(new JsonPatchOperation()
                {
                    Path      = "/fields/" + SeqEventField,
                    Operation = Operation.Add,
                    Value     = evt.Id
                });
            }

            if (!string.IsNullOrEmpty(Tags))
            {
                _step = "Adding tags";
                LogIfDebug(_step);
                document.Add(new JsonPatchOperation()
                {
                    Path      = "/fields/Tags",
                    Operation = Operation.Add,
                    Value     = Tags //DevOps takes a comma seperated list without any alterations
                });
            }

            _step = "Setting description";
            LogIfDebug(_step);

            document.Add(
                new JsonPatchOperation()
            {
                Path      = $"/fields/{DescriptionDevOpsMappingField}",
                Operation = Operation.Add,
                Value     = RenderDescription(evt)
            });

            if (!string.IsNullOrEmpty(SeqToDevOpsMapping))
            {
                _step = "Setting Seq to DevOps property mappings";
                LogIfDebug(_step);
                var keyValuePairs = SeqToDevOpsMapping.ParseKeyValueArray();
                foreach (var value in keyValuePairs)
                {
                    if (evt.Data.Properties.ContainsKey(value.Key))
                    {
                        LogIfDebug("Setting Seq to DevOps Property: " + value.Value + " Value: " + value.Key);
                        document.Add(
                            new JsonPatchOperation()
                        {
                            Path      = $"/fields/{value.Value}",
                            Operation = Operation.Add,
                            Value     = evt.Data.Properties[value.Key]
                        });
                    }
                }
            }

            if (!string.IsNullOrEmpty(DevOpsMappings))
            {
                _step = "Setting DevOps static property mappings";
                LogIfDebug(_step);
                var keyValuePairs = DevOpsMappings.ParseKeyValueArray();
                foreach (var value in keyValuePairs)
                {
                    LogIfDebug("Setting DevOps Static Property: " + value.Key + " Value: " + value.Value);
                    document.Add(
                        new JsonPatchOperation()
                    {
                        Path      = $"/fields/{value.Key}",
                        Operation = Operation.Add,
                        Value     = value.Value
                    });
                }
            }

            if (!string.IsNullOrEmpty(AreaPath))
            {
                _step = "Setting Area Path";
                LogIfDebug(_step);
                document.Add(
                    new JsonPatchOperation()
                {
                    Path      = $"/fields/System.AreaPath",
                    Operation = Operation.Add,
                    Value     = AreaPath
                });
            }

            if (!string.IsNullOrEmpty(Iteration))
            {
                _step = "Setting Iteration";
                LogIfDebug(_step);
                document.Add(
                    new JsonPatchOperation()
                {
                    Path      = $"/fields/System.IterationPath",
                    Operation = Operation.Add,
                    Value     = Iteration
                });
            }

            _step = "Adding work item";
            LogIfDebug(_step);
            var workitem = await workitemClient.CreateWorkItemAsync(document, Project, DevOpsIssueType, false, true);

            _step = "Finished process";
            LogIfDebug(_step);
            return(true);
        }
示例#53
0
        public void AddToListInvalidPositionTooLarge()
        {
            var doc = new
            {
                IntegerList = new List<int>() { 1, 2, 3 }
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("IntegerList/4", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            var exception = Assert.Throws<JsonPatchException>(() =>
            {
                deserialized.ApplyTo(doc);
            });
            Assert.Equal(
                "For operation 'add' on array property at path '/IntegerList/4', the index is larger than the array size.",
                exception.Message);
        }
示例#54
0
        public IActionResult Post([FromBody] JObject payload)
        {
            string tags       = "";
            string authHeader = "";
            string pat        = "";

#if DEBUG
            isDebug = true;
#endif

            if (!isDebug)
            {
                tags       = Request.Headers.ContainsKey("Work-Item-Tags") ? Request.Headers["Work-Item-Tags"] : new StringValues("");
                authHeader = Request.Headers.ContainsKey("Authorization") ? Request.Headers["Authorization"] : new StringValues("");

                if (!authHeader.StartsWith("Basic"))
                {
                    return(new StandardResponseObjectResult("missing basic authorization header", StatusCodes.Status401Unauthorized));
                }

                //get pat from basic authorization header. This was set in the web hook
                pat = this.GetPersonalAccessToken(authHeader);
            }

            PayloadViewModel vm = this.BuildPayloadViewModel(payload);

            //make sure pat is not empty, if it is, pull from appsettings
            vm.pat = (!string.IsNullOrEmpty(pat)) ? pat : _appSettings.Value.AzureDevOpsToken;

            if (string.IsNullOrEmpty(vm.pat))
            {
                return(new StandardResponseObjectResult("missing pat from authorization header and appsettings", StatusCodes.Status404NotFound));
            }

            if (vm.eventType != "workitem.created")
            {
                return(new OkResult());
            }

            if (vm.id == -1)
            {
                return(new OkResult());
            }

            JsonPatchDocument patchDocument = new JsonPatchDocument();

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Test,
                Path      = "/rev",
                Value     = (vm.rev + 1).ToString()
            }
                );

            if (string.IsNullOrEmpty(vm.assignedTo))
            {
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.AssignedTo",
                    Value     = vm.createdBy
                }
                    );
            }

            if (!string.IsNullOrEmpty(tags))
            {
                patchDocument.Add(
                    new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/System.Tags",
                    Value     = tags
                }
                    );
            }

            patchDocument.Add(
                new JsonPatchOperation()
            {
                Operation = Operation.Add,
                Path      = "/fields/System.IterationPath",
                Value     = vm.teamProject
            }
                );

            var result = _workItemRepo.UpdateWorkItem(patchDocument, vm);

            return((result != null) ? new OkResult() : new StatusCodeResult(500));
        }
示例#55
0
        public void ShouldAddToListWithDifferentCase()
        {
            var doc = new
            {
                IntegerList = new List<int>() { 1, 2, 3 }
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("integerlist/0", 4);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal(new List<int>() { 4, 1, 2, 3 }, doc.IntegerList);
        }
        public async Task <WorkItemModel> UpdateWorkItem(WorkItemModel workItemModel)
        {
            using (Logger.BeginScopeContext(nameof(UpdateWorkItem)))
            {
                AttachmentReference attachmentReference = null;
                string attachmentText = workItemModel.Attachment?.Text;
                if (!string.IsNullOrEmpty(attachmentText))
                {
                    using (var stream = new MemoryStream())
                        using (var writer = new StreamWriter(stream))
                        {
                            writer.Write(attachmentText);
                            writer.Flush();
                            stream.Position = 0;
                            try
                            {
                                attachmentReference = await _witClient.CreateAttachmentAsync(
                                    stream,
                                    fileName : workItemModel.Attachment.Name);
                            }
                            catch
                            {
                                // Implement simple, sensible logging mechanism
                                //
                                // https://github.com/microsoft/sarif-sdk/issues/1771
                                throw;
                            }
                        }
                }

                var patchDocument = new JsonPatchDocument();

                if (attachmentReference != null)
                {
                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Remove,
                        Path      = $"/relations/0"
                    });

                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/relations/-",
                        Value     = new
                        {
                            rel = "AttachedFile",
                            attachmentReference.Url
                        }
                    });

                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.History}",
                        Value     = workItemModel.CommentOrDiscussion
                    });

                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.ReproSteps}",
                        Value     = workItemModel.BodyOrDescription
                    });
                }

                try
                {
                    if (int.TryParse(workItemModel.Uri.OriginalString.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault(), out int workItemId))
                    {
                        Logger.LogInformation($"Updating work item id: {workItemId}");
                        _ = await _witClient.UpdateWorkItemAsync(patchDocument, id : workItemId);

                        Logger.LogInformation($"UPDATED: {workItemModel.Uri}");
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);
                    this.Logger.LogError(e, "Updating work item: {workItemModel.Title}", workItemModel.Title);

                    if (patchDocument != null)
                    {
                        string patchJson = JsonConvert.SerializeObject(patchDocument, Formatting.Indented);
                        Console.Error.WriteLine(patchJson);
                    }
                }

                return(workItemModel);
            }
        }
示例#57
0
        public void ShouldReplacePropertyWithDifferentCase()
        {
            dynamic doc = new ExpandoObject();
            doc.StringProperty = "A";

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("stringproperty", "B");

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal("B", doc.StringProperty);
        }
        public async Task <WorkItemModel> CreateWorkItem(WorkItemModel workItemModel)
        {
            using (Logger.BeginScopeContext(nameof(CreateWorkItem)))
            {
                //TODO: Provide helper that generates useful attachment name from filed bug.
                //      This helper should be common to both ADO and GH filers. The implementation
                //      should work like this: the filer should prefix the proposed file name with
                //      the account and project and number of the filed work item. So an attachment
                //      name of Scan.sarif would be converted tO
                //
                //         MyAcct_MyProject_WorkItem1000_Scan.sarif
                //
                //      The GH filer may prefer to use 'issue' instead:
                //
                //         myowner_my-repo_Issue1000_Scan.sarif
                //
                //      The common helper should preserve casing choices in the account/owner and
                //      project/repo information that's provided.
                //
                //      Obviously, this proposal requires a change below to first file the bug,
                //      then compute the file name and add the attachment.
                //
                //      https://github.com/microsoft/sarif-sdk/issues/1753

                AttachmentReference attachmentReference = null;
                string attachmentText = workItemModel.Attachment?.Text;
                if (!string.IsNullOrEmpty(attachmentText))
                {
                    using (var stream = new MemoryStream())
                        using (var writer = new StreamWriter(stream))
                        {
                            writer.Write(attachmentText);
                            writer.Flush();
                            stream.Position = 0;
                            try
                            {
                                attachmentReference = await _witClient.CreateAttachmentAsync(
                                    stream,
                                    fileName : workItemModel.Attachment.Name);
                            }
                            catch
                            {
                                // Implement simple, sensible logging mechanism
                                //
                                // https://github.com/microsoft/sarif-sdk/issues/1771
                                throw;
                            }
                        }
                }

                var patchDocument = new JsonPatchDocument
                {
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Title}",
                        Value     = workItemModel.Title
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Area}",
                        Value     = workItemModel.Area ?? workItemModel.RepositoryOrProject
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.Tags}",
                        Value     = string.Join(",", workItemModel.LabelsOrTags)
                    },
                    new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/fields/{AzureDevOpsFieldNames.ReproSteps}",
                        Value     = workItemModel.BodyOrDescription
                    }
                };

                if (workItemModel.CustomFields != null)
                {
                    foreach (KeyValuePair <string, string> customField in workItemModel.CustomFields)
                    {
                        patchDocument.Add(new JsonPatchOperation
                        {
                            Operation = Operation.Add,
                            Path      = $"/fields/{customField.Key}",
                            Value     = customField.Value
                        });
                    }
                }

                if (attachmentReference != null)
                {
                    patchDocument.Add(
                        new JsonPatchOperation
                    {
                        Operation = Operation.Add,
                        Path      = $"/relations/-",
                        Value     = new
                        {
                            rel = "AttachedFile",
                            attachmentReference.Url
                        }
                    });
                }

                WorkItem workItem = null;

                try
                {
                    // TODO: Make work item kind configurable for Azure DevOps filer
                    //
                    // https://github.com/microsoft/sarif-sdk/issues/1770
                    string workItemKind = "Bug";

                    Logger.LogInformation($"Creating work item: {workItemModel.Title}");
                    workItem = await _witClient.CreateWorkItemAsync(patchDocument, project : workItemModel.RepositoryOrProject, workItemKind);

                    workItemModel.Uri = new Uri(workItem.Url, UriKind.Absolute);

                    workItemModel.HtmlUri = new Uri(((ReferenceLink)workItem.Links.Links["html"]).Href, UriKind.Absolute);
                    Logger.LogInformation($"CREATED: {workItemModel.HtmlUri}");
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);
                    this.Logger.LogError(e, "Creating work item: {workItemModel.Title}", workItemModel.Title);

                    if (patchDocument != null)
                    {
                        string patchJson = JsonConvert.SerializeObject(patchDocument, Formatting.Indented);
                        Console.Error.WriteLine(patchJson);
                    }
                }

                return(workItemModel);
            }
        }
示例#59
0
        public void AddNewPropertyToExpandoOject()
        {
            dynamic doc = new
            {
                Test = 1,
                nested = new ExpandoObject()
            };

            // create patch
            JsonPatchDocument patchDoc = new JsonPatchDocument();
            patchDoc.Add("Nested/NewInt", 1);

            var serialized = JsonConvert.SerializeObject(patchDoc);
            var deserialized = JsonConvert.DeserializeObject<JsonPatchDocument>(serialized);

            deserialized.ApplyTo(doc);

            Assert.Equal(1, doc.nested.NewInt);
            Assert.Equal(1, doc.Test);
        }
示例#60
0
        public AzureTestCase AssociateAutomationToExistingTestCase(string workItemId, string testName, string testProjectName, string requirementUrl)
        {
            var uri = new Uri(_uri);

            var           credentials = new VssBasicCredential(string.Empty, _personalAccessToken);
            VssConnection connection  = new VssConnection(uri, credentials);
            WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>();

            var existingItem  = workItemTrackingHttpClient.GetWorkItemAsync(workItemId.ToInt(), expand: WorkItemExpand.Relations).Result;
            var patchDocument = new JsonPatchDocument();

            if (existingItem.Fields.ContainsKey("Microsoft.VSTS.TCM.AutomatedTestName"))
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Replace,
                    Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestName",
                    Value     = testName,
                });
            }
            else
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestName",
                    Value     = testName,
                });
            }

            if (existingItem.Fields.ContainsKey("Microsoft.VSTS.TCM.AutomatedTestStorage"))
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Replace,
                    Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestStorage",
                    Value     = testProjectName,
                });
            }
            else
            {
                patchDocument.Add(new JsonPatchOperation()
                {
                    Operation = Operation.Add,
                    Path      = "/fields/Microsoft.VSTS.TCM.AutomatedTestStorage",
                    Value     = testProjectName,
                });
            }

            if (!string.IsNullOrEmpty(requirementUrl))
            {
                if (existingItem.Relations == null)
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "System.LinkTypes.Hierarchy-Reverse",
                            url        = requirementUrl,
                            attributes = new Dictionary <string, object>()
                            {
                                { "isLocked", false },
                                { "name", "Parent" },
                                { "comment", "added automatically" },
                            },
                        },
                    });
                }
                else if (!existingItem.Relations.Any(x => x.Url.Equals(requirementUrl)))
                {
                    patchDocument.Add(
                        new JsonPatchOperation()
                    {
                        Operation = Operation.Add,
                        Path      = "/relations/-",
                        Value     = new
                        {
                            rel        = "System.LinkTypes.Hierarchy-Reverse",
                            url        = requirementUrl,
                            attributes = new Dictionary <string, object>()
                            {
                                { "isLocked", false },
                                { "name", "Parent" },
                                { "comment", "added automatically" },
                            },
                        },
                    });
                }
            }

            try
            {
                WorkItem result = workItemTrackingHttpClient.UpdateWorkItemAsync(patchDocument, workItemId.ToInt()).Result;

                return(ConvertWorkItemToAzureTestCase(result));
            }
            catch (AggregateException ex)
            {
                Debug.WriteLine("Error updating test case: {0}", ex.InnerException.Message);
                return(null);
            }
        }