Title image of Clone all repositories from Azure DevOps (Powershell or C#)

Clone all repositories from Azure DevOps (Powershell or C#)

3 February 2023

·
Azure

Cloning repositories one by one in Azure DevOps is easy. But what about cloning all of them? 🤔

I was recently running some code analysis at my work and needed all 200 of our repositories on my machine. DevOps doesn’t have any download all repositories feature so I had to write a little script to do it. As well as code analysis this script could be useful for onboarding new starters.

Post Objective: A quick script for cloning all repositories from Azure DevOps to your machine.

Generate a personal access token

We’re going to use the Azure deops API to list all repositories in your project. That list can then be used to clone all of the repositories.

There are many ways to authenticate with the API. To keep things simple for our script we’re going to use a personal access token.

💡

Personal access tokens are an easy alternative to other auth methods like OAuth. DevOps users can create and manage their own PATs. Each token can be limited to certain permissions and expire after a certain amount of time. PACTs are secrets and should be treated with the same caution as passwords.

To generate a token log into DevOps and goto “User Settings”→ “Personal access tokens” → “New Token”:

Generating a PAT to clone all repositories from Azure DevOps

When creating the token make sure to enable the “Read” code permission. This is the permission needed to list all of the repositories:

Selecting the Read code token permission

And make sure you copy the token when you save it somewhere safe. This will be your only chance.

PowerShell to Clone all repositories from Azure DevOps

With the token generated, we can put it to work with a couple lines of Powershell.

In the following script, we loop through the repositories and clone them to our machine:

$personalAccessToken = ''
$base64AuthInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$result = Invoke-RestMethod -Uri "https://dev.azure.com/{organization}/{project}/_apis/git/repositories?api-version=6.0" -Method Get -Headers $headers

$result.value.name | ForEach-Object {
     git clone ('https://{organization}@dev.azure.com/{organization}/{project}/_git/' + [uri]::EscapeDataString($_)) repositories/$_
}

To use the script save it to a file named something like “clone.ps1”.

Add your personal access token to the $personalAccessToken variable. Then replace {organization} with your DevOps organization name and {project} with your project name.

Finally, run the script from a PowerShell window:

./clone.ps1

All of your repositories should be cloned to your machine inside a ‘repositories’ folder 🙂

C# version

Let’s do the same thing in C#!

We can follow the same process as Powershell: first list the repositories from the ADO API then clone them to our machine. To clone the repositories we need Git but unfortunately, C# has no built-in APIs for using Git. But fear not there is a well-established community project to fix this called LibGit2Sharp.

Add the package to your C# project with the following command:

dotnet add package LibGit2Sharp

The C# we need can be broken down into two steps.

First, we get the list of repositories from the Azure DevOps API:

var patToken = "";
var organization = "";
var project = "";
var cloneFolder = "";

// Get list of repositories
var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue("basic", $"{Convert.ToBase64String(Encoding.UTF8.GetBytes($":{patToken}"))}");
var response = await http.GetAsync($"https://dev.azure.com/{organization}/{project}/_apis/git/repositories?api-version=6.0");

var repos = JsonSerializer.Deserialize<AzureDevOpsReposResponse>(
	await response.Content.ReadAsStringAsync(), 
	new JsonSerializerOptions { PropertyNameCaseInsensitive = true}
);

Console.WriteLine($"{repos.Value.Count()} repositories found");

Remember to add your ADO Pat token, organization and project names. As well as the cloneFolder variable which is where the repositories will be cloned into.

Second, we can loop through the repository names and use LibGit2Sharp to clone them to a temp folder:

foreach (var repo in repos.Value)
{
    try
    {
        // Clone repository to clone folder
        Console.WriteLine($"Cloning {repo.name}");

        var options = new CloneOptions
        {
            CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials() { Username = "pat", Password = patToken }
        };

        Repository.Clone($"https://@dev.azure.com/{organization}/{project}/_git/{Uri.EscapeUriString(repo.name)}", Path.Combine(cloneFolder, repo.name), options);
}

You can see that the Pat token can always be used in the Git credentials to clone the repositories from ADO.

You should now be able to clone all repositories from Azure DevOps in either Powershell or C# 🙂