Trimming stale branches from Azure DevOps

Jul 28, 2023

So, basically, this script is your cleanup crew for your Azure DevOps repo. Giving everyone force-push rights to delete branches can be a bit risky. Over time, old branches pile up, and without a built-in Azure tool to handle the mess, your repo can start looking like a digital hoarder’s paradise.

This script is your broom, letting admins sweep up old branches safely and regularly, keeping things tidy without handing out keys to everyone. It’s a tidy-up hack for your repo, making everyone’s life a bit easier and your repo a lot neater.

param(
    [string]$OrgName,
    [string]$Project,
    [string]$Pat,
    [int]$CutoffDays,
    [string[]]$Blacklist
)

$Bytes = [System.Text.Encoding]::ASCII.GetBytes(":$($Pat)")
$EncodedPAT = [System.Convert]::ToBase64String($Bytes)
$OrgUrl = "https://dev.azure.com/$OrgName"
$BaseUrl = "$OrgUrl/$Project/_apis"
$Repos = az repos list  --project $Project --query "[].{name:name, id:id}" | ConvertFrom-Json
foreach($Repo in $Repos){
    $Branches = az rest `
                    --method get `
                    --uri "$BaseUrl/git/repositories/$($Repo.id)/stats/branches?api-version=7.1-preview.1" `
                    --headers "Authorization=Basic $EncodedPAT" `
                    --query "value[].{name:name, lastPush:commit.author.date, id:commit.commitId}" `
                    | ConvertFrom-Json

    $CutOffDate = (Get-Date).AddDays($CutoffDays)

    # Filter the items
    $StaleBranches = $Branches | Where-Object { (Get-Date $_.lastPush) -lt $CutOffDate }

    foreach($Branch in $StaleBranches){
        # Skip branches in the blacklist
        if ($Blacklist -contains $Branch.name) {
            Write-Output "Skipping $($Branch.name) as it is in the blacklist"
            continue
        }

        Write-Warning "Deleting $($Branch.name) from  $($Repo.name). Last commit was $($Branch.lastPush) ($(((Get-Date)-(Get-Date $Branch.lastPush)).Days) days ago)"
        az repos ref delete --org $OrgUrl -p $Project -r $Repo.id --name "heads/$($Branch.name)" --object-id $Branch.id 
    }
}

Thanks to colleague for keeping standards high over here.

devopspowershell
Creative

Yasen Dinkov

Blender Sprite Renderer

The 10 Circles of Magic in Production