Public/azuredevops.ps1


function Get-RKAzDevOpsLibrary {
      <#
.Description
Get a complete library from a Azure DevOps
#>

      [CmdletBinding()]
      param (
            [Parameter()]
            [string]
            $LibraryName
      )
      $AllLibraries = Invoke-RKDevOpsAPI "distributedtask/variablegroups/?groupName=$LibraryName&api-version=6.0-preview.2" 'GET'
      $Result = @{}
      foreach ($p in ($AllLibraries.value.Variables).PSObject.Properties) {
            $Result[$p.Name] = $p.Value.Value
      }
      return $Result
}


function Get-RKAzDevOpsLibraryKey {
      <#
.Description
Get a single key from a Azure DevOps Library
#>

      [CmdletBinding()]
      param (
            [Parameter()] [string] $LibraryName,
            [Parameter()] [string] $KeyName
      )
      $AllKeys = Get-RKAzDevOpsLibrary -LibraryName $LibraryName
      return $AllKeys[$KeyName]
}


function Set-RKAzDevOpsLibraryKey {
      <#
.Description
Add/Update a Key in a Azure DevOps Library
#>

      [CmdletBinding()]
      param (
            [Parameter()] [string] $LibraryName,
            [Parameter()] [string] $KeyName,
            [Parameter()] [string] $Value
      )

      $Existing = Invoke-RKDevOpsAPI "distributedtask/variablegroups/?groupName=$LibraryName&api-version=6.0-preview.2" 'GET'
      if (!($Existing)) {
            throw "Library $LibraryName not found"
      }
      $GroupID = $Existing.value.id

      $NewObj = $Existing.value | Select-Object -Property * -ExcludeProperty isShared, variableGroupProjectReferences, id, createdBy, createdOn, modifiedOn, modifiedBy

      $NewKeyObjValue = New-Object pscustomobject
      $NewKeyObjValue | Add-Member NoteProperty "value" $Value

      $DoesExist = [bool]($NewObj.Variables.PSobject.Properties.name -match $KeyName)
      if ($DoesExist) {
            $NewObj.Variables."$KeyName" = $NewKeyObjValue
      }
      else {
            $NewObj.Variables | Add-Member NoteProperty $KeyName $NewKeyObjValue
      }

      $Body = $NewObj | ConvertTo-Json -Depth 10
      Invoke-RKDevOpsAPIPut "distributedtask/variablegroups/$($GroupID)?api-version=6.0-preview.1" $Body

}


Function Get-RKAzDevOpsCommitRangeSinceLastSuccessfulDeployment {
      <#
  .SYNOPSIS
        Commit Id Range Since Last Successful Deployment
  .DESCRIPTION
        This function utilises the Azure DevOps REST API to determine the range of commits that have taken place since the last successful deployment.
  .PARAMETER ArtifactName
        The name of the source artifact alias in your release pipeline that you want to get the latest commit id of.
  .PARAMETER ReleaseDefinitionId
        The ID of the release pipeline to which the current release belongs. In Azure DevOps, you can access this variable as $(Release.DefinitionId).
  .PARAMETER ReleaseDefinitionEnvironmentId
        The ID of the stage in the corresponding release pipeline. In Azure DevOps, you can access this variable as $(Release.DefinitionEnvironmentId).
  .PARAMETER ReleaseId
        The identifier of the current release record. In Azure DevOps, you can access this variable as $(Release.ReleaseId).
  .PARAMETER SystemTeamFoundationCollectionUri
        The URL of the Team Foundation collection or Azure Pipelines. Use this from your scripts or tasks to call REST APIs on other services such as Build and Version control. In Azure DevOps, you can access this variable as $(System.TeamFoundationCollectionUri).
  .PARAMETER SystemTeamProject
        The name of the project to which the build or release belongs. In Azure DevOps, you can access this variable as $(System.TeamProject).
  .OUTPUTS
        A string object with the commit range separated by two dots (..).
 
        This commit id string can be passed directly into subsequent git commands.
  .NOTES
        Version: 1.0
        Author: Liam Dunphy
        Creation Date: 11/05/2021
        Purpose/Change: Initial script development
  .EXAMPLE
        ...
   
  #>

      [CmdletBinding()]
      param(
            [Parameter(Mandatory = $true)]
            [string]$ArtifactName,

            [Parameter(Mandatory = $true)]
            [string]$CurrentDeploymentCommitId,

            [Parameter(Mandatory = $true)]
            [int]$ReleaseDefinitionId,

            [Parameter(Mandatory = $true)]
            [int]$ReleaseDefinitionEnvironmentId,

            [Parameter(Mandatory = $true)]
            [int]$ReleaseId,
          
            [Parameter(Mandatory = $true)]
            [string]$SystemTeamFoundationCollectionUri,

            [Parameter(Mandatory = $true)]
            [string]$SystemTeamProject
      )

      $deployments = (az devops invoke --area release --resource deployments --org=$SystemTeamFoundationCollectionUri `
                  --route-parameters project=$SystemTeamProject `
                  --query-parameters definitionId=$ReleaseDefinitionId `
                  definitionEnvironmentId=$ReleaseDefinitionEnvironmentId `
                  deploymentStatus=30 `
                  operationStatus=7960 `
                  latestAttemptsOnly=true `
                  queryOrder=0 `
                  top=50 `
                  continuationToken=345) | ConvertFrom-Json

      # api path: "{project}/_apis/{area}/{resource}"
      # operationStatus is a magic enum - doesn't sync with https://docs.microsoft.com/en-us/javascript/api/azure-devops-extension-api/operationstatus. existing value pulled from XHR
      # deploymentStatus is a magic enum - doesn't sync with https://docs.microsoft.com/en-us/javascript/api/azure-devops-extension-api/deploymentstatus. existing value pulled from XHR

      $previousSuccessfulDeployments = ($deployments.value | Where-Object { ($_.deploymentStatus -eq "succeeded") -and ($_.id -ne $ReleaseId) } | Sort-Object completedOn -Descending)

      if ($previousSuccessfulDeployments.count -ne 0) {
            $lastSuccessfulDeploymentCommitId = ($previousSuccessfulDeployments[0].release.artifacts | Where-Object alias -eq $ArtifactName).definitionReference.sourceVersion.id
            return "$CurrentDeploymentCommitId..$lastSuccessfulDeploymentCommitId"
      }
      else {
            return $CurrentDeploymentCommitId
      }
}