YouTrackAutomation.psm1
# Copyright WebMD Health Services # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License #Requires -Version 5.1 Set-StrictMode -Version 'Latest' # Functions should use $moduleRoot as the relative root from which to find # things. A published module has its function appended to this file, while a # module in development has its functions in the Functions directory. $moduleRoot = $PSScriptRoot # Store each of your module's functions in its own file in the Functions # directory. On the build server, your module's functions will be appended to # this file, so only dot-source files that exist on the file system. This allows # developers to work on a module without having to build it first. Grab all the # functions that are in their own files. $functionsPath = Join-Path -Path $moduleRoot -ChildPath 'Functions\*.ps1' if( (Test-Path -Path $functionsPath) ) { foreach( $functionPath in (Get-Item $functionsPath) ) { . $functionPath.FullName } } function Get-YTIssue { <# .SYNOPSIS Gets an issue from YouTrack. .DESCRIPTION The `Get-YTIssue` function gets an issue from YouTrack using the issue ID or issue key. The function returns the following fields by default: * `id` * `idReadable` * `summary` * `description` * `project(name)` * `reporter(name)` * `attachments(id,name,url,created,author(name))` In order to add additional fields to the response, use the `-AdditionalField` parameter, with each field name being an entry in the string array. .EXAMPLE Get-YTIssue -Session $session -IssueId 'DEMO-1' Demonstrates fetching an issue based on the issue key. This will return the default fields for the `DEMO-1` issue. .EXAMPLE Get-YTIssue -Session $session -IssueId '3-4' Demonstrates fetching an issue based on the issue id. This will return the default fields for the `DEMO-5` issue. .EXAMPLE Get-YTIssue -Session $session -IssueId 'DEMO-1' -AdditionalField 'comments(id,author(name),text)' Demonstrates fetching an issue based on the issue key and including additional fields. This will return the default fields for the `DEMO-1` issue, as well as the comments for the issue along with the comment id, comment author, and comment text. #> [CmdletBinding()] param( # The Session object for a YouTrack session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The ID of the issue to get. This can be the issue key (`DEMO-3`) or the issue ID (`3-4`). [Parameter(Mandatory)] [String] $IssueId, # Additional fields to include in the response. This should be a comma-separated list of field names. [String[]] $AdditionalField ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $fields = 'id,idReadable,summary,description,project(name,shortName),reporter(name),attachments(id,name,url,created,author(name))' if ($AdditionalField) { $fields += ",$($AdditionalField -join ',')" } $fields = [Uri]::EscapeUriString($fields) Invoke-YTRestMethod -Session $Session -Name "issues/${IssueId}?fields=$fields" } function Get-YTProject { <# .SYNOPSIS Gets projects from YouTrack. .DESCRIPTION The `Get-YTProject` function gets projects from YouTrack. By default, all projects are returned. To return a specific project pass in its short name to the `ShortName` parameter. Wildcards are not supported. The function returns the following fields by default: * `id` * `name` * `shortName` In order to add additional fields to the response, use the `AdditionalField` parameter, with each field name being an entry in the string array. If the `ShortName` parameter is provided, the function will return only the project with the matching short name. .EXAMPLE Get-YTProject -Session $session Demonstrates fetching all projects from YouTrack. This will return the default fields for all projects. .EXAMPLE Get-YTProject -Session $session -ShortName 'DEMO' Demonstrates fetching a specific project from YouTrack. This will return the default fields for the `DEMO` project. .EXAMPLE Get-YTProject -Session $session -AdditionalField 'description' Demonstrates fetching all projects from YouTrack and including additional fields. This will return the default fields along with the description for all projects. #> [CmdletBinding()] param( # The session object for a YouTrack Session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The short name of the project to get. [String] $ShortName, # Additional fields to include in the response. [String[]] $AdditionalField ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $fields = 'id,name,shortName' if ($AdditionalField) { $fields += ",$($AdditionalField -join ',')" } $fields = [Uri]::EscapeUriString($fields) $projects = Invoke-YTRestMethod -Session $Session -Name "admin/projects?fields=$fields" if ($ShortName) { return $projects | Where-Object 'shortName' -EQ $ShortName } return $projects } function Invoke-YTRestMethod { <# .SYNOPSIS Invokes a REST method in YouTrack. .DESCRIPTION The `Invoke-YTRestMethod` function invokes a REST method in YouTrack using the provided session object. Pass in the name of the API endpoint to make the request to. By default, this function makes the HTTP request using the HTTP `Get` method. Use the `Method` parameter to use a different HTTP method. Provide the body of the request using the `Body` parameter. .EXAMPLE Invoke-YTRestMethod -Session $session -Name 'admin/projects' Demonstrates invoking the `GET` method on the `admin/projects` endpoint in YouTrack. .EXAMPLE Invoke-YTRestMethod -Session $session -Name 'admin/projects' -Method Post -Body @{ name = 'Demo Project' shortName = 'DEMO' leader = @{id = '2-1'} } Demonstrates invoking the `POST` method on the `admin/projects` endpoint in YouTrack with a body containing the name, short name, and leader of the project. #> [CmdletBinding(SupportsShouldProcess)] param( # The Session object for a YouTrack session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The name of the API endpoint to make a request to. This should be everything after the `/api/` in the URL. [Parameter(Mandatory)] [String] $Name, [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get, [Object] $Body ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $url = "$($Session.Url)${name}" Write-Debug "URL: $url" $headers = @{ 'Authorization' = "Bearer $($Session.ApiToken)" 'Accept' = 'application/json' } $requestParams = @{} if ($Body) { $requestParams['Body'] = $Body | ConvertTo-Json $requestParams['ContentType'] = 'application/json' } if ($Method -eq [Microsoft.PowerShell.Commands.WebRequestMethod]::Get -or $PSCmdlet.ShouldProcess($url, $method)) { try { Invoke-RestMethod -Uri $url -Headers $headers -Method $Method @requestParams | ForEach-Object { $_ } | Where-Object { $_ } | Write-Output } catch { Write-Error -Message ($_.ToString() | ConvertFrom-Json | Select-Object -ExpandProperty 'error_description') return } } } function New-YTIssue { <# .SYNOPSIS Creates a new issue in YouTrack. .DESCRIPTION The `New-YTIssue` function creates a new issue in YouTrack. Pass the short name of the project where the issue should be created to the `Project` parameter, and the title of the issue to the `Summary` parameter. You can also provide an optional description to the `Description` parameter. .EXAMPLE New-YTIssue -Session $session -Project 'DEMO' -Summary 'New Issue' Demonstrates creating a new issue in the `DEMO` project with the summary `New Issue`. .EXAMPLE New-YTIssue -Session $session -Project 'DEMO' -Summary 'Write Docs' -Description 'Write YouTrackAutomation docs' Demonstrates creating a new issue in the `DEMO` project with the summary `Write Docs` and the description `Write YouTrackAutomation docs`. #> [CmdletBinding()] param( # The session object for a Youtrack Session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The project that the issue will be created in. This can be a project object, project short name, or project ID. [Parameter(Mandatory)] [Object] $Project, # The summary of the issue. [Alias('Title')] [Parameter(Mandatory)] [String] $Summary, # The description of the issue. [String] $Description ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $issueFields = @{ summary = $Summary project = @{ id = Resolve-YTProjectId -Session $session -Project $Project } } if ($Description) { $issueFields['description'] = $Description } $fields = 'id,idReadable,summary' Invoke-YTRestMethod -Session $Session -Name "issues?fields=$fields" -Body $issueFields -Method Post } function New-YTProject { <# .SYNOPSIS Creates a new project in YouTrack. .DESCRIPTION The `New-YTProject` function creates a new project in YouTrack. The function requires the following parameters: * `Name`: The name of the project. * `ShortName`: The short name of the project. * `Leader`: The id or the name of the project owner. .EXAMPLE New-YTProject -Session $session -Name 'Demo Project' -ShortName 'DEMO' -Leader 'admin' Demonstrates creating a new project in YouTrack with the name `Demo Project`, the short name `DEMO`, and the project owner `admin`. .EXAMPLE New-YTProject -Session $session -Name 'Demo Project' -ShortName 'DEMO' -Leader '2-1' Demonstrates creating a new project in YouTrack with the name `Demo Project`, the short name `DEMO`, and the project owner `admin`, but using the project owner's id instead of their name. #> [CmdletBinding()] param( # The session object for a YouTrack Session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The name of the project. [Parameter(Mandatory)] [String] $Name, # The short name of the project. [Parameter(Mandatory)] [String] $ShortName, # The id or the name of the project owner. [Parameter(Mandatory)] [String] $Leader, # The description of the project. [String] $Description, # Template project to use for the new project. [ValidateSet('scrum', 'kanban')] [String] $Template, # Additional fields to include in the response. [String[]] $AdditionalFields ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($Leader -notmatch '\d+-\d+') { $Leader = Invoke-YTRestMethod -Session $Session -Name 'users?fields=name,id' | Where-Object { $_.name -eq $Leader } | Select-Object -ExpandProperty 'id' } $fields = 'id,name,shortName' $body = @{ name = $Name shortName = $ShortName leader = @{ id = $Leader } } if ($Description) { $body['description'] = $Description } if ($AdditionalFields) { $fields += ",$($AdditionalFields -join ',')" } if ($Template) { $fields += "&template=$Template" } $fields = [Uri]::EscapeUriString($fields) Invoke-YTRestMethod -Session $Session -Name "admin/projects?fields=$fields" -Body $body -Method Post } function New-YTSession { <# .SYNOPSIS Creates a new YouTrack session object. .DESCRIPTION The `New-YTSession` function creates a new YouTrack session object that can be used to interact with the YouTrack API. Provide the URL of the YouTrack instance and an API token to create a new session. This session contains the URL, the API key, and the YouTrackSharp `BearerTokenConnection` object. .EXAMPLE $session = New-YTSession -Url 'https://my-youtrack-instance.com' -ApiToken 'my-api-key' Demonstrates creating a YouTrack session object with the url 'https://my-youtrack-instance.com' and the API token 'my-api-key'. #> [CmdletBinding()] param( # The URL of the YouTrack instance. [Parameter(Mandatory)] [String] $Url, # The API token for the YouTrack instance. [Parameter(Mandatory)] [String] $ApiToken ) return [pscustomobject]@{ Url = "$Url/api/" ApiToken = $ApiToken } } function Remove-YTProject { <# .SYNOPSIS Removes a YouTrack project. .DESCRIPTiON The `Remove-YTProject` function deletes an entire project in YouTrack. Pass the project object, the id of the object, or the short name of the project to the `Project` parameter. .EXAMPLE Remove-YTProject -Session $session -Project 'DEMO' Demonstrates removing the project with the 'DEMO' short name. .EXAMPLE Remove-YTProject -Session $session -Project '0-1' Demonstrates removing the project with the '0-1' id. #> [CmdletBinding(SupportsShouldProcess)] param( # The Session object for a YouTrack session. Create a new Session using `New-YTSession`. [Parameter(Mandatory)] [Object] $Session, # The project to be deleted. This can be a project object, project short name, or project ID. [Parameter(Mandatory)] [Object] $Project ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # $msg = $ShortName # if (-not $ProjectId) # { # $project = Get-YTProject -Session $Session -ShortName $ShortName # $ProjectId = $project.id # $msg = $ShortName # } $projectId = Resolve-YTProjectId -Session $Session -Project $Project if ($PSCmdlet.ShouldProcess($projectId, 'Remove YouTrack Project')) { Invoke-YTRestMethod -Session $Session -Method Delete -Name "admin/projects/${ProjectId}" } } function Resolve-YTProjectId { <# .SYNOPSIS Gets ID for a project. .DESCRIPTION The `Resolve-YTProjectId` function takes in a project, project short name, or project id and returns the project id associated with the project provided. .EXAMPLE Resolve-YTProject.ps1 -Session $session -Project 'DEMO' Demonstrates resolving the project id for the project with the `DEMO` short name. .EXAMPLE Resolve-YTProject.ps1 -Session $session -Project '0-1' Demonstrates resolving the project id for the project with the `0-1` id. .EXAMPLE Resolve-YTProject.ps1 -Session $session -Project $project Demonstrates resolving the project id for the project with a project object. #> [CmdletBinding()] param( # The session object for a YouTrack Session. Create a new Session using `New-YTSession`. [Object] $Session, # The project to resolve the id for. Can be a project object, a project id, or a project short name. [Object] $Project ) if ($Project | Get-Member -Name 'id') { return $Project.id } if ($Project -is [String] -and $Project -match '^\d+-\d+$') { return $Project } if ($Project -is [String]) { return Get-YTProject -Session $Session -ShortName $Project | Select-Object -ExpandProperty 'id' } $msg = "Failed to resolve project ""${Project}"": expected an object with an `id` property, a string ID " + '(e.g. ''0-0''), or a project short name.' Write-Error $msg } function Use-CallerPreference { <# .SYNOPSIS Sets the PowerShell preference variables in a module's function based on the callers preferences. .DESCRIPTION Script module functions do not automatically inherit their caller's variables, including preferences set by common parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't get passed into any function that belongs to a module. When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the function's caller: * ErrorAction * Debug * Confirm * InformationAction * Verbose * WarningAction * WhatIf This function should be used in a module's function to grab the caller's preference variables so the caller doesn't have to explicitly pass common parameters to the module function. This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d). There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add explicit `-ErrorAction $ErrorActionPreference` to every `Write-Error` call. Please vote up this issue so it can get fixed. .LINK about_Preference_Variables .LINK about_CommonParameters .LINK https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d .LINK http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/ .EXAMPLE Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Demonstrates how to set the caller's common parameter preference variables in a module function. #> [CmdletBinding()] param ( [Parameter(Mandatory)] #[Management.Automation.PSScriptCmdlet] # The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` # attribute. $Cmdlet, [Parameter(Mandatory)] # The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the # `[CmdletBinding()]` attribute. # # Used to set variables in its callers' scope, even if that caller is in a different script module. [Management.Automation.SessionState]$SessionState ) Set-StrictMode -Version 'Latest' # List of preference variables taken from the about_Preference_Variables and their common parameter name (taken # from about_CommonParameters). $commonPreferences = @{ 'ErrorActionPreference' = 'ErrorAction'; 'DebugPreference' = 'Debug'; 'ConfirmPreference' = 'Confirm'; 'InformationPreference' = 'InformationAction'; 'VerbosePreference' = 'Verbose'; 'WarningPreference' = 'WarningAction'; 'WhatIfPreference' = 'WhatIf'; } foreach( $prefName in $commonPreferences.Keys ) { $parameterName = $commonPreferences[$prefName] # Don't do anything if the parameter was passed in. if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) ) { continue } $variable = $Cmdlet.SessionState.PSVariable.Get($prefName) # Don't do anything if caller didn't use a common parameter. if( -not $variable ) { continue } if( $SessionState -eq $ExecutionContext.SessionState ) { Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false } else { $SessionState.PSVariable.Set($variable.Name, $variable.Value) } } } |