Monday, September 28, 2020

Stale braches cleanup in Git repo

As code development moves forward, collaboration and experimentation flourish, developers join and leave the team, the Git repos start to accumulate stale branches. There is no exact definition for for "stale branch", but both Azure DevOps and GitHub, have Stale branches view. This view displays "... branches in the repo that haven't had any commits in three months or longer". There are many reasons why branches became stale. Eventually, there will be a lots of them:


Apart from "polluting" the repo and making it harder to find branches, this situation has another side effect. When CI tools run pipelines, the worker machines (agents) have to clone repo on each run. During repo cloning, Git creates references files for braches in the local folder .git/refs/remotes/origin. This translates into a lot of small IO operations that affects pipeline execution time.

The manual clean up of the staled branches could be tedious process, especially when repo has tens, hundreds, or even thousands of such branches. Below is a simple PowerShell script that will help to automate the process.

$TTL = 90 #days
$borderTime = (Get-Date).AddDays(-$TTL)
git fetch origin
$remoteBranches = git branch -| Where-Object {$_ -like '*remotes/origin/*'} | ForEach-Object {$_.trim()}
$remoteBranches = $remoteBranches | Where-Object { ($_ -notlike 'remotes/origin/HEAD*') `
                                              -and ($_ -ne 'remotes/origin/master') }
foreach($branch in $remoteBranches){
    $branchName = ($branch.Split('/', 3))[2]
    $branchSHA = git rev-parse origin/$branchName
    $branchLastUpdate = [DateTime]::Parse($(git show ---format=%ci $branchSHA))
    if($branchLastUpdate -lt $borderTime)
    {
        Write-Output "git push origin :$branchName"
    }
}

The script needs to be run in the local repo folder, it can be executed as a file or just pasted into PowerShell console. As an output, the script will produce a list of "delete branch" git statements (without actually execution of them):

git push origin :branch_1
git push origin :branch_2
git push origin :task/xyz
...
git push origin :feature/abc

The list needs to be reviewed - the branches that have to be preserved must be removed from this list. After that, each statement can be executed individually, or all of them at ones as a batch. The excluded branches could be added into the script's branch filter (second Where-Object statement, lines 5-6) to review time in the feature.

Monday, September 14, 2020

Credentials renew for "automated" ARM connection in Azure DevOps

When you setup Azure Resource Manager connection in Azure DevOps using "Service principal (automatic)" authentication, Azure DevOps will create new service principal (app registration) in Azure Active Directory and grant this principal desired access to Azure resources. Have a look at the documentation here.

When the system setups the service principal in Azure AD, it will generate a client secret with 2 year expiration. Azure DevOps will store it in service connection (without exposing to the end-user) and will use it for Service Principal Authentication. This is where "automatic" part ends currently as Azure DevOps doesn't rollover client server after two years.

If you are not aware of this 2 years expiration period for the client secret, you will find yourself (like I found myself) in the situation where your Azure related tasks will start to fail with ExpiredServicePrincipal errors. The fix is obvious - go to Azure AD and create new client secret. It is not obvious thou how to configure service connection in Azure DevOps as there is no UI to provide new client secret (as it is "automatic" connection):

After some experimentation, I found that you just have to click "Save" button (see the picture above) to force Azure DevOps to create new client secret in Azure AD and update its service connection configuration. After this, do not forget to add a reminder to your calendar to repeat this process a week before the next 2 years expiration.

How to backup Azure DevOps code repositories

Under " shared responsibility in the cloud " model, the client is always responsible for its own data. Azure DevOps, as a SaaS off...