Comment supprimer rapidement la totalité des baux "Legacy Retention Model" d’une organisation/collection Azure DevOps ?
Les différentes évolutions d’Azure Pipeline ont amené beaucoup de bonnes choses. Dont une belle simplification de la gestion des stratégies de rétention des builds. Mais ceci est arrivé avec un petit effet de bord : des pipelines qui ne disposaient pas d’une stratégie de rétention voient leurs exécutions affublées d’un bail "Legacy Retention Model".
La problématique
Le bail "Legacy Retention Model" interdit la suppression des exécutions.
Aucune stratégie n’étant définie avant l’évolution de cette fonctionnalité, Microsoft ne peut pas prendre la décision de supprimer des exécutions à notre place. La démarche est donc logique.
Pour pourvoir supprimer les excitions concernées, il faut donc retirer les baux. Cette opération peut être fastidieuse si vos avez beaucoup de pipelines, projets, ou organisation / collections.
Une solution
L’an dernier j’avais créé un petit script PowerShell qui effectuait une opération similaire sur mon organisation Azure DevOps. Je l’ai un peu adapté afin de pouvoir l’utiliser sur de grosses collections on-premise, et supprimer la totalité des baux "Legacy Retention Model" d’une collection. Si vous avez migré d'Azure DevOps Server 2020 vers 2022, ne passez pas à côté de celui-ci ;)
La configuration est relativement simple. Il y a 3 variables à adapter (la quatrième étant là pour faciliter la réutilisation dans le futur):
$urlServer
: Url du serveur Azure DevOps on-premise, ou https://dev.azure.com$collection
: Nom ou Id de la Collection on-premise, ou de l’organisation cloud.$token
: Token de type PAT génèré via Azure DevOps.$apiVersion
: Afin de pouvoir s’adapter à de futurs besoins (7.0 est la version 2022 on-premise, et aussi l’actuelle version cloud).
# Settings
$urlServer = "https://mon-server-azure-devops/tfs"
$collection = "MaCollection"
$token = "xxxxxxxxxxxxx"
$api = "7.0"
$ownerId = "Legacy Retention Model"
# ---
$headers = @{
Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(":$($token)"))
}
function Invoke-ADO {
param (
[Uri]$Uri,
[Microsoft.PowerShell.Commands.WebRequestMethod]$Method = "Get"
)
return Invoke-RestMethod -Uri $Uri -Method $Method -Headers $headers
}
$projects = Invoke-ADO -Uri "$($urlServer)/$($collection)/_apis/projects?api-version=$($api)"
foreach($project in $projects.value){
Write-Host "Project : $($project.name)"
$urlProject = "$($urlServer)/$($collection)/$($project.id)"
$definitions = Invoke-ADO -Uri "$($urlProject)/_apis/build/definitions?api-version=$($api)"
foreach ($definition in $definitions.value) {
Write-Host "Build definition : $($definition.name)"
$runs = Invoke-ADO -Uri "$($urlProject)/_apis/pipelines/$($definition.id)/runs?api-version=$($api)"
foreach ($run in $runs.value) {
$leases = Invoke-ADO -Uri "$($urlProject)/_apis/build/builds/$($run.id)/leases?api-version=$($api)"
foreach ($lease in $leases.value) {
if ($lease.ownerId -Match $ownerId) {
Write-Host "Run : $($run.id) ($($run.createdDate))" -ForegroundColor Green
Invoke-ADO -Uri "$($urlProject)/_apis/build/retention/leases?ids=$($lease.leaseId)&api-version=$($api)" -Method Delete
}
}
}
}
}