Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Formatting/PSDevOps.SharedQuery.format.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Write-FormatView -TypeName PSDevOps.SharedQuery -Property IsPublic, Path, Wiql -Wrap -GroupByProperty Project
70 changes: 68 additions & 2 deletions Get-ADOWorkItem.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@

# If provided, will only return the first N results from a query.
[Parameter(ParameterSetName='/{Organization}/{Project}/{Team}/_apis/wit/wiql',ValueFromPipelineByPropertyName)]
[Parameter(ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[Alias('Top')]
[uint32]
$First,
Expand All @@ -103,6 +104,33 @@
[switch]
$WorkItemType,

# If set, will return work item shared queries
[Parameter(Mandatory,ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[switch]
$SharedQuery,

# If set, will return shared queries that have been deleted.
[Parameter(ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[switch]
$IncludeDeleted,

# If provided, will return shared queries up to a given depth.
[Parameter(ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[ValidateRange(0,2)]
[int]
$Depth,

# If provided, will filter the shared queries returned
[Parameter(ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[int]
$SharedQueryFilter,

# Determines how data from shared queries will be expanded. By default, expands all data.
[Parameter(ParameterSetName='/{Organization}/{Project}/_apis/wit/queries',ValueFromPipelineByPropertyName)]
[ValidateSet('All','Clauses','Minimal','None', 'Wiql')]
[string]
$ExpandSharedQuery = 'All',

# One or more fields.
[Alias('Fields','Select')]
[string[]]
Expand Down Expand Up @@ -170,6 +198,31 @@
}
#endregion Output Work Item


#region ExpandSharedQueries
$expandSharedQueries = {
param([Parameter(ValueFromPipeline)]$node)
process {
if (-not $node) { return }
$node.pstypenames.clear()
foreach ($typeName in "$organization.SharedQuery",
"$organization.$Project.SharedQuery",
"PSDevOps.SharedQuery"
) {
$node.pstypenames.Add($typeName)
}
$node |
Add-Member NoteProperty Organization $organization -Force -PassThru |
Add-Member NoteProperty Project $Project -Force -PassThru |
Add-Member NoteProperty Server $Server -Force -PassThru
if ($node.haschildren) {
$node.children |
& $MyInvocation.MyCommand.ScriptBlock
}
}
}
#endregion ExpandSharedQueries

$allIDS = [Collections.ArrayList]::new()
}

Expand All @@ -181,6 +234,19 @@
$selfSplat.Query = "Select [System.ID] from WorkItems Where [System.Title] contains '$title'"
Get-ADOWorkItem @selfSplat
}
elseif ($psCmdlet.ParameterSetName -eq '/{Organization}/{Project}/_apis/wit/queries') {
$myInvokeParams = @{} + $invokeParams
$myInvokeParams.Url = "$Server".TrimEnd('/') + $psCmdlet.ParameterSetName

$myInvokeParams.QueryParameter = @{'$expand'= $ExpandSharedQuery}
$myInvokeParams.UrlParameter = @{} + $psBoundParameters
if ($IncludeDeleted) { $myInvokeParams.QueryParameter.'$includeDeleted' = $true }
if ($First) { $myInvokeParams.QueryParameter.'$top' = $First}
if ($Depth) { $myInvokeParams.QueryParameter.'$depth' = $Depth}
$myInvokeParams.Property = @{Organization = $Organization;Project=$Project}
Invoke-ADORestAPI @myInvokeParams | & $expandSharedQueries
return
}
elseif (
$PSCmdlet.ParameterSetName -in
'/{Organization}/{Project}/_apis/wit/workitems/{id}',
Expand All @@ -198,7 +264,7 @@
elseif ($PSCmdlet.ParameterSetName -eq '/{Organization}/{Project}/{Team}/_apis/wit/wiql')
{
$uri = "$Server".TrimEnd('/') + (. $ReplaceRouteParameter $PSCmdlet.ParameterSetName) + '?'
$uri +=
$uri +=
@(if ($First) {
"`$top=$First"
}
Expand All @@ -214,7 +280,6 @@
$realQuery += ' AND '
}


$realQuery +=
@(
if ($Project) {
Expand Down Expand Up @@ -261,6 +326,7 @@
"api-version=$ApiVersion"
}
$invokeParams.Uri = $uri
$invokeParams.Property = @{Organization = $Organization}
$workItemTypes = Invoke-ADORestAPI @invokeParams
$workItemTypes -replace '"":', '"_blank":' |
ConvertFrom-Json |
Expand Down
131 changes: 121 additions & 10 deletions New-ADOWorkItem.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,55 @@
.Link
Invoke-ADORestAPI
#>
[CmdletBinding(DefaultParameterSetName='ByID',SupportsShouldProcess=$true)]
[CmdletBinding(DefaultParameterSetName='WorkItem',SupportsShouldProcess=$true)]
[OutputType('PSDevOps.WorkItem')]
param(
# The InputObject
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[PSObject]
$InputObject,

# The type of the work item.
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[Parameter(Mandatory, ParameterSetName='WorkItem',ValueFromPipelineByPropertyName)]
[Alias('WorkItemType')]
[string]
$Type,

# If set, will create a shared query for work items. The -InputObject will be passed to the body.
[Parameter(Mandatory,ParameterSetName='SharedQuery',ValueFromPipelineByPropertyName)]
[string]
$QueryName,

# If provided, will create shared queries beneath a given folder.
[Parameter(ParameterSetName='SharedQuery',ValueFromPipelineByPropertyName)]
[Parameter(ParameterSetName='SharedQueryFolder',ValueFromPipelineByPropertyName)]
[string]
$QueryPath,

# If provided, create a shared query with a given WIQL.
[Parameter(Mandatory, ParameterSetName='SharedQuery',ValueFromPipelineByPropertyName)]
[string]
$WIQL,

# If provided, the shared query created may be hierchical
[Parameter(ParameterSetName='SharedQuery',ValueFromPipelineByPropertyName)]
[ValidateSet('Flat','OneHop', 'Tree')]
[string]
$QueryType,

# The recursion option for use in a tree query.
[Parameter(ParameterSetName='SharedQuery',ValueFromPipelineByPropertyName)]
[ValidateSet('childFirst','parentFirst')]
[string]
$QueryRecursiveOption,

# If provided, create a shared query folder.
[Parameter(Mandatory, ParameterSetName='SharedQueryFolder',ValueFromPipelineByPropertyName)]
[string]
$FolderName,

# The work item ParentID
[Parameter(ValueFromPipelineByPropertyName)]
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[string]
$ParentID,

Expand All @@ -42,13 +75,13 @@
$Project,

# A collection of relationships for the work item.
[Parameter(ValueFromPipelineByPropertyName)]
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[Alias('Relationships')]
[Collections.IDictionary]
$Relationship,

# A list of comments to be added to the work item.
[Parameter(ValueFromPipelineByPropertyName)]
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[PSObject[]]
$Comment,

Expand All @@ -58,7 +91,7 @@
$Tag,

# If set, will not validate rules.
[Parameter(ValueFromPipelineByPropertyName)]
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[Alias('BypassRules','NoRules','NoRule')]
[switch]
$BypassRule,
Expand All @@ -70,7 +103,7 @@
$ValidateOnly,

# If set, will only validate rules, but will not update the work item.
[Parameter(ValueFromPipelineByPropertyName)]
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='WorkItem')]
[Alias('SuppressNotifications','SkipNotification','SkipNotifications','NoNotify')]
[switch]
$SupressNotification,
Expand Down Expand Up @@ -160,6 +193,9 @@
}
}
#endregion Output Work Item



$q = [Collections.Queue]::new()
}

Expand All @@ -177,14 +213,89 @@

$c++
Write-Progress "Creating" "$type [$c/$t]" -PercentComplete ($c * 100 / $t) -Id $progId

$orgAndProject = @{Organization=$Organization;Project=$Project}
$validFields =
if ($script:ADOFieldCache.$uribase) {
$script:ADOFieldCache.$uribase
} else {
Get-ADOField -Organization $Organization -Project $Project -Server $Server @invokeParams
Get-ADOField @orgAndProject -Server $Server @invokeParams
}

if ($psParameterSet -in 'SharedQuery', 'SharedQueryFolder') {
if ($Server -ne 'https://dev.azure.com/' -and
-not $PSBoundParameters.ApiVersion) {
$ApiVersion = '2.0'
}

$queryPathParts = @($QueryPath -split '/')
$sharedQueries = $null
foreach ($qp in $queryPathParts) {
if (-not $qp) { continue }
if (-not ($qp -as [guid])) {
$sharedQueries = Get-ADOWorkItem -SharedQuery @orgAndProject -Depth 2
break
}
}

if ($sharedQueries) {
$queryPathId = $sharedQueries |
Where-Object Path -eq $QueryPath |
Select-Object -ExpandProperty ID
if (-not $queryPathId) {
Write-Error "Unable to find Query Path '$QueryPath'"
continue
} else {
$QueryPath = $queryPathId
}
}

$uri = $uriBase, "_apis/wit/queries", $(if ($QueryPath) { $QueryPath }) -ne '' -join '/'
$uri = $uri.ToString().TrimEnd('/')
$uri += '?' +
(@(
if ($ApiVersion) { "api-version=$ApiVersion" }
if ($validateOnly) { "validateWiqlOnly=true" }
) -join '&')
$invokeParams.uri = $uri

$queryObject = @{}
if ($psParameterSet -eq 'SharedQueryFolder') {
$queryObject['name'] = $FolderName
$queryObject['isFolder'] = $true
if ($QueryType) {
$queryObject['queryType'] = $QueryType
}
if ($queryRecursionOption) {
$queryObject['queryRecursionOption'] = $queryRecursionOption
}

} else {
$queryObject['name'] = $QueryName
$queryObject['wiql'] = $WIQL

}

$invokeParams.Body = ConvertTo-Json $queryObject -Depth 100
$invokeParams.Method = 'POST'
$invokeParams.ContentType = 'application/json'
$invokeParams.PSTypeName = @(
"$Organization.$psParameterSet"
"$Organization.$project.$psParameterSet"
"PSDevOps.$psParameterSet"
)
if ($WhatIfPreference) {
$invokeParams.Remove('PersonalAccessToken')
$invokeParams
continue
}

if (-not $PSCmdlet.ShouldProcess("POST $uri with $($invokeParams.body)")) { continue }
$restResponse = Invoke-ADORestAPI @invokeParams 2>&1
$restResponse
continue
}


$validFieldTable = $validFields | Group-Object ReferenceName -AsHashTable
$uri = $uriBase, "_apis/wit/workitems", "`$$($Type)?" -join '/'
if ($Server -ne 'https://dev.azure.com/' -and
Expand Down
35 changes: 35 additions & 0 deletions PSDevOps.format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,41 @@ $($ParentNode.CustomControl.CustomEntries.CustomEntry.CustomItem.ExpressionBindi
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSDevOps.SharedQuery</Name>
<ViewSelectedBy>
<TypeName>PSDevOps.SharedQuery</TypeName>
</ViewSelectedBy>
<GroupBy>
<PropertyName>Project</PropertyName>
</GroupBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
</TableColumnHeader>
<TableColumnHeader>
</TableColumnHeader>
<TableColumnHeader>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap />
<TableColumnItems>
<TableColumnItem>
<PropertyName>IsPublic</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Path</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Wiql</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSDevOps.Team</Name>
<ViewSelectedBy>
Expand Down
Loading