Skip to content

Instantly share code, notes, and snippets.

@nh43de
Last active July 9, 2024 13:26
Show Gist options
  • Save nh43de/30c8c8c1c2e40d239f6557df81e1f6d2 to your computer and use it in GitHub Desktop.
Save nh43de/30c8c8c1c2e40d239f6557df81e1f6d2 to your computer and use it in GitHub Desktop.
Clone all repos from Azure DevOps using Powershell
<#
--credits to https://blog.rsuter.com/script-to-clone-all-git-repositories-from-your-vsts-collection/
Create a file called "CloneAllRepos.config" in the same directory with
[General]
Url=??
Username=??
Password=??
To execute the script in the Windows or PowerShell command prompt, run the following command:
powershell -ExecutionPolicy Bypass -File ./CloneAllRepos.ps1
If you’d like to execute the script without bypassing the policy in each call, you have to enable script execution globally:
Set-ExecutionPolicy Unrestricted
Now, you can execute the script in the PowerShell command line in this way:
./CloneAllRepos.ps1
#>
# Read configuration file
Get-Content "CloneAllRepos.config" | foreach-object -begin {$h=@{}} -process {
$k = [regex]::split($_,'=');
if(($k[0].CompareTo("") -ne 0) -and ($k[0].StartsWith("[") -ne $True)) {
$h.Add($k[0], $k[1])
}
}
$url = $h.Get_Item("Url")
$username = $h.Get_Item("Username")
$password = $h.Get_Item("Password")
# Retrieve list of all repositories
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$headers = @{
"Authorization" = ("Basic {0}" -f $base64AuthInfo)
"Accept" = "application/json"
}
Add-Type -AssemblyName System.Web
$gitcred = ("{0}:{1}" -f [System.Web.HttpUtility]::UrlEncode($username),$password)
$resp = Invoke-WebRequest -Headers $headers -Uri ("{0}/_apis/git/repositories?api-version=1.0" -f $url)
$json = convertFrom-JSON $resp.Content
# Clone or pull all repositories
$initpath = get-location
foreach ($entry in $json.value) {
$name = $entry.name
Write-Host $name
$url = $entry.remoteUrl -replace "://", ("://{0}@" -f $gitcred)
if(!(Test-Path -Path $name)) {
git clone $url
} else {
set-location $name
git pull
set-location $initpath
}
}
@vernazza
Copy link

It works, but I had to change line 53 to
$url = $entry.webUrl -replace "://", ("://{0}@" -f $gitcred)

@rklec
Copy link

rklec commented Jul 9, 2024

You may aloso wnat to check/guard that the config file exists:

# Define the configuration file path
$configFilePath = "CloneAllRepos.config"

# Check if the configuration file exists
if (-not (Test-Path -Path $configFilePath)) {
    Write-Host "Configuration file '$configFilePath' not found. Please ensure the file exists and try again." -ForegroundColor Red
    exit 1
}

And finally, to get rid of annoying PowerShell errors, because git writes to STDERR, you may guard the git clauses:

            $pullResult = & git pull 2>&1
            if ($LASTEXITCODE -ne 0) {
                Write-Host "Error pulling repository '$name': $pullResult" -ForegroundColor Red
                continue
            }         

https://martdegraaf.github.io/posts/consulting/git-clone-all-repos-azure-devops/#cloneallreposps1 also shows more features, like updating and using the az CLI for getting the auth token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment