--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


Recently Changed Pages:

View All Pages

View All Tags


WIKI Disclaimer: As with most other things on the Internet, the content on this wiki is not supported. It was contributed by me and is published “as is”. It has worked for me, and might work for you.
Also note that any view or statement expressed anywhere on this site are strictly mine and not the opinions or views of my employer.

Pages with comments

View All Comments


Script: Azure DevOps API: Keep Forever

Goal of the script is to check all my deployments in production and set the retain indefinitely / keep forever property to true if this is not done yet. It uses the following parts / useful techniques:

  • List all projects
  • List all deployments
  • Get Releases
  • The combined use of the $top parameter and a continuation token

The Script

Note that you need to change the first three variables.

# Define organization base url, PAT and API version variables
$orgUrl = ""
$releaseOrgUrl = ""
$pat = "XXX"
$apiversion = "api-version=6.1-preview"
# Create header with PAT
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$header = @{authorization = "Basic $token"}
# First list all projects
$projecturl = "$orgUrl/_apis/projects?$apiversion"
Write-Output "Projects url = $projecturl"
$projects = (Invoke-RestMethod -Uri $projecturl -Method GET -ContentType "application/json" -Headers $header).Value
# Override to test with 1 project
# $projects = $projects | where {$ -eq "projectname"}
ForEach ($project in $projects){
    Write-Host "Project: $($"
    # List all deployments 
    # Note that with the default settings you only get a maximum of 50 deployments per request, which can be changed using the $top parameter, to a max of 100. After which you need to use the continuationToken to loop through multiple requests and add the responses. 
    Write-Host "Evaluating deployments per 100: " -NoNewline
    $deploymentbaseurl = "$releaseOrgUrl/$($$apiversion&`$top=100"
    $deploymenturl = $deploymentbaseurl
    $deployresults = @()
    do {
        # Write-Output "Deployment url = $deploymenturl"
        # Note: The ResponseHeadersVariable parameter was added in PS 6
        $deployments = Invoke-RestMethod -Uri $deploymenturl -Method GET -ContentType "application/json" -Headers $header -ResponseHeadersVariable headers
        # Add the deployments to the previous deployments, if any
        $deployresults += $deployments.value
        # Grab the continuation token from the webserver response, and change the deployment url accordingly
        if ($headers["x-ms-continuationtoken"]){
            $continuation = $headers["x-ms-continuationtoken"]
            #write-host "Token: $continuation"
            $deploymenturl = $deploymentbaseurl + "&continuationtoken=" + $continuation
        Write-Host "." -NoNewline
    } while ($headers["x-ms-continuationtoken"])
    # Only select the successful deployments to production
    $prddeployments = $deployresults | Select-Object release,deploymentStatus,releaseEnvironment,releaseDefinition | Where-Object {(($ -eq "production") -AND ($_.deploymentStatus -eq "succeeded"))}
    Write-Host "`nNumber of total deployments = $($deployresults.Count)"
    Write-Host "Number of prod deployments = $($prddeployments.Count)"
    # Check every production deployment if the retain forever flag is set to true
    ForEach ($prddeploy in $prddeployments){
        $releaseurl = "$releaseOrgUrl/$($$($$apiversion"
        #Write-Output "Release url = $releaseurl"
        $keepforever = (Invoke-RestMethod -Uri $releaseurl -Method GET -ContentType "application/json" -Headers $header).keepforever
        if (!$keepforever) {
            Write-Host "Missing Retain Forever: " -ForegroundColor Red -NoNewline; Write-Host "$($prddeploy.release.webAccessUri)"
            # Comment the next lines out if you first want to run without actually changing something
                $changeddeployment = Invoke-RestMethod -Uri $releaseurl -Method Patch -ContentType "application/json" -Headers $header -Body "{`"keepforever`":`"true`"}"
                write-host "Deployment $($ (id:$($ was set to keep forever: $($changeddeployment.keepForever)"
            } catch {
                write-host "Changing keep forever failed, please try to do manually: $($prddeploy.release.webAccessUri)"
                Write-host $_.Exception.Message


You could leave a comment if you were logged in.
scriptazuredevopsapikeepforever.txt · Last modified: 2022/01/20 16:37 by sjoerd