예제 #1
0
        protected override QueryHierarchyItem DoNewItem()
        {
            var itemType = GetParameter <string>("ItemType").ToLower();
            var isFolder = itemType.Equals("folder");

            var item  = isFolder? GetParameter <string>("Folder"): GetParameter <string>("Query");
            var wiql  = GetParameter <string>("Wiql");
            var scope = GetParameter <string>("Scope").Equals("Personal") ? "My Queries" : "Shared Queries";
            var force = GetParameter <bool>("Force");

            var(_, tp) = GetCollectionAndProject();

            var fullPath   = NodeUtil.NormalizeNodePath(item, tp.Name, scope, includeScope: true, separator: '/');
            var queryName  = Path.GetFileName(fullPath);
            var parentPath = Path.GetDirectoryName(fullPath);

            var existingItem = GetItem <QueryHierarchyItem>();

            if (existingItem != null && isFolder)
            {
                Log("Folder already exists.");

                if (!force)
                {
                    throw new Exception($"A folder with the specified name '{fullPath}' already exists.");
                }

                return(existingItem);
            }

            if (!ShouldProcess(tp, $"{(existingItem == null ? "Create" : "Overwrite")} " +
                               $"work item {itemType} '{fullPath}'"))
            {
                return(null);
            }

            var client = GetClient <WorkItemTrackingHttpClient>();

            var newItem = new QueryHierarchyItem()
            {
                Name     = queryName,
                Path     = parentPath,
                IsFolder = isFolder,
                Wiql     = wiql
            };

            var parentFolder = GetItem <QueryHierarchyItem>(new{ Folder = parentPath, ItemType = "Folder" }) ??
                               NewItem <QueryHierarchyItem>(new { Folder = parentPath, ItemType = "Folder" });

            this.Log($"Creating query '{queryName}' in folder '{parentPath}'");

            var result = client.CreateQueryAsync(newItem, tp.Name, parentFolder.Id.ToString())
                         .GetResult($"Error creating new work item {itemType} '{fullPath}'");

            return(result);
        }
예제 #2
0
        //TODO: Inject TeamProject
        //TODO: Use NormalizePath

        protected override IEnumerable <WebApiFolder> DoGetItems()
        {
            var folder     = GetParameter <object>("Folder");
            var queryOrder = GetParameter <FolderPathQueryOrder>("QueryOrder");

            while (true)
            {
                switch (folder)
                {
                case WebApiFolder f:
                {
                    yield return(f);

                    yield break;
                }

                case string s when s.IsWildcard():
                {
                    var client = GetClient <ReleaseHttpClient>();
                    var(_, tp) = GetCollectionAndProject();
                    s          = NodeUtil.NormalizeNodePath(s, tp.Name);
                    var folders = client.GetFoldersAsync(tp.Name, null, queryOrder)
                                  .GetResult($"Error getting folders matching {s}");

                    foreach (var i in folders
                             .Where(f => f.Path.IsLike(s) || GetFolderName(f).IsLike(s)))
                    {
                        yield return(i);
                    }

                    yield break;
                }

                case string s:
                {
                    var client = GetClient <ReleaseHttpClient>();
                    var(_, tp) = GetCollectionAndProject();
                    var f = client.GetFoldersAsync(tp.Name, NodeUtil.NormalizeNodePath(s, tp.Name), queryOrder)
                            .GetResult($"Error getting folders matching {s}").FirstOrDefault();

                    if (f != null)
                    {
                        yield return(f);
                    }

                    yield break;
                }

                default:
                {
                    throw new ArgumentException($"Invalid or non-existent pipeline folder '{folder}'");
                }
                }
            }
        }
예제 #3
0
        protected override IEnumerable <QueryHierarchyItem> DoGetItems()
        {
            var itemType = GetParameter <string>("ItemType").ToLower();
            var isFolder = itemType.Equals("folder");

            var item  = isFolder ? GetParameter <string>("Folder") : GetParameter <string>("Query");
            var scope = GetParameter <string>(nameof(GetWorkItemQuery.Scope));

            var(_, tp) = GetCollectionAndProject();
            var client = GetClient <Microsoft.TeamFoundation.WorkItemTracking.WebApi.WorkItemTrackingHttpClient>();

            while (true)
            {
                switch (item)
                {
                case string s:
                {
                    var result = client.GetQueriesAsync(tp.Name, QueryExpand.All, 2)
                                 .GetResult("Error getting work item query root folders")
                                 .Where(q => scope.Equals("Both") || q.IsPublic == scope.Equals("Shared"))
                                 .ToList();

                    foreach (var rootFolder in result)
                    {
                        if (rootFolder.Name.Equals(s) && isFolder)
                        {
                            yield return(rootFolder);

                            yield break;
                        }

                        var path = NodeUtil.NormalizeNodePath(s, tp.Name, rootFolder.Name, includeScope: true, separator: '/');

                        foreach (var c in GetItemsRecursively(rootFolder, path, tp.Name, itemType.Equals("query"), client))
                        {
                            yield return(c);
                        }
                    }
                    yield break;
                }

                default: throw new ArgumentException($"Invalid or non-exixtent query/folder '{item}'");
                }
            }
        }
예제 #4
0
        protected override WebApiFolder DoNewItem()
        {
            var(_, tp) = GetCollectionAndProject();
            var folder      = GetParameter <string>(nameof(NewReleaseDefinitionFolder.Folder));
            var description = GetParameter <string>(nameof(NewReleaseDefinitionFolder.Description));

            if (!ShouldProcess(tp, $"Create release folder '{folder}'"))
            {
                return(null);
            }

            var client    = GetClient <ReleaseHttpClient>();
            var newFolder = new WebApiFolder()
            {
                Description = description,
                Path        = NodeUtil.NormalizeNodePath(folder, tp.Name)
            };

            return(client.CreateFolderAsync(newFolder, tp.Name)
                   .GetResult($"Error creating folder '{folder}'"));
        }
예제 #5
0
        protected override ClassificationNode DoNewItem()
        {
            var node           = GetParameter <string>(nameof(NewClassificationNode.Node));
            var structureGroup = GetParameter <TreeStructureGroup>("StructureGroup");
            var force          = GetParameter <bool>(nameof(NewClassificationNode.Force));

            var(_, tp) = GetCollectionAndProject();
            var nodePath   = NodeUtil.NormalizeNodePath(node, tp.Name, structureGroup.ToString().TrimEnd('s'), false, false, true);
            var client     = GetClient <WorkItemTrackingHttpClient>();
            var parentPath = Path.GetDirectoryName(nodePath);
            var nodeName   = Path.GetFileName(nodePath);

            if (!ShouldProcess($"Team Project {tp.Name}", $"Create node '{nodePath}'"))
            {
                return(null);
            }

            if (!TestItem <ClassificationNode>(new { Node = parentPath }))
            {
                if (!force)
                {
                    this.Log($"Parent node '{parentPath}' does not exist");
                    throw new Exception($"Parent node '{parentPath}' does not exist. Check the path or use -Force the create any missing parent nodes.");
                }

                NewItem <ClassificationNode>(new { Node = parentPath });
            }

            var patch = new WorkItemClassificationNode()
            {
                Name = nodeName
            };

            var result = client.CreateOrUpdateClassificationNodeAsync(patch, tp.Name, structureGroup, parentPath)
                         .GetResult($"Error creating node {nodePath}");

            return(new ClassificationNode(result, tp.Name, client));
        }
예제 #6
0
        protected override TestPlan DoNewItem()
        {
            var testPlan      = GetParameter <string>(nameof(NewTestPlan.TestPlan));
            var owner         = GetParameter <string>(nameof(NewTestPlan.Owner));
            var areaPath      = GetParameter <string>(nameof(NewTestPlan.AreaPath), "\\");
            var iterationPath = GetParameter <string>(nameof(NewTestPlan.IterationPath), "\\");
            var startDate     = GetParameter <DateTime>(nameof(NewTestPlan.StartDate));
            var endDate       = GetParameter <DateTime>(nameof(NewTestPlan.EndDate));

            var(_, tp) = GetCollectionAndProject();

            var client = GetClient <TestPlanHttpClient>();

            return(client.CreateTestPlanAsync(new TestPlanCreateParams()
            {
                AreaPath = NodeUtil.NormalizeNodePath(areaPath, tp.Name, "Areas", includeTeamProject: true),
                Iteration = NodeUtil.NormalizeNodePath(iterationPath, tp.Name, "Iterations", includeTeamProject: true),
                Name = testPlan,
                // TODO: Owner = owner,
                StartDate = (startDate == DateTime.MinValue? (DateTime?)null: startDate),
                EndDate = (endDate == DateTime.MinValue? (DateTime?)null: endDate)
            }, tp.Name).GetResult($"Error creating test plan '{testPlan}'"));
        }
예제 #7
0
        protected override IEnumerable <ClassificationNode> DoGetItems()
        {
            var node           = GetParameter <object>(nameof(GetClassificationNode.Node));
            var structureGroup = GetParameter <TreeStructureGroup>("StructureGroup");

            var(_, tp) = this.GetCollectionAndProject();
            bool   done = false;
            string path = null;

            while (!done)
            {
                switch (node)
                {
                case WorkItemClassificationNode n:
                {
                    yield return(new ClassificationNode(n, tp.Name, null));

                    yield break;
                }

                case string s when s.Equals("\\") || s.Equals("/"):
                {
                    path = "\\";
                    done = true;
                    break;
                }

                case string s when !string.IsNullOrEmpty(s) && s.IsWildcard():
                {
                    path = NodeUtil.NormalizeNodePath(s, tp.Name, structureGroup.ToString().TrimEnd('s'), true, false, true, false, true);
                    done = true;
                    break;
                }

                case string s when !string.IsNullOrEmpty(s):
                {
                    path = NodeUtil.NormalizeNodePath(s, tp.Name, structureGroup.ToString().TrimEnd('s'), false, false, true, false, false);
                    done = true;
                    break;
                }

                default:
                {
                    throw new ArgumentException($"Invalid or non-existent node {node}");
                }
                }
            }

            var client = GetClient <WorkItemTrackingHttpClient>();
            int depth  = 1;

            if (path.IsWildcard())
            {
                depth = 2;
                Logger.Log($"Preparing to recursively search for pattern '{path}'");

                var root = new ClassificationNode(client.GetClassificationNodeAsync(tp.Name, structureGroup, "\\", depth)
                                                  .GetResult($"Error retrieving {structureGroup} from path '{path}'"),
                                                  tp.Name, client);

                foreach (var n in root.GetChildren(path, true))
                {
                    yield return(n);
                }

                yield break;
            }

            Logger.Log($"Getting {structureGroup} under path '{path}'");

            yield return(new ClassificationNode(client.GetClassificationNodeAsync(tp.Name, structureGroup, path, depth)
                                                .GetResult($"Error retrieving {structureGroup} from path '{path}'"), tp.Name, null));
        }
예제 #8
0
        protected override Models.Team DoSetItem()
        {
            var(tpc, tp, t) = GetCollectionProjectAndTeam();
            var description      = GetParameter <string>(nameof(SetTeam.Description));
            var defaultTeam      = GetParameter <bool>(nameof(SetTeam.Default));
            var defaultAreaPath  = GetParameter <string>(nameof(SetTeam.DefaultAreaPath));
            var areaPaths        = GetParameter <IEnumerable <string> >(nameof(SetTeam.AreaPaths));
            var backlogIteration = GetParameter <string>(nameof(SetTeam.BacklogIteration));
            var iterationPaths   = GetParameter <IEnumerable <string> >(nameof(SetTeam.IterationPaths));
            var defaultIteration = GetParameter <string>(nameof(SetTeam.DefaultIterationMacro));

            var teamClient    = GetClient <TeamHttpClient>();
            var projectClient = GetClient <ProjectHttpClient>();
            var workClient    = GetClient <WorkHttpClient>();

            // Set description

            if (HasParameter("Description") && ShouldProcess(t, $"Set team's description to '{description}'"))
            {
                teamClient.UpdateTeamAsync(new WebApiTeam()
                {
                    Description = description ?? string.Empty
                }, tp.Id.ToString(), t.Id.ToString())
                .GetResult($"Error setting team '{t.Name}''s description to '{description}'");
            }

            // Set default team

            if (defaultTeam && ShouldProcess(tp, $"Set team '{t.Name} as default'"))
            {
                throw new NotImplementedException("Set team as default is currently not supported");
            }

            // Set Team Field / Area Path settings

            var ctx            = new TeamContext(tp.Name, t.Name);
            var teamFieldPatch = new TeamFieldValuesPatch();

            if (!string.IsNullOrEmpty(defaultAreaPath) &&
                ShouldProcess(t, $"Set team's default area path (team field) to '{defaultAreaPath}'"))
            {
                if (tpc.IsHosted)
                {
                    this.Log("Conected to Azure DevOps Services. Treating Team Field Value as Area Path");
                    defaultAreaPath = NodeUtil.NormalizeNodePath(defaultAreaPath, tp.Name, "Areas", includeTeamProject: true);
                }

                if (areaPaths == null)
                {
                    this.Log("AreaPaths is empty. Adding DefaultAreaPath (TeamFieldValue) to AreaPaths as default value.");

                    areaPaths = new string[] { defaultAreaPath };
                }

                var area = new { Node = defaultAreaPath };

                if (!TestItem <Models.ClassificationNode>(area))
                {
                    NewItem <Models.ClassificationNode>(area);
                }

                this.Log($"Setting default area path (team field) to {defaultAreaPath}");

                teamFieldPatch.DefaultValue = defaultAreaPath;
            }

            if (areaPaths != null &&
                ShouldProcess(t, $"Set {string.Join(", ", areaPaths)} as team's area paths"))
            {
                var values = new List <TeamFieldValue>();

                foreach (var a in areaPaths)
                {
                    values.Add(new TeamFieldValue()
                    {
                        Value           = NodeUtil.NormalizeNodePath(a.TrimEnd('\\', '*'), tp.Name, scope: "Areas", includeTeamProject: true),
                        IncludeChildren = a.EndsWith("*")
                    });
                }

                teamFieldPatch.Values = values;

                workClient.UpdateTeamFieldValuesAsync(teamFieldPatch, ctx)
                .GetResult("Error applying team field value and/or area path settings");
            }

            // Set backlog and iteration path settings

            bool isDirty        = false;
            var  iterationPatch = new TeamSettingsPatch();

            if (backlogIteration != null &&
                ShouldProcess(t, $"Set the team's backlog iteration to '{backlogIteration}'"))
            {
                this.Log($"Setting backlog iteration to {backlogIteration}");

                var iteration = GetItem <Models.ClassificationNode>(new
                {
                    Node           = backlogIteration,
                    StructureGroup = TreeStructureGroup.Iterations
                });

                iterationPatch.BacklogIteration     =
                    iterationPatch.DefaultIteration =
                        iteration.Identifier;

                isDirty = true;
            }

            if (!string.IsNullOrEmpty(defaultIteration) &&
                ShouldProcess(t, $"Set the team's default iteration to '{defaultIteration}'"))
            {
                this.Log($"Setting default iteration to '{defaultIteration}'");

                if (!defaultIteration.StartsWith("@"))
                {
                    var iteration = GetItem <Models.ClassificationNode>(new
                    {
                        Node           = defaultIteration,
                        StructureGroup = TreeStructureGroup.Iterations
                    });

                    iterationPatch.DefaultIteration = iteration.Identifier;
                }
                else
                {
                    iterationPatch.DefaultIteration      = null;
                    iterationPatch.DefaultIterationMacro = defaultIteration;
                }

                isDirty = true;
            }

            if (isDirty)
            {
                workClient.UpdateTeamSettingsAsync(iterationPatch, ctx)
                .GetResult("Error applying iteration and/or board settings");
            }

            // TODO: Finish migration

            //         if (BacklogVisibilities && ShouldProcess(Team, $"Set the team"s backlog visibilities to {_DumpObj {BacklogVisibilities}}"))
            //         {
            //             this.Log($"Setting backlog iteration to {BacklogVisibilities}");
            //             patch.BacklogVisibilities = _NewDictionary @([string], [bool]) BacklogVisibilities

            //             isDirty = true
            //         }

            //         if (DefaultIterationMacro && ShouldProcess(Team, $"Set the team"s default iteration macro to {DefaultIterationMacro}"))
            //         {
            //             this.Log($"Setting default iteration macro to {DefaultIterationMacro}");
            //             patch.DefaultIterationMacro = DefaultIterationMacro

            //             isDirty = true
            //         }

            //         if (WorkingDays && ShouldProcess(Team, $"Set the team"s working days to {_DumpObj {WorkingDays}}"))
            //         {
            //             this.Log($"Setting working days to {{WorkingDays}|ConvertTo=-Json -Compress}");
            //             patch.WorkingDays = WorkingDays

            //             isDirty = true
            //         }

            //         if(BugsBehavior && ShouldProcess(Team, $"Set the team"s bugs behavior to {_DumpObj {BugsBehavior}}"))
            //         {
            //             this.Log($"Setting bugs behavior to {_DumpObj {BugsBehavior}}");
            //             patch.BugsBehavior = BugsBehavior

            //             isDirty = true
            //         }

            //         if(isDirty)
            //         {
            //             task = client.UpdateTeamSettingsAsync(patch, ctx)
            //             result = task.Result; if(task.IsFaulted) { _throw new Exception("Error applying iteration settings" task.Exception.InnerExceptions })
            //         }

            //         if(Passthru.IsPresent)
            //         {
            //             WriteObject(t); return;
            //         }
            //     }
            // }

            return(GetItem <Models.Team>());
        }