Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Get-VSTeamWiql #314 #315

Closed
wants to merge 5 commits into from
Closed
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
26 changes: 17 additions & 9 deletions Build-Module.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ if ($installDep.IsPresent -or $analyzeScript.IsPresent) {

# Install each module
if ($manifest.RequiredModules) {
$manifest.RequiredModules | ForEach-Object { if (-not (get-module $_ -ListAvailable)) { Write-Host "Installing $_"; Install-Module -SkipPublisherCheck -Name $_ -Repository PSGallery -F -Scope CurrentUser } }
$manifest.RequiredModules | ForEach-Object { if (-not (get-module $_ -ListAvailable)) { Write-Host "Installing $_"; Install-Module -Name $_ -Repository PSGallery -F -Scope CurrentUser } }
}
}

Expand Down Expand Up @@ -81,14 +81,22 @@ if ($buildHelp.IsPresent) {
}

Write-Output 'Publishing about help files'
Copy-Item -Path ./Source/en-US -Destination "$output/" -Recurse -Force
Copy-Item -Path ./Source/VSTeam.psm1 -Destination "$output/VSTeam.psm1" -Force
Copy-Item -Path ./Source/en-US -Destination "$output/" -Recurse -Force
Copy-Item -Path ./Source/VSTeam.psd1 -Destination "$output/VSTeam.psd1" -Force

Write-Output 'Updating Functions To Export'

Get-Content -Path ./Source/VSTeam.psm1 | Out-File -Append -FilePath "$output/VSTeam.psm1" -Encoding ascii
<#Write-Output 'Updating Functions To Export'
$newValue = ((Get-ChildItem -Path "./Source/Public" -Filter '*.ps1').BaseName |
ForEach-Object -Process { Write-Output "'$_'" }) -join ','
ForEach-Object -Process { Write-Output "'$_'" }) -join ','
#>

(Get-Content "./Source/VSTeam.psd1") -Replace ("FunctionsToExport.+", "FunctionsToExport = ($newValue)") | Set-Content "$output/VSTeam.psd1"
$PSDsettings = Import-PowerShellDataFile -path "./Source/VSTeam.psd1"
Write-Output 'Updating Functions To Export'
$FunctionsToExport = @()
$FunctionsToExport += $PSDsettings.FunctionsToExport.where({$_ -like "_*"})
$FunctionsToExport += (Get-ChildItem -Path "./Source/Public" -Filter '*.ps1').BaseName
Update-ModuleManifest -Path "$output/VSTeam.psd1" -FunctionsToExport $FunctionsToExport

Write-Output "Publish complete to $output"

Expand All @@ -100,8 +108,8 @@ if ($ipmo.IsPresent -or $runTests.IsPresent) {
if ((Get-Module VSTeam)) {
Remove-Module VSTeam
}

Import-Module "$output/VSTeam.psd1" -Force
$env:testing = $true
Import-Module "$output/VSTeam.psd1" -Global -Force
Set-VSTeamAlias
}

Expand Down Expand Up @@ -154,4 +162,4 @@ if ($analyzeScript.IsPresent) {
$r = Invoke-ScriptAnalyzer -Path $output -Recurse
$r | ForEach-Object { Write-Host "##vso[task.logissue type=$($_.Severity);sourcepath=$($_.ScriptPath);linenumber=$($_.Line);columnnumber=$($_.Column);]$($_.Message)" }
Write-Output "Static code analysis complete."
}
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

# Fix Get-VSTeamWiql #314
Changed file : Source\Public\Get-VSTeamWIQL.ps1 | Team parameter is now optional, removed dynamic param, completer & name-to-id trnasformer for ID parameter.
New files :
Source\Classes\VSTeamQueryCache.ps1 | implments cache for completer and transformer
Source\Classes\QueryCompleter.ps1 | argument completer - completes by friendly name
Source\Classes\QueryTransformToIDAttribute.ps1 | argument transformer turns name of query into its GUID
Source\Clasess\_classes.json | Add three classes above
## 6.5.1

Merged [Pull Request](https://github.com/DarqueWarrior/vsteam/pull/317) from [Brittan DeYoung](https://github.com/brittandeyoung) which included the following:
Expand Down
41 changes: 41 additions & 0 deletions Source/Classes/QueryCompleter.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using namespace System.Collections
using namespace System.Collections.Generic
using namespace System.Management.Automation

class QueryCompleter : IArgumentCompleter {
[IEnumerable[CompletionResult]] CompleteArgument(
[string] $CommandName,
[string] $ParameterName,
[string] $WordToComplete,
[Language.CommandAst] $CommandAst,
[IDictionary] $FakeBoundParameters) {

$results = [List[CompletionResult]]::new()


# If the user has explictly added the -ProjectName parameter
# to the command use that instead of the default project.
$projectName = $FakeBoundParameters['ProjectName']

# Only use the default project if the ProjectName parameter was
# not used
if (-not $projectName) {
$projectName = _getDefaultProject
}

# If there is no projectName by this point just return a empty
# list.
if ($projectName) {

foreach ( $q in [vsteamquerycache]::GetCurrent() ) {
if ($q.name -like "*$WordToComplete*" -and $q.name -notmatch '\w') {
$results.Add([CompletionResult]::new($q.name))
}
elseif ($q.name -like "*$WordToComplete*") {
$results.Add([CompletionResult]::new("'$($q.name.replace("'","''"))'", $q.name, 0, $q.name))
}
}
}
return $results
}
}
16 changes: 16 additions & 0 deletions Source/Classes/QueryTransformToIDAttribute.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using namespace System.Management.Automation

class QueryTransformToIDAttribute : ArgumentTransformationAttribute {
[object] Transform(
[EngineIntrinsics]$EngineIntrinsics,
[object] $InputData
) {
#If input data isn't empty and is not a GUID, and it is found as a name in the cache,
#then replace it with the match ID from the cache
if ($InputData -and $InputData -notmatch "[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}" -and
[VSTeamQueryCache]::queries.where({$_.name -eq $InputData}).count) {
$InputData = [VSTeamQueryCache]::queries.where({$_.name -eq $InputData}).id
}
return ($InputData)
}
}
22 changes: 22 additions & 0 deletions Source/Classes/VSTeamQueryCache.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class VSTeamQueryCache {
static [int] $timestamp = -1
static [object] $queries = $null
static [Void] Update () {
$projectName = (_getDefaultProject)
if ($projectName) {
[VSTeamQueryCache]::queries = (_callAPi -ProjectName $projectName -Area wit -Resource queries -version (_getApiVersion core ) -QueryString @{'$depth'=1}
).value.children | Where-Object -property isfolder -ne "True" | Select-Object Name,ID | Sort-Object Name
[VSTeamQueryCache]::timestamp = (Get-Date).TimeOfDay.TotalMinutes
}
}
static [void] Invalidate () {
[VSTeamQueryCache]::timestamp = -1
}
static [object] GetCurrent () {
if ([VSTeamQueryCache]::timestamp -lt 0 -or
[VSTeamQueryCache]::timestamp -lt [datetime]::Now.TimeOfDay.TotalMinutes -5) {
[VSTeamQueryCache]::Update()
}
return ([VSTeamQueryCache]::queries)
}
}
5 changes: 4 additions & 1 deletion Source/Classes/_classes.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"outputFile": "vsteam.classes.ps1",
"outputFile": "vsteam.psm1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change will not be merged. I will get other changes in.

"fileType": "classes",
"files": [
"InvokeCompleter.ps1",
Expand All @@ -13,11 +13,14 @@
"WorkItemTypeCompleter.ps1",
"ProcessValidateAttribute.ps1",
"ProjectValidateAttribute.ps1",
"QueryCompleter.ps1",
"QueryTransformToIDAttribute.ps1",
"UncachedProjectValidateAttribute.ps1",
"WorkItemTypeValidateAttribute.ps1",
"VSTeamVersions.ps1",
"VSTeamProjectCache.ps1",
"VSTeamProcessCache.ps1",
"VSTeamQueryCache.ps1",
"VSTeamDirectory.ps1",
"VSTeamLeaf.ps1",
"VSTeamPools.ps1",
Expand Down
85 changes: 40 additions & 45 deletions Source/Public/Get-VSTeamWiql.ps1
Original file line number Diff line number Diff line change
@@ -1,80 +1,75 @@
function Get-VSTeamWiql {
[CmdletBinding(DefaultParameterSetName = 'ByID')]
param(
[QueryTransformToIDAttribute()]
[ArgumentCompleter([QueryCompleter])]
[Parameter(ParameterSetName = 'ByID', Mandatory = $true, Position = 0)]
[string] $Id,

[Parameter(ParameterSetName = 'ByQuery', Mandatory = $true, Position = 0)]
[Parameter(ParameterSetName = 'ByQuery', Mandatory = $true)]
[string] $Query,

[Parameter(Mandatory = $true, Position = 1)]
[string] $Team,

[int] $Top = 100,
[Parameter(Position = 2)]
[ProjectValidateAttribute()]
[ArgumentCompleter([ProjectCompleter])]
$ProjectName,

[int] $Top = 100,
[Switch] $TimePrecision,

[Switch] $Expand
)
DynamicParam {
#$arrSet = Get-VSTeamProject | Select-Object -ExpandProperty Name
_buildProjectNameDynamicParam -mandatory $true #-arrSet $arrSet
}

Process {

# Bind the parameter to a friendly variable
$ProjectName = $PSBoundParameters["ProjectName"]

$QueryString = @{
'$top' = $Top
timePrecision = $TimePrecision
process {
#build paramters for _callAPI
$params = @{
ProjectName = $ProjectName
Area = 'wit'
Resource = 'wiql'
Version = [VSTeamVersions]::Core
QueryString = @{
'$top' = $Top
timePrecision = $TimePrecision
}
}

# Call the REST API
if ($Query) {

$body = (@{
query = $Query
}) | ConvertTo-Json

$resp = _callAPI -ProjectName $ProjectName -Team $Team -Area 'wit' -Resource 'wiql' `
-method "POST" -ContentType "application/json" `
-Version $(_getApiVersion Core) `
-Querystring $QueryString `
-Body $body
$params['body'] = @{query = $Query} | ConvertTo-Json
$params['method'] = 'POST'
$params['ContentType'] = 'application/json'
}
else {
$resp = _callAPI -ProjectName $ProjectName -Team $Team -Area 'wit' -Resource 'wiql' `
-Version $(_getApiVersion Core) -id "$Id" `
-Querystring $QueryString
$params['id']= $Id
}
if ($Team) {
$params['Team']= $Team
}
$resp = _callAPI @params

if ($Expand) {
#Handle queries for work item links also allow for the tests not Setting the query result type.
if ($resp.psobject.Properties['queryResultType'] -and $resp.queryResultType -eq 'workItemLink') {
Add-Member -InputObject $resp -MemberType NoteProperty -Name Workitems -Value @()
$Ids = $resp.workItemRelations.Target.id
}
else { $Ids = $resp.workItems.id }

[array]$Ids = $resp.workItems.id
$Fields = $resp.columns.referenceName

$resp.workItems = @()
#splitting id array by 200, since a maximum of 200 ids are allowed per call
$countIds = $Ids.Count
$resp.workItems = for ($beginRange = 0; $beginRange -lt $countIds; $beginRange += 200) {

$endRange = ($beginRange + 199)

if ($endRange -gt $countIds) {
$idArray = $Ids[$beginRange..($countIds - 1)]
#in case strict mode is on,pick lesser of 0..199 and 0..count-1
$endRange = [math]::Min(($beginRange + 199),($countIds - 1))
#if query contains "*" don't specify fields, otherwise use fields returned.
if ($Query -match "\*") {
Get-VSTeamWorkItem -Id $Ids[$beginRange..$endRange]
}
else {
$idArray = $Ids[$beginRange..($endRange)]
Get-VSTeamWorkItem -Id $Ids[$beginRange..$endRange] -Fields $resp.columns.referenceName
}

(Get-VSTeamWorkItem -Fields $Fields -Id $idArray).value
}
}

_applyTypesToWiql -item $resp

return $resp
}
}
}
12 changes: 2 additions & 10 deletions Source/VSTeam.psm1
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
# Dot sources all the files in Public, Private and Classes
# Then reads the file names in Public and exports them
# as the fucntions for the module.
# To export an alias you have to manually add it to the
# Export-ModuleMember below.
# The module manifest is using wildcard exports for functions
# and alias so you only have to name the files correctly.

# Files are built using a script in the root folder
. "$PSScriptRoot\vsteam.classes.ps1"
# Dot source Public & Private functions
# Files are built using a script in the root folder of the repository
. "$PSScriptRoot\vsteam.functions.ps1"

# Check to see if the user stored the default project in an environment variable
Expand Down
1 change: 1 addition & 0 deletions unit/test/Add-VSTeamProject.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Describe 'VSTeamProject' {
. "$PSScriptRoot/../../Source/Classes/VSTeamLeaf.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamDirectory.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamVersions.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamProcess.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamProjectCache.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamProcessCache.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamUserEntitlement.ps1"
Expand Down
31 changes: 18 additions & 13 deletions unit/test/Get-VSTeamWiql.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ Set-StrictMode -Version Latest
Describe 'VSTeamWiql' {
BeforeAll {
$sut = (Split-Path -Leaf $PSCommandPath).Replace(".Tests.", ".")

. "$PSScriptRoot/../../Source/Classes/VSTeamVersions.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamProjectCache.ps1"
. "$PSScriptRoot/../../Source/Classes/ProjectValidateAttribute.ps1"
. "$PSScriptRoot/../../Source/Classes/ProjectCompleter.ps1"
. "$PSScriptRoot/../../Source/Classes/VSTeamQueryCache.ps1"
. "$PSScriptRoot/../../Source/Classes/QueryCompleter.ps1"
. "$PSScriptRoot/../../Source/Classes/QueryTransformToIDAttribute.ps1"
. "$PSScriptRoot/../../Source/Private/applyTypes.ps1"
. "$PSScriptRoot/../../Source/Private/common.ps1"
. "$PSScriptRoot/../../Source/Public/Get-VSTeamWorkItem.ps1"
Expand All @@ -33,15 +36,6 @@ Describe 'VSTeamWiql' {
descending = $false
}

$wiqlResult = @{
querytype = "flat"
queryTypeResult = "worItem"
asOf = "2019-10-03T18:35:09.117Z"
columns = @($column)
sortColumns = @($sortColumn)
workItems = @($workItem, $workItem)
}

$expandedWorkItems = @{
count = 1
value = @($workItem, $workItem)
Expand All @@ -53,7 +47,17 @@ Describe 'VSTeamWiql' {
Mock Invoke-RestMethod {
# If this test fails uncomment the line below to see how the mock was called.
# Write-Host $args


# result is returned and -Expand is specified, the work items field is overwritten
#If $wiqlResult is defined once (like column, and work item) the second expand has a problem
$wiqlResult = @{
querytype = "flat"
queryTypeResult = "workItem"
asOf = "2019-10-03T18:35:09.117Z"
columns = @($column)
sortColumns = @($sortColumn)
workItems = @($workItem, $workItem)
}
return $wiqlResult
}

Expand Down Expand Up @@ -134,6 +138,7 @@ Describe 'VSTeamWiql' {
}
}


It 'Get work items with custom WIQL query with time precision' {
$Global:PSDefaultParameterValues.Remove("*-vsteam*:projectName")
$wiqlQuery = "Select [System.Id], [System.Title], [System.State] From WorkItems"
Expand All @@ -147,8 +152,8 @@ Describe 'VSTeamWiql' {
$Body -like "*[System.State]*" -and
$Body -like '*`}' -and # Make sure the body is an object
$ContentType -eq 'application/json' -and
$Uri -like "*timePrecision=True*"
$Uri -like "*`$top=100*"
$Uri -like "*timePrecision=True*" -and
$Uri -like "*`$top=100*" -and
$Uri -like "https://dev.azure.com/test/test/test team/_apis/wit/wiql?api-version=$(_getApiVersion Core)*"
}
}
Expand Down