From ee84d2efd2a525d997b9238d1c05d0fd5135ca24 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Wed, 3 Nov 2021 16:08:34 -0700 Subject: [PATCH 01/12] Updating Get/Set-ADOPermission: Enabling easier permission sets (addresses #128) --- Get-ADOPermission.ps1 | 14 ++++- Set-ADOPermission.ps1 | 137 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 135 insertions(+), 16 deletions(-) diff --git a/Get-ADOPermission.ps1 b/Get-ADOPermission.ps1 index 7a2a7395..f21bbcc4 100644 --- a/Get-ADOPermission.ps1 +++ b/Get-ADOPermission.ps1 @@ -77,7 +77,7 @@ [switch] $Tagging, - # If set, will get permissions for tagging related to the current project. + # If set, will get permissions for Team Foundation Version Control related to the current project. [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] [switch] $ManageTFVC, @@ -98,10 +98,16 @@ $BuildPermission, # If provided, will get build and release permissions for a given project's repositoryID - [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] [string] $RepositoryID, + # If provided, will get permissions for a given branch within a repository + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='RepositoryBranch')] + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='AllRepositories')] + [string] + $BranchName, + # If set, will get permissions for repositories within a project [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectRepository')] [Alias('ProjectRepositories')] @@ -262,6 +268,10 @@ if ($psCmdlet.ParameterSetName -eq 'AllRepositories') {'s'})V2$( if ($ProjectID) { '/' + $projectId} )$( if ($repositoryID) {'/' + $repositoryID} +)$( +if ($BranchName) { + '/refs/heads/' + ([BitConverter]::ToString([Text.Encoding]::Unicode.GetBytes($BranchName)).Replace('-','').ToLower()) +} )" } + $PSBoundParameters) } diff --git a/Set-ADOPermission.ps1 b/Set-ADOPermission.ps1 index ec81c5cb..0503f70e 100644 --- a/Set-ADOPermission.ps1 +++ b/Set-ADOPermission.ps1 @@ -20,6 +20,67 @@ [string] $Organization, + # The Project ID. + # If this is provided without anything else, will get permissions for the projectID + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Project')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Tagging')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildPermission')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectRepository')] + [Alias('Project')] + [string] + $ProjectID, + + # The Build Definition ID + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] + [string] + $DefinitionID, + + # The path to the build. + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] + [string] + $Path ='/', + + # If set, will set build and release permissions for a given project. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildPermission')] + [switch] + $BuildPermission, + + # If set, will set permissions for repositories within a project + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectRepository')] + [Alias('ProjectRepositories')] + [switch] + $ProjectRepository, + + # If provided, will set permissions for a given repositoryID + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] + [string] + $RepositoryID, + + # If provided, will set permissions for a given branch within a repository + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='AllRepositories')] + [string] + $BranchName, + + # If set, will set permissions for all repositories within a project + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='AllRepositories')] + [Alias('AllRepositories')] + [switch] + $AllRepository, + + # If set, will set permissions for tagging related to the current project. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Tagging')] + [switch] + $Tagging, + + # If set, will set permissions for Team Foundation Version Control related to the current project. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] + [switch] + $ManageTFVC, + # If set, will list the type of permisssions. [Parameter(ParameterSetName='securitynamespaces')] [Alias('SecurityNamespace', 'ListPermissionType','ListSecurityNamespace')] @@ -45,27 +106,24 @@ $Descriptor, # One or more identities. Identities will be converted into descriptors. - [Parameter(ValueFromPipelineByPropertyName, - ParameterSetName='accesscontrolentries/{NamespaceId}')] + [Parameter(ValueFromPipelineByPropertyName)] [string[]] $Identity, # One or more allow permissions. - [Parameter(ValueFromPipelineByPropertyName, - ParameterSetName='accesscontrolentries/{NamespaceId}')] + [Parameter(ValueFromPipelineByPropertyName)] [string[]] $Allow, # One or more deny permissions. - [Parameter(ValueFromPipelineByPropertyName, - ParameterSetName='accesscontrolentries/{NamespaceId}')] + [Parameter(ValueFromPipelineByPropertyName)] [string[]] $Deny, + # If set, will overwrite this entry with existing entries. # By default, will merge permissions for the specified token. - [Parameter(ValueFromPipelineByPropertyName, - ParameterSetName='accesscontrolentries/{NamespaceId}')] + [Parameter(ValueFromPipelineByPropertyName)] [Alias('NoMerge')] [switch] $Overwrite, @@ -113,15 +171,63 @@ process { $ParameterSet = $psCmdlet.ParameterSetName - $q.Enqueue(@{ParameterSet=$ParameterSet} + $PSBoundParameters) + if ($psCmdlet.ParameterSetName -notin 'securitynamespaces', 'accesscontrolentries/{NamespaceId}') { + if ($ProjectID -and -not ($ProjectID -as [guid])) { + $oldProgressPref = $ProgressPreference; $ProgressPreference = 'silentlycontinue' + $projectID = Get-ADOProject -Organization $Organization -Project $projectID | Select-Object -ExpandProperty ProjectID + $ProgressPreference = $oldProgressPref + if (-not $ProjectID) { return } + } + switch -Regex ($psCmdlet.ParameterSetName) { + Project { + $null = $PSBoundParameters.Remove('ProjectID') + $q.Enqueue(@{ + ParameterSet='accesscontrolentries/{NamespaceId}' + NamespaceID = '52d39943-cb85-4d7f-8fa8-c6baac873819' + SecurityToken = "`$PROJECT:vstfs:///Classification/TeamProject/$ProjectID" + } + $PSBoundParameters) + } + Tagging { + $q.Enqueue(@{ + ParameterSet='accesscontrolentries/{NamespaceId}' + NamespaceID = 'bb50f182-8e5e-40b8-bc21-e8752a1e7ae2' + SecurityToken = "/$ProjectID" + } + $PSBoundParameters) + } + ManageTFVC { + $q.Enqueue(@{ + ParameterSet='accesscontrolentries/{NamespaceId}' + NamespaceID = 'a39371cf-0841-4c16-bbd3-276e341bc052' + SecurityToken = "/$ProjectID" + } + $PSBoundParameters) + } + 'RepositoryID|AllRepositories|ProjectRepository' { + $q.Enqueue(@{ + ParameterSet='accesscontrolentries/{NamespaceId}' + NamespaceID = '2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87' + SecurityToken = "repo$( +if ($psCmdlet.ParameterSetName -eq 'AllRepositories') {'s'})V2$( +if ($ProjectID) { '/' + $projectId} +)$( +if ($repositoryID) {'/' + $repositoryID} +)$( +if ($BranchName) { + '/refs/heads/' + ([BitConverter]::ToString([Text.Encoding]::Unicode.GetBytes($BranchName)).Replace('-','').ToLower()) +} +)" + + } + $PSBoundParameters) + } + } + } else { + $q.Enqueue(@{ParameterSet=$ParameterSet} + $PSBoundParameters) + } } end { $c, $t, $progId = 0, $q.Count, [Random]::new().Next() while ($q.Count) { - . $DQ $q # Pop one off the queue and declare all of it's variables (see /parts/DQ.ps1). - - + . $DQ $q # Pop one off the queue and declare all of it's variables (see /parts/DQ.ps1). $uri = # The URI is comprised of @( @@ -147,7 +253,7 @@ $realDeny = 0 if (-not $cachedNamespaces.$namespaceID) { $cachedNamespaces.$namespaceID = - Get-ADOPermission -Organization $Organization -PersonalAccessToken $psboundParameters["PersonalAccessToken"] | + Get-ADOPermission -Organization $Organization -PersonalAccessToken $psboundParameters["PersonalAccessToken"] -PermissionType | Where-Object NamespaceID -EQ $NamespaceID | Select-Object -First 1 } @@ -221,6 +327,7 @@ $invokeParams.Body = [Ordered]@{ token = $SecurityToken merge = -not $Overwrite + # inheritPermissions = $false accessControlEntries = @( foreach ($desc in $Descriptors) { if (-not $desc) { continue } @@ -234,7 +341,9 @@ ) } - + <#$invokeParams.Body = @{ + value = @($invokeParams.Body) + }#> $additionalProperties = @{Organization=$Organization;Server=$Server;SecurityToken=$SecurityToken} if ($WhatIfPreference) { From f82f0fac41dbc5522e6701458fbbdf48b68070af Mon Sep 17 00:00:00 2001 From: James Brundage Date: Wed, 3 Nov 2021 16:33:52 -0700 Subject: [PATCH 02/12] Set-ADOPermission: Allowing -Inherit permissions. Warning when permissions are not found. --- Set-ADOPermission.ps1 | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Set-ADOPermission.ps1 b/Set-ADOPermission.ps1 index 0503f70e..3adeb8a3 100644 --- a/Set-ADOPermission.ps1 +++ b/Set-ADOPermission.ps1 @@ -120,7 +120,6 @@ [string[]] $Deny, - # If set, will overwrite this entry with existing entries. # By default, will merge permissions for the specified token. [Parameter(ValueFromPipelineByPropertyName)] @@ -128,6 +127,13 @@ [switch] $Overwrite, + # If set, will inherit this permissions. + # By permissions will not be inherited. + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('InheritPermission','InheritPermissions')] + [switch] + $Inherit, + # The server. By default https://dev.azure.com/. # To use against TFS, provide the tfs server URL (e.g. http://tfsserver:8080/tfs). [Parameter(ValueFromPipelineByPropertyName)] @@ -275,7 +281,7 @@ if ($BranchName) { } ) - $friendlyAllow = @(foreach ($Allowed in $Allow) { + $friendlyAllow = @(:nextAllow foreach ($Allowed in $Allow) { if ($Allowed -match '^\d+$') { $realAllow = $realAllow -bor $Allowed } else { @@ -283,12 +289,15 @@ if ($BranchName) { if ($act.Name -like $Allowed -or $act.DisplayName -like $Allowed) { $realAllow = $realAllow -bor $act.bit $act.Name + continue nextAllow } } + Write-Warning "Permission '$Allowed' not found in '$($cachedNamespaces.$NamespaceID.Name)'. +$($cachedNamespaces.$namespaceID.actions | Format-Table -Property Name, DisplayName | Out-String)" } }) - $friendlyDeny = @(foreach ($denied in $Deny) { + $friendlyDeny = @(:nextDeny foreach ($denied in $Deny) { if ($denied -match '^\d+$') { $realDeny = $realDeny -bor $denied } else { @@ -296,8 +305,11 @@ if ($BranchName) { if ($act.Name -like $denied -or $act.DisplayName -like $denied) { $realDeny = $realDeny -bor $act.bit $act.Name + continue nextDeny } } + Write-Warning "Permission '$denied' not found in '$($cachedNamespaces.$NamespaceID.Name)'. +$($cachedNamespaces.$namespaceID.actions | Format-Table -Property Name, DisplayName | Out-String)" } }) @@ -327,6 +339,7 @@ if ($BranchName) { $invokeParams.Body = [Ordered]@{ token = $SecurityToken merge = -not $Overwrite + inheritPermissions = if ($Inherit) { $true } else { $false} # inheritPermissions = $false accessControlEntries = @( foreach ($desc in $Descriptors) { @@ -341,10 +354,6 @@ if ($BranchName) { ) } - <#$invokeParams.Body = @{ - value = @($invokeParams.Body) - }#> - $additionalProperties = @{Organization=$Organization;Server=$Server;SecurityToken=$SecurityToken} if ($WhatIfPreference) { $invokeParams From 847f688587033b484b771dc33b38525a9bff199c Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:25:25 -0700 Subject: [PATCH 03/12] Updating type defintions for Area/IterationPath: Aliasing AreaPathID/IterationPathID to .Identifier. Aliasing AreaPath/IterationPath to .Path --- Types/PSDevOps.AreaPath/Alias.psd1 | 4 ++++ Types/PSDevOps.IterationPath/Alias.psd1 | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 Types/PSDevOps.AreaPath/Alias.psd1 create mode 100644 Types/PSDevOps.IterationPath/Alias.psd1 diff --git a/Types/PSDevOps.AreaPath/Alias.psd1 b/Types/PSDevOps.AreaPath/Alias.psd1 new file mode 100644 index 00000000..e2628b50 --- /dev/null +++ b/Types/PSDevOps.AreaPath/Alias.psd1 @@ -0,0 +1,4 @@ +@{ + AreaPathID = 'Identifier' + AreaPath = 'Path' +} diff --git a/Types/PSDevOps.IterationPath/Alias.psd1 b/Types/PSDevOps.IterationPath/Alias.psd1 new file mode 100644 index 00000000..431033cd --- /dev/null +++ b/Types/PSDevOps.IterationPath/Alias.psd1 @@ -0,0 +1,4 @@ +@{ + IterationID = 'Identifier' + IterationPath = 'Path' +} From e958934ef4af1fc314d615491f0ad903b9358e98 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:26:50 -0700 Subject: [PATCH 04/12] Get-ADOArea/IterationPath: Allowing -AreaPath/-IterationPath to pipe to itself, and making more fault-tolerant. --- Get-ADOAreaPath.ps1 | 2 +- Get-ADOIterationPath.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Get-ADOAreaPath.ps1 b/Get-ADOAreaPath.ps1 index eb2e616c..65f654e5 100644 --- a/Get-ADOAreaPath.ps1 +++ b/Get-ADOAreaPath.ps1 @@ -86,7 +86,7 @@ "$server".TrimEnd('/') # the Server (minus any trailing slashes), (. $ReplaceRouteParameter $PSCmdlet.ParameterSetName) # and any parameterized URLs in this parameter set. if ($AreaPath) { - $AreaPath + $AreaPath -replace '\\','/' -replace '.+/Area' -replace '^/' } ) -as [string[]] -ne '' -join '/' diff --git a/Get-ADOIterationPath.ps1 b/Get-ADOIterationPath.ps1 index a4e41472..15ee164c 100644 --- a/Get-ADOIterationPath.ps1 +++ b/Get-ADOIterationPath.ps1 @@ -84,7 +84,7 @@ "$server".TrimEnd('/') # the Server (minus any trailing slashes), (. $ReplaceRouteParameter $PSCmdlet.ParameterSetName) # and any parameterized URLs in this parameter set. if ($IterationPath) { - $IterationPath + $IterationPath -replace '\\','/' -replace '.+/Iteration' -replace '^/' } ) -as [string[]] -ne '' -join '/' From 799e755c72573f778244a8d9ee50fa7493472a0c Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:29:26 -0700 Subject: [PATCH 05/12] Get-ADOPermission: Now Supporting Addtional Easy Permissions: * Analytics * AreaPaths * Dashboards * IterationPaths Slight Internal Refactoring. --- Get-ADOPermission.ps1 | 151 +++++++++++++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 33 deletions(-) diff --git a/Get-ADOPermission.ps1 b/Get-ADOPermission.ps1 index f21bbcc4..a2a6b06c 100644 --- a/Get-ADOPermission.ps1 +++ b/Get-ADOPermission.ps1 @@ -7,6 +7,10 @@ Gets Azure DevOps security permissions. .Example Get-ADOPermission -Organization MyOrganization -Project MyProject -PersonalAccessToken $pat + .Example + Get-ADOProject -Organization MyOrganization -Project MyProject | # Get the project + Get-ADOTeam | # get the teams within the project + Get-ADOPermission -Dashboard # get the dashboard permissions of each team within the project. .Link https://docs.microsoft.com/en-us/rest/api/azure/devops/security/access%20control%20lists/query .Link @@ -44,19 +48,38 @@ $SecurityToken, # The Project ID. - # If this is provided without anything else, will get permissions for the projectID + # If this is provided without anything else, will get permissions for the projectID [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Project')] + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='Analytics')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='AreaPath')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Dashboard')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Tagging')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildPermission')] - [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='IterationPath')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='RepositoryID')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectRepository')] - [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectOverview')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ProjectOverview')] [Alias('Project')] [string] $ProjectID, + # If provided, will get permissions related to a given teamID. ( see Get-ADOTeam) + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='Dashboard')] + [string] + $TeamID, + + # If provided, will get permissions related to an Area Path. ( see Get-ADOAreaPath ) + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='AreaPath')] + [string] + $AreaPath, + + # If provided, will get permissions related to an Iteration Path. ( see Get-ADOIterationPath ) + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='IterationPath')] + [string] + $IterationPath, + # If set, will get common permissions related to a project. # These are: # * Builds @@ -77,11 +100,27 @@ [switch] $Tagging, + # If set, will get permissions for analytics related to the current project. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Analytics')] + [switch] + $Analytics, + # If set, will get permissions for Team Foundation Version Control related to the current project. [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] [switch] $ManageTFVC, + # If set, will get permissions for Delivery Plans. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Plan')] + [switch] + $Plan, + + # If set, will get dashboard permissions related to the current project. + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Dashboard')] + [Alias('Dashboards')] + [switch] + $Dashboard, + # The Build Definition ID [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] [string] @@ -90,7 +129,7 @@ # The path to the build. [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] [string] - $Path ='/', + $BuildPath ='/', # If set, will get build and release permissions for a given project. [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildPermission')] @@ -176,92 +215,138 @@ $ProgressPreference = $oldProgressPref if (-not $ProjectID) { return } } - switch -Regex ($psCmdlet.ParameterSetName) { + $psBoundParameters["ParameterSet"] ='accesscontrollists/{NamespaceId}' + switch -Regex ($psCmdlet.ParameterSetName) { Project { $null = $PSBoundParameters.Remove('ProjectID') - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '52d39943-cb85-4d7f-8fa8-c6baac873819' SecurityToken = "`$PROJECT:vstfs:///Classification/TeamProject/$ProjectID" } + $PSBoundParameters) + + } + 'AreaPath|IterationPath' { + $gotPath = + if ($psCmdlet.ParameterSetName -eq 'AreaPath') { + Get-ADOAreaPath -Organization $Organization -Project $ProjectID -AreaPath $AreaPath + } else { + Get-ADOIterationPath -Organization $Organization -Project $ProjectID -IterationPath $iterationPath + } + + if (-not $gotPath) { + continue + } + $PathIdList = @( + $gotPath.Identifier + $parentUri = $gotPath._links.parent.href + while ($parentUri) { + $parentPath = Invoke-ADORestAPI -Uri $parentUri + $parentPath.identifier + $parentUri = $parentPath._links.parent.href + } + ) + + [Array]::Reverse($PathIdList) + + $null = $PSBoundParameters.Remove('ProjectID') + + $q.Enqueue(@{ + NamespaceID = + if ($psCmdlet.ParameterSetName -eq 'AreaPath') { + '83e28ad4-2d72-4ceb-97b0-c7726d5502c3' + } else { + 'bf7bfa03-b2b7-47db-8113-fa2e002cc5b1' + } + SecurityToken = @(foreach($PathId in $PathIdList) { + "vstfs:///Classification/Node/$PathId" + }) -join ':' + } + $PSBoundParameters) + } + Analytics { + $null = $PSBoundParameters.Remove('ProjectID') + $q.Enqueue(@{ + NamespaceID = if ($ProjectID) { '58450c49-b02d-465a-ab12-59ae512d6531' } else { 'd34d3680-dfe5-4cc6-a949-7d9c68f73cba'} + SecurityToken = "`$/$(if ($ProjectID) { $ProjectID } else { 'Shared' })" + } + $PSBoundParameters) + } + Dashboard { + $null = $PSBoundParameters.Remove('ProjectID') + $q.Enqueue(@{ + NamespaceID = '8adf73b7-389a-4276-b638-fe1653f7efc7' + SecurityToken = "$/$(if ($ProjectID) { $ProjectID })/$(if ($teamID) { $teamid } else { [guid]::Empty } )" + } + $PSBoundParameters) } ProjectOverview { $null = $psboundParameters.Remove('Recurse') - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '52d39943-cb85-4d7f-8fa8-c6baac873819' # Project permissions SecurityToken = "`$PROJECT:vstfs:///Classification/TeamProject/$ProjectID" } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87' # Repositories SecurityToken = "reposV2/$projectId" Recurse = $true } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '33344d9c-fc72-4d6f-aba5-fa317101a7e9' # Build definitions SecurityToken = "$ProjectID/" Recurse = $true } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'c788c23e-1b46-4162-8f5e-d7585343b5de' # Releases SecurityToken = "$ProjectID/" Recurse = $true } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '8adf73b7-389a-4276-b638-fe1653f7efc7' # Dashboards SecurityToken = "`$/$ProjectID/" Recurse = $true } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '49b48001-ca20-4adc-8111-5b60c903a50c' # Service Endpoints SecurityToken = "endpoints/$ProjectID" Recurse = $true } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'cb594ebe-87dd-4fc9-ac2c-6a10a4c92046' # Service Hooks SecurityToken = "PublisherSecurity/$ProjectID" Recurse = $true } + $PSBoundParameters) } + Plan { + $q.Enqueue(@{ + NamespaceID = 'bed337f8-e5f3-4fb9-80da-81e17d06e7a8' + SecurityToken = "Plan" + } + $PSBoundParameters) + } Tagging { - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'bb50f182-8e5e-40b8-bc21-e8752a1e7ae2' SecurityToken = "/$ProjectID" } + $PSBoundParameters) } ManageTFVC { - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'a39371cf-0841-4c16-bbd3-276e341bc052' SecurityToken = "/$ProjectID" } + $PSBoundParameters) } 'BuildDefinition|BuildPermission' { - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'a39371cf-0841-4c16-bbd3-276e341bc052' - SecurityToken = "$ProjectID$(($path -replace '\\','/').TrimEnd('/'))/$DefinitionID" + SecurityToken = "$ProjectID$(($buildpath -replace '\\','/').TrimEnd('/'))/$DefinitionID" } + $PSBoundParameters) - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'c788c23e-1b46-4162-8f5e-d7585343b5de' - SecurityToken = "$ProjectID$(($path -replace '\\','/').TrimEnd('/'))/$DefinitionID" + SecurityToken = "$ProjectID$(($buildpath -replace '\\','/').TrimEnd('/'))/$DefinitionID" } + $PSBoundParameters) } 'RepositoryID|AllRepositories|ProjectRepository' { - $q.Enqueue(@{ - ParameterSet='accesscontrollists/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87' SecurityToken = "repo$( if ($psCmdlet.ParameterSetName -eq 'AllRepositories') {'s'})V2$( From 90745e32bdc580f8711e19977f9120b1c1750fbe Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:30:24 -0700 Subject: [PATCH 06/12] Set-ADOPermission: Now Supporting Addtional Easy Permissions: * Analytics * Builds * AreaPaths (fixes #91) * Dashboards * IterationPaths Slight Internal Refactoring. --- Set-ADOPermission.ps1 | 104 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/Set-ADOPermission.ps1 b/Set-ADOPermission.ps1 index 3adeb8a3..af12ad13 100644 --- a/Set-ADOPermission.ps1 +++ b/Set-ADOPermission.ps1 @@ -9,6 +9,8 @@ Set-ADOPermission -Organization MyOrganization -Project MyProject -PersonalAccessToken $pat .Link https://docs.microsoft.com/en-us/rest/api/azure/devops/security/access%20control%20entries/set%20access%20control%20entries + .Link + https://docs.microsoft.com/en-us/azure/devops/organizations/security/namespace-reference #> [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("Test-ForParameterSetAmbiguity", "", Justification="Ambiguity Desired.")] @@ -23,6 +25,10 @@ # The Project ID. # If this is provided without anything else, will get permissions for the projectID [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Project')] + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='Analytics')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='AreaPath')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Dashboard')] + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='IterationPath')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='Tagging')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='ManageTFVC')] [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] @@ -33,6 +39,21 @@ [string] $ProjectID, + # If provided, will set permissions related to a given teamID. ( see Get-ADOTeam) + [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='Dashboard')] + [string] + $TeamID, + + # If provided, will set permissions related to an Area Path. ( see Get-ADOAreaPath ) + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='AreaPath')] + [string] + $AreaPath, + + # If provided, will set permissions related to an Iteration Path. ( see Get-ADOIterationPath ) + [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='IterationPath')] + [string] + $IterationPath, + # The Build Definition ID [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] [string] @@ -41,7 +62,7 @@ # The path to the build. [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='BuildDefinition')] [string] - $Path ='/', + $BuildPath ='/', # If set, will set build and release permissions for a given project. [Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='BuildPermission')] @@ -184,32 +205,97 @@ $ProgressPreference = $oldProgressPref if (-not $ProjectID) { return } } + $psBoundParameters['ParameterSet']='accesscontrolentries/{NamespaceId}' switch -Regex ($psCmdlet.ParameterSetName) { Project { $null = $PSBoundParameters.Remove('ProjectID') - $q.Enqueue(@{ - ParameterSet='accesscontrolentries/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '52d39943-cb85-4d7f-8fa8-c6baac873819' SecurityToken = "`$PROJECT:vstfs:///Classification/TeamProject/$ProjectID" } + $PSBoundParameters) } + Analytics { + $null = $PSBoundParameters.Remove('ProjectID') + $q.Enqueue(@{ + NamespaceID = if ($ProjectID) { '58450c49-b02d-465a-ab12-59ae512d6531' } else { 'd34d3680-dfe5-4cc6-a949-7d9c68f73cba'} + SecurityToken = "`$/$(if ($ProjectID) { $ProjectID } else { 'Shared' })" + } + $PSBoundParameters) + } + 'AreaPath|IterationPath' { + $gotPath = + if ($psCmdlet.ParameterSetName -eq 'AreaPath') { + Get-ADOAreaPath -Organization $Organization -Project $ProjectID -AreaPath $AreaPath + } else { + Get-ADOIterationPath -Organization $Organization -Project $ProjectID -IterationPath $iterationPath + } + + if (-not $gotPath) { + continue + } + $PathIdList = @( + $gotPath.Identifier + $parentUri = $gotPath._links.parent.href + while ($parentUri) { + $parentPath = Invoke-ADORestAPI -Uri $parentUri + $parentPath.identifier + $parentUri = $parentPath._links.parent.href + } + ) + + [Array]::Reverse($PathIdList) + + $null = $PSBoundParameters.Remove('ProjectID') + + $q.Enqueue(@{ + NamespaceID = + if ($psCmdlet.ParameterSetName -eq 'AreaPath') { + '83e28ad4-2d72-4ceb-97b0-c7726d5502c3' + } else { + 'bf7bfa03-b2b7-47db-8113-fa2e002cc5b1' + } + SecurityToken = @(foreach($PathId in $PathIdList) { + "vstfs:///Classification/Node/$PathId" + }) -join ':' + } + $PSBoundParameters) + } + Dashboard { + $null = $PSBoundParameters.Remove('ProjectID') + $q.Enqueue(@{ + NamespaceID = '8adf73b7-389a-4276-b638-fe1653f7efc7' + SecurityToken = "$/$(if ($ProjectID) { $ProjectID })/$(if ($teamID) { $teamid } else { [guid]::Empty } )" + } + $PSBoundParameters) + } + Plan { + $q.Enqueue(@{ + NamespaceID = 'bed337f8-e5f3-4fb9-80da-81e17d06e7a8' + SecurityToken = "Plan" + } + $PSBoundParameters) + } Tagging { - $q.Enqueue(@{ - ParameterSet='accesscontrolentries/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'bb50f182-8e5e-40b8-bc21-e8752a1e7ae2' SecurityToken = "/$ProjectID" } + $PSBoundParameters) } ManageTFVC { - $q.Enqueue(@{ - ParameterSet='accesscontrolentries/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = 'a39371cf-0841-4c16-bbd3-276e341bc052' SecurityToken = "/$ProjectID" } + $PSBoundParameters) } + 'BuildDefinition|BuildPermission' { + + $q.Enqueue(@{ + NamespaceID = 'a39371cf-0841-4c16-bbd3-276e341bc052' + SecurityToken = "$ProjectID$(($BuildPath -replace '\\','/').TrimEnd('/'))/$DefinitionID" + } + $PSBoundParameters) + $q.Enqueue(@{ + NamespaceID = 'c788c23e-1b46-4162-8f5e-d7585343b5de' + SecurityToken = "$ProjectID$(($BuildPath -replace '\\','/').TrimEnd('/'))/$DefinitionID" + } + $PSBoundParameters) + } 'RepositoryID|AllRepositories|ProjectRepository' { - $q.Enqueue(@{ - ParameterSet='accesscontrolentries/{NamespaceId}' + $q.Enqueue(@{ NamespaceID = '2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87' SecurityToken = "repo$( if ($psCmdlet.ParameterSetName -eq 'AllRepositories') {'s'})V2$( From c4f332087062304354b9eb734123c381be36d720 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:32:52 -0700 Subject: [PATCH 07/12] Updating Area/Iteration Path Formatting Defintions to display AreaPath/IterationPath instead of Path --- Formatting/PSDevOps.AreaPath.format.ps1 | 2 +- Formatting/PSDevOps.IterationPath.format.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Formatting/PSDevOps.AreaPath.format.ps1 b/Formatting/PSDevOps.AreaPath.format.ps1 index a91cb21b..ab210792 100644 --- a/Formatting/PSDevOps.AreaPath.format.ps1 +++ b/Formatting/PSDevOps.AreaPath.format.ps1 @@ -1 +1 @@ -Write-FormatView -TypeName PSDevOps.AreaPath -Property Organization, Path \ No newline at end of file +Write-FormatView -TypeName PSDevOps.AreaPath -Property Organization, AreaPath \ No newline at end of file diff --git a/Formatting/PSDevOps.IterationPath.format.ps1 b/Formatting/PSDevOps.IterationPath.format.ps1 index 215297b1..a419e140 100644 --- a/Formatting/PSDevOps.IterationPath.format.ps1 +++ b/Formatting/PSDevOps.IterationPath.format.ps1 @@ -1 +1 @@ -Write-FormatView -TypeName PSDevOps.IterationPath -Property Path, StartDate, EndDate -AutoSize +Write-FormatView -TypeName PSDevOps.IterationPath -Property IterationPath, StartDate, EndDate -AutoSize From 531e46d0817413b7da3d8026a0f2e77ac7185081 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:33:41 -0700 Subject: [PATCH 08/12] Updating PSDevOps.Build.Defintion types, Aliasing 'BuildPath' to .Path. --- Types/PSDevOps.Build.Definition/Alias.psd1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Types/PSDevOps.Build.Definition/Alias.psd1 b/Types/PSDevOps.Build.Definition/Alias.psd1 index 6e500d2f..f717f3e5 100644 --- a/Types/PSDevOps.Build.Definition/Alias.psd1 +++ b/Types/PSDevOps.Build.Definition/Alias.psd1 @@ -1 +1,4 @@ -@{DefinitionID = 'ID'} +@{ + DefinitionID = 'ID' + BuildPath = 'Path' +} From 3df19c5c75395aeeedb9723b1cbb02a29171e1f3 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sat, 6 Nov 2021 14:34:23 -0700 Subject: [PATCH 09/12] Updating format/types.ps1xml --- PSDevOps.format.ps1xml | 4 ++-- PSDevOps.types.ps1xml | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/PSDevOps.format.ps1xml b/PSDevOps.format.ps1xml index fc1344da..801c1cbb 100644 --- a/PSDevOps.format.ps1xml +++ b/PSDevOps.format.ps1xml @@ -21,7 +21,7 @@ Organization - Path + AreaPath @@ -721,7 +721,7 @@ $($ParentNode.CustomControl.CustomEntries.CustomEntry.CustomItem.ExpressionBindi - Path + IterationPath StartDate diff --git a/PSDevOps.types.ps1xml b/PSDevOps.types.ps1xml index 78d9f20f..55c20646 100644 --- a/PSDevOps.types.ps1xml +++ b/PSDevOps.types.ps1xml @@ -19,6 +19,32 @@ + + PSDevOps.AreaPath + + + AreaPath + Path + + + AreaPathID + Identifier + + + + + Deserialized.PSDevOps.AreaPath + + + AreaPath + Path + + + AreaPathID + Identifier + + + PSDevOps.ArtifactFeed @@ -256,6 +282,10 @@ PSDevOps.Build.Definition + + BuildPath + Path + DefinitionID ID @@ -265,6 +295,10 @@ Deserialized.PSDevOps.Build.Definition + + BuildPath + Path + DefinitionID ID @@ -610,6 +644,14 @@ param($params) Invoke-GitRESTApi -Uri '$($property.Value)' -UrlParameter `$psbou PSDevOps.IterationPath + + IterationID + Identifier + + + IterationPath + Path + EndDate @@ -641,6 +683,14 @@ param($params) Invoke-GitRESTApi -Uri '$($property.Value)' -UrlParameter `$psbou Deserialized.PSDevOps.IterationPath + + IterationID + Identifier + + + IterationPath + Path + EndDate From 7b117f79b40956da1cac963dfb41c58440d725c2 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sun, 7 Nov 2021 12:44:26 -0800 Subject: [PATCH 10/12] Adding CHANGELOG.md --- CHANGELOG.md | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..6733f2bf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,334 @@ +0.5.6: +--- +### Azure DevOps Improvements +* Get-ADOPermission : Can now get permissions related to Dashboards, Analytics, AreaPaths, and IterationPaths +* Set-ADOPermission : Now can easily set permissions based off of a variety of pipeline inputs (Fixes #128 and #91) +* Get-ADOAreaPath : Removing "Area" from paths passed in, formatting returns with 'AreaPath' instead of 'Path' +* Get-ADOIterationPath : Removing "Iteration" from paths passed in, formatting returns with 'IterationPath' instead of 'Path' +* Get-ADOBuild : Extended Type Definitions now contain an alias property of BuildPath +### GitHub Workflow Improvements +* Adding "On" files for issue creation, deletion, or modification (Fixes #132) +* Adding "On" files for common scheduling needs (Fixes #134) +* ReleaseNameFormat can not be customized in ReleaseModule step (Fixes #130) + +0.5.5.1: +--- +* Allowing for [Reflection.AssemblyMetaData] attributes on step .ps1 files (to customize YAML). Issue #123 +* Better support for Object and array parameters in Azure DevOps. Issue #125. + +0.5.5: +--- +* Azure DevOps: Adding support for Shared Queries (Fixes #117) +** Get-ADOWorkItem -SharedQuery can get shared queries +** New-ADOWorkItem -WIQL will create shared queries. -FolderName will create folders. +** Remove-ADOWorkItem -QueryID can remove a shared query by ID +* GitHub Workflows: +** Adding Job/Step definitions to Release Module +** Adding -NoCoverage to RunPester Step +** Creating Example workflow that publishes PSDevOps. + +0.5.4.2: +--- +* Adding Register-ADOArtifactFeed (Fixes #118) + +0.5.4.1: +--- +* Fixing Invoke-ADORestApi issues: #111,#114,#115 +* Attaching .BuildID and .DefinitionID properties to Get-ADOBuild where appropriate. + +0.5.4: +--- +* Formatting Improvments: +** Get-ADOField now includes .Type +** Get-ADOExtension now includes .Version +* Set-ADOTeam -DefaultAreaPath/-AreaPath parameter set issue fixed (fixes #103 / #92) +** Added tests for Set-ADOTeam +* GitHub Workflow Definition Improvements: +** New Triggers: +*** On PullToMain +** New Jobs: +*** UpdateModuleTag +*** PublishToGallery +** New Steps: +*** PublishPowerShellGallery +*** TagModuleVersion +* New-GitHubWorkflow/New-ADOPipeline now support -RootDirectory +* Fixing pluralization / list issue with multiple GitHub Workflow "On" +0.5.3 +--- +* Get-ADORepository : Adding -PullRequestID +* New/Set-ADOWorkItem: Fixing pipelining issue + +0.5.2 +--- +* Get-ADOTeam: Adding alias -AreaPath for -TeamFieldValue, carrying on team property +* Set-ADOTeam: Support for -DefaultAreaPath/-AreaPath (TeamFieldValues api, fixing issue #92) +* Get-ADOTest: Enabling pagination and filtering of results. +** Invoke-ADORestAPI: Fixing -Cache(ing) correctly (#88) +** Invoke-GitHubRESTAPI: Only using .ContentEncoding if present in results (PowerShell core fix) +* Get-ADOWorkItem: +** Fixing -Related (#79) +** Fixing -Comment errors when there are no commments (#80) +* New/Set-ADOWorkItem: +** Adding -Relationship and -Comment (#81) +** Improving Formatting of Work Items (#82) +** Adding -Tag +* Invoke-ADORestAPI: Fixing issue with -QueryParameter +0.5.1 +--- +* Bugfixes: +** Get-ADOTest: Fixing parameter sets and adding formatting. +** Invoke-GitHubRESTAPI: Only using .ContentEncoding when present. +0.5 +--- +* Improved Git Functionality +** New-GitHubAction +** Invoke-GitHubRESTApi +** Connect/Disconnect-GitHub (enabling smart aliases like api.github.com/zen and api.github.com/repos//) +** Formatting for GitHub Issues and Repos +* Azure DevOps Additions/Fixes +** Invoke-ADORestAPI -AsJob + +** Get-ADOArtifactFeed now has -Metric, -PackageList, -PackageVersionList, -Provenance +** Get-ADOIdentity [new] +** Get-ADOProject now has -Board, -TestVariable, -TestConfiguration +** Get-ADOPermission is now more API-complete and has parameter sets for permission types +** Set-ADOPermission +** Get-ADOExtension can now read extension data +** Set-ADOExtension can now set extension data +** Get-ADOTest [new] +** New-ADOPipeline now has -RootDirectory +** Tons of New Type Definitions and Formatters + +0.4.9 +--- +* New Command: Wait-ADOBuild +* Start-ADOBuild +** Supports -Debug (to start a build with extra tracing) +** Allows parameters as PSObject +* Get-ADORepository: Added -IncludeHidden, -IncludeRemoteURL, -IncludeLink +* Improvements to Pipelines and Workflows: +** Pester, PSScriptAnalyzer, and ScriptCop now produce output variables +** PSDevOps now includes a file to generate it's own build +** PublishTest/CodeCoverage Results steps will always() run +** Convert-BuildStep will add a .Name to each script step. + +0.4.8 +--- +* Improved Tracing +** New Commands: Write-ADOOutput, Trace-ADOCommand/GitHubCommand +** Renaming Command / Adding Parameters: Set-ADOVariable -> Write-ADOVariable. Added -IsOutput & -IsReadOnly. +** Adding Trace-GitHubCommand/ADOCommand +** Improved logging of parameters in Convert-BuildStep +* New Functionality in Azure DevOps: +** Get-ADOProject now has -TestRun, -TestPlan, -Release, and -PendingApproval (and better progress bars) +** Get-ADOWorkItemType now has -Field +** Commands for Picklists: Add/Get/Remove/Update-ADOPicklist +0.4.7 +---- +* New Commands: +** Add/Get/Remove-ADOWiki +** Get-ADOPermission +* Bugfixes: +** Honoring Get-ADOBuild -DefinitionName +* Disconnect-ADO is now run prior at the start of Connect-ADO, and on module unload. +0.4.6 +--- +* New-ADOPipeline/New-GitHubWorkflow: Adding -BuildScript +* Connect-ADO: Auto-detecting connected user's teams and adding tab completion for -Project/-ProjectID/-Team/-TeamID +* Convert-BuildStep: Re-ordering YAML for GitHub Workflows (putting .runs last) +* Convert-ADOPipeline: Not returning .inputs when there are no .inputs +* Get-ADOProject: Adding -PolicyType and -PolicyConfiguration +* Get-ADORepository: Adding -PullRequest, -SourceReference, -TargetReference, -ReviewerIdentity, -CreatorIdentity. +* Get-ADOBuild: Adding -DefinitionName +* Invoke-ADORestAPI: Passing content length of 0 when body is empty. +* Updating README +0.4.5 +--- +* New Commands: +** Connect/Disconnect-ADO: Caching connection info and saving default parameters! +** New-ADOBuild : Create build definitions! +** Remove-ADOAgentPool : Cleaning up pools, queues, and agents. +* Core Improvements +** Invoke-ADORestApi +*** Now supports -ContinuationToken (and auto-continues unless passed a $first or $top query parameter) +*** Caches access tokens. +*** BREAKING: Invoke-ADORestApi No longer has -Proxy* parameters. +* Updated Commands: +** Get-ADOUser/Get-ADOTeam : Additional Graph scenarios added. +** New/Set-ADOWorkItem : Added -BypassRule, -ValidateOnly, -SkipNotification +0.4.4 +--- +* Get-ADOTask: Adding -YAMLSchema. +* Get-ADOTeam: Adding -Setting/-FieldValue/-Iteration/-Board. +* Get-ADOAreaPath/ADOIterationPath: Making parameter names match cmdlet. Honoring -AreaPath/-IterationPath. +* Get-ADOProject: Adding -ProcessConfiguration, -Plan, -PlanID, and -DeliveryTimeline. +* New Command: Set-ADOTeam +0.4.3 +--- +*Renaming commands: +** New-ADODashboard -> Add-ADODashboard +** New-ADOTeam -> Add-ADOTeam +* Add-ADOTeam can now add members to a team +* Get-ADOTeam can now get an -Identity +* New Command: Get-ADOUser +* Get-ADOAgentPool: Fixed pipelining bug, added -AgentName/-IncludeCapability/-IncludeLastCompletedRequest/-IncludeAssignedRequest. +* Set-ADOProject: Can now -EnableFeature and -DisableFeature +0.4.2 +--- +* Build Step Improvements: +** New-ADOPipeline now has -PowerShellCore and -WindowsPowerShell +** Import-BuildStep now has parameter sets +** New-ADOPipeline/New-GitHubWorkflow now refer to a metadata collection based off of their noun. +** BuildStep directories can be aliased: +*** ADOPipeline directories can be: ADOPipeline, ADO, AzDo, and AzureDevOps. +*** GitHubWorkflow directories can be: GitHubWorkflow, GitHubWorkflows, and GitHub. +* New Dashboard Commands: Clear/Update-ADODashboard +* New Extension Commands: Enable/Disbale-ADOExtension +* Improved formatting/types for Extensions. +* Breaking change: Install/Uninstall-ADOExtension now accept -PublisherID and -ExtensionID, not -PublisherName and -ExtensionName. +0.4.1 +--- +* More GitHub Functionality: +** Write-GitHubDebug +** Write-GitHubOutput +** Hide-GitHubOutput +** New-GitHubWorkflow allows for more complex event mapping. +* Azure DevOps Pipeline Changes +** Convert-BuildStep once again converts using ${{parameters}} syntax +* New/Improved Azure DevOps Cmdlets +** Get/New/Remove-ADODashboard +** Get-ADOAgentPool now supports -PoolID +** Set-ADOProject +** Repositories returned from a build definition are now decorated as PSDevOps.Repository +* Improved testing and static analysis compliance +0.4 +--- +* Overhaul of GitHub Workflow functionality. +** New-GitHubAction renamed to New-GitHubWorkflow +** /GitHubActions renamed to /GitHub +** Added -EventParameter to allow for parameters from events such as workflow_dispatch +** Added Write-GitHubError/GitHubWarning (updating Write-ADOError/Write-ADOWarning for consistency) +** Cleaning up GitHub Workflow parts +* Get-ADOTask no longer has -ApiVersion parameter +0.3.9 +--- +* New/Get/Remove-ADOWorkItemType: Create/get/remove work custom work item types, states, rules, and behaviors. +* Added Get-ADOBuild -IncludeAllProperty/-IncludeLatestBuild. +* ScriptCop Integration: PowerShelllStaticAnalysis stage now runs ScriptCop as well. +* Improved ScriptAnalyzer Integration: Rule name is now outputted. +0.3.8 +--- +* Add/Remove-ADOAreaPath +* Formatter for AreaPaths + +0.3.7 +--- +* Convert-ADOPipeline now has -Passthru and -Wherefore +* Get-ADOWorkProcess now has -Behavior and -WorkItemType +* Get-ADOWorkItem now has -Mine, -CurrentIteration, -Comment, -Update, -Revision. + +0.3.6.1 +--- +* Convert-ADOPipeline now binds to .Variables property +* Fixing bug in PSDevOps.WorkItem types file, which displayed in formatting. +0.3.6 +--- +* Added: Get-ADOTask, Convert-ADOPipeline +0.3.5 +--- +* New Command: Get-ADOTeam +* Get-ADOBuild -CodeCoverage +* Progress bars on Get-ADORepository +* Slight refactoring to make progress bars easier in any function + +0.3.4.1 +--- +* Removing supplied parameters in commands generated by Import-ADOProxy. +0.3.4 +--- +* New capability: Import-ADOProxy (Import a proxy module with for your ADO / TFS instance) +* New REST Commands: Get-ADOAreaPath, Get-ADOIterationPath, Get-ADOExtension +* More Features: Get-ADORepository -FileList +* Massive Internal Refactoring (switching to dynamic parameters for -PersonalAccessToken etc, standardizing pstypenames) +0.3.3 +--- +* Now Caching Personal Access Tokens! +* URLEncoding all segments in Parts/ReplaceRouteParameter. +* Ensuring all Azure DevOps YAML Parameters are wrapped in a string. +0.3.2 +--- +* Pester workarounds - Steps/InstallPester and Steps/RunPester now accept a PesterMaxVersion (defaulting to 4.99.99) +* Convert-BuildStep handles blank parameter defaults correctly +* Get-ADOBuild can get yaml definitions directly, e.g Get-ADOBuild -DefinitionID 123 -DefinitionYaml +0.3.1 +--- +* Bugfixes and Improvements to Convert/Import/Expand-BuildStep: +1. Enforcing pluralization of certain fields within Azure DevOps +2. Handling [string[]], [int[]], [float[]], or [ScriptBlock] parameters +* Allowing lists of primitives to not be indented in YAML. +0.3.0 +--- +* Added Convert/Import/Expand-BuildStep +* Allowing build steps to be defined in functions +* Automagically importing build step parameters +0.2.9 +--- +* Get/New/Remove-ADORepository +* Get/New/Remove-ADOServiceEndpoint +* Get-ADOAgentPool +** Improvements to New-ADOPipeline to avoid unexpected singletons +0.2.8 +--- +* Get/New/Update-ADOBuild +* Improving New-ADOPipeline: +** Unknown -InputObject properties will no longer be pluralized +** Added 'Pool' to list of known singletons +0.2.7 +--- +* New Cmdlet: Set-ADOArtifactFeed +* Improvements to New/Get/Remove-ADOArtifactFeed (better pipelining, renaming -FullyQualifiedID to -FeedID) +0.2.6 +--- +* New Cmdlets: +** New/Get/Remove-ADOArtifactFeed +** New/Remove-ADOProject +** New-GitHubAction +0.2.5 +--- +* Improving Get-ADOWorkItem: +** -Title allows getting work items by title +** -NoDetail allows for queries to only return IDs +** Passing -Field will skip formatting +** WorkItemsBatch will be used for query results. +** Passing an old -ApiVersion will not use workItemsBatch +** Formatting improved +* Adding Get-ADOWorkProcess +* Fixing issues with -ADOField commands when not provided a -Project +0.2.4 +--- +* Adding Adding -CanSortBy, -IsQueryable, and -ReadOnly to New-ADOField. +* Adding parameter help to New-ADOField +0.2.3 +--- +* Adding New/Remove-ADOField +* Adding help to Get-ADOField +* Adding formatting for fields +0.2.2 +--- +* Adding New/Set/Remove-ADOWorkItem +* Adding Get-ADOField +* New Parameter: Get-ADOWorkItem -WorkItemType +* New Parameter: New-ADOPipeline -Option +* Initial formatting +* Switching Parts to use latest VMImage + +0.2.1 : +* Added Get-ADOWorkItem +--- +0.2 : +--- +* Added Invoke-ADORestAPI +0.1 : +--- +Initial Commit From 1665664d23ce77c7fa3d0f9be6fef5a50fe2bf62 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sun, 7 Nov 2021 12:44:53 -0800 Subject: [PATCH 11/12] Updating Module Version [0.5.6] and Release Notes --- PSDevOps.psd1 | 113 ++++++-------------------------------------------- 1 file changed, 13 insertions(+), 100 deletions(-) diff --git a/PSDevOps.psd1 b/PSDevOps.psd1 index 812ce428..be24a444 100644 --- a/PSDevOps.psd1 +++ b/PSDevOps.psd1 @@ -9,107 +9,20 @@ ProjectURI = 'https://github.com/StartAutomating/PSDevOps' LicenseURI = 'https://github.com/StartAutomating/PSDevOps/blob/master/LICENSE' ReleaseNotes = @' -0.5.5.1: ---- -* Allowing for [Reflection.AssemblyMetaData] attributes on step .ps1 files (to customize YAML). Issue #123 -* Better support for Object and array parameters in Azure DevOps. Issue #125. - -0.5.5: ---- -* Azure DevOps: Adding support for Shared Queries (Fixes #117) -** Get-ADOWorkItem -SharedQuery can get shared queries -** New-ADOWorkItem -WIQL will create shared queries. -FolderName will create folders. -** Remove-ADOWorkItem -QueryID can remove a shared query by ID -* GitHub Workflows: -** Adding Job/Step definitions to Release Module -** Adding -NoCoverage to RunPester Step -** Creating Example workflow that publishes PSDevOps. - -0.5.4.2: ---- -* Adding Register-ADOArtifactFeed (Fixes #118) - -0.5.4.1: ---- -* Fixing Invoke-ADORestApi issues: #111,#114,#115 -* Attaching .BuildID and .DefinitionID properties to Get-ADOBuild where appropriate. - -0.5.4: ---- -* Formatting Improvments: -** Get-ADOField now includes .Type -** Get-ADOExtension now includes .Version -* Set-ADOTeam -DefaultAreaPath/-AreaPath parameter set issue fixed (fixes #103 / #92) -** Added tests for Set-ADOTeam -* GitHub Workflow Definition Improvements: -** New Triggers: -*** On PullToMain -** New Jobs: -*** UpdateModuleTag -*** PublishToGallery -** New Steps: -*** PublishPowerShellGallery -*** TagModuleVersion -* New-GitHubWorkflow/New-ADOPipeline now support -RootDirectory -* Fixing pluralization / list issue with multiple GitHub Workflow "On" -0.5.3 ---- -* Get-ADORepository : Adding -PullRequestID -* New/Set-ADOWorkItem: Fixing pipelining issue - -0.5.2 ---- -* Get-ADOTeam: Adding alias -AreaPath for -TeamFieldValue, carrying on team property -* Set-ADOTeam: Support for -DefaultAreaPath/-AreaPath (TeamFieldValues api, fixing issue #92) -* Get-ADOTest: Enabling pagination and filtering of results. -** Invoke-ADORestAPI: Fixing -Cache(ing) correctly (#88) -** Invoke-GitHubRESTAPI: Only using .ContentEncoding if present in results (PowerShell core fix) -* Get-ADOWorkItem: -** Fixing -Related (#79) -** Fixing -Comment errors when there are no commments (#80) -* New/Set-ADOWorkItem: -** Adding -Relationship and -Comment (#81) -** Improving Formatting of Work Items (#82) -** Adding -Tag -* Invoke-ADORestAPI: Fixing issue with -QueryParameter -0.5.1 ---- -* Bugfixes: -** Get-ADOTest: Fixing parameter sets and adding formatting. -** Invoke-GitHubRESTAPI: Only using .ContentEncoding when present. -0.5 ---- -* Improved Git Functionality -** New-GitHubAction -** Invoke-GitHubRESTApi -** Connect/Disconnect-GitHub (enabling smart aliases like api.github.com/zen and api.github.com/repos//) -** Formatting for GitHub Issues and Repos -* Azure DevOps Additions/Fixes -** Invoke-ADORestAPI -AsJob +0.5.6: +--- +### Azure DevOps Improvements +* Get-ADOPermission : Can now get permissions related to Dashboards, Analytics, AreaPaths, and IterationPaths +* Set-ADOPermission : Now can easily set permissions based off of a variety of pipeline inputs (Fixes #128 and #91) +* Get-ADOAreaPath : Removing "Area" from paths passed in, formatting returns with 'AreaPath' instead of 'Path' +* Get-ADOIterationPath : Removing "Iteration" from paths passed in, formatting returns with 'IterationPath' instead of 'Path' +* Get-ADOBuild : Extended Type Definitions now contain an alias property of BuildPath +### GitHub Workflow Improvements +* Adding "On" files for issue creation, deletion, or modification (Fixes #132) +* Adding "On" files for common scheduling needs (Fixes #134) +* ReleaseNameFormat can not be customized in ReleaseModule step (Fixes #130) -** Get-ADOArtifactFeed now has -Metric, -PackageList, -PackageVersionList, -Provenance -** Get-ADOIdentity [new] -** Get-ADOProject now has -Board, -TestVariable, -TestConfiguration -** Get-ADOPermission is now more API-complete and has parameter sets for permission types -** Set-ADOPermission -** Get-ADOExtension can now read extension data -** Set-ADOExtension can now set extension data -** Get-ADOTest [new] -** New-ADOPipeline now has -RootDirectory -** Tons of New Type Definitions and Formatters - -0.4.9 ---- -* New Command: Wait-ADOBuild -* Start-ADOBuild -** Supports -Debug (to start a build with extra tracing) -** Allows parameters as PSObject -* Get-ADORepository: Added -IncludeHidden, -IncludeRemoteURL, -IncludeLink -* Improvements to Pipelines and Workflows: -** Pester, PSScriptAnalyzer, and ScriptCop now produce output variables -** PSDevOps now includes a file to generate it's own build -** PublishTest/CodeCoverage Results steps will always() run -** Convert-BuildStep will add a .Name to each script step. +Previous Release Notes available in [CHANGELOG.md](https://github.com/StartAutomating/PSDevOps/blob/master/CHANGELOG.md) '@ } Colors = @{ From 1aad9e041ec5a2674a04fde067a593d7c1f42477 Mon Sep 17 00:00:00 2001 From: James Brundage Date: Sun, 7 Nov 2021 12:51:24 -0800 Subject: [PATCH 12/12] Updating Module Version [0.5.6] and Release Notes --- PSDevOps.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PSDevOps.psd1 b/PSDevOps.psd1 index be24a444..9ca76be3 100644 --- a/PSDevOps.psd1 +++ b/PSDevOps.psd1 @@ -1,5 +1,5 @@ @{ - ModuleVersion = '0.5.5.1' + ModuleVersion = '0.5.6' RootModule = 'PSDevOps.psm1' Description = 'PowerShell Tools for DevOps' Guid = 'e6b56c5f-41ac-4ba4-8b88-2c063f683176'