Last active
April 23, 2024 12:35
-
-
Save rfennell/5764fe4bb1372dd9a9e1d5a1c1bc05a0 to your computer and use it in GitHub Desktop.
Copy repos from GitLab to Azure DevOps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Copies GitLab repositories to Azure DevOps. | |
.DESCRIPTION | |
This script retrieves GitLab repositories using the provided GitLab token and copies them to an Azure DevOps project. | |
.PARAMETER gitlabtoken | |
Specifies the GitLab token to authenticate with the GitLab API. | |
Create a personal access token in GitLab by navigating to Profile > Edit Profile > Access Tokens. | |
Create a personal access token with read_api permissions | |
.PARAMETER azdoorg | |
Specifies the Azure DevOps organization e.g. for https://dev.azure.com/your-org this value is your-org | |
.PARAMETER azdoproject | |
Specifies the Azure DevOps project name | |
.PARAMETER gitlaburl | |
Specifies the based GitLab URL, only needs to be changed if using a on premise GitLab instance defaults to https://gitlab.com | |
.PARAMETER gitlabowned | |
List only projects owned by the authenticated user, defaults to true | |
.EXAMPLE | |
PS C:\> Copy-GitLabRepoToAzureDevOps -gitlabtoken "your-gitlab-token" -azdoorg "your-org" -azdoproject "your-project" | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory = $true)] | |
$gitlabtoken, | |
[Parameter(Mandatory = $true)] | |
$azdoorg, | |
[Parameter(Mandatory = $true)] | |
$azdoproject, | |
[Parameter(Mandatory = $false)] | |
$gitlaburl = "https://gitlab.com", | |
[Parameter(Mandatory = $false)] | |
$gitlabowned = $true | |
) | |
# Check PowerShell version | |
# We need PowerShell 7 for the correct version of invoke-restmethod | |
if ($PSVersionTable.PSVersion.Major -lt 7) { | |
Write-Host "This script requires PowerShell 7 or later. Please upgrade your PowerShell version." -ForegroundColor Red | |
exit | |
} | |
# we are using the Azure CLI to interact with Azure DevOps | |
# so make a simple list call to check if we are logged in | |
# it is done this way to avoid the need to pass a token to the script | |
# and the need for the slow login process on every run | |
# the alternative is to pass the token to the script and use it in the az command e.g | |
Write-Host "Checking Azure DevOps authentication" -ForegroundColor Green | |
# echo "######" | az devops login --organization https://dev.azure.com/contoso/ | |
az repos list --org https://dev.azure.com/$AzDoOrg --project $azdoproject --output none | |
# check the exit code of the last command | |
if ($? -eq $false) { | |
Write-Host "Azure DevOps login failed, please login using 'az login --allow-no-subscriptions' then try again." -ForegroundColor Red | |
exit | |
} | |
Write-Host "Azure DevOps authentication check successful." -ForegroundColor Green | |
# this gets all the projects that can be seen by the authenticated GitLab user, | |
# if we don't specify the token, we will get all the public projects too | |
# this might not be correct for the on premise version of GitLab as we will want all projects/repos | |
$uri = "$gitlaburl/api/v4/projects?private_token=$gitlabtoken&owned=$gitlabowned&per_page=100" | |
Write-Host "Getting GitLab Projects owned by the authenticated GitLab user..." | |
$response = Invoke-RestMethod -Uri $uri -Method Get -ResponseHeadersVariable "ResponseHeaders" | |
# check if we have more than one page of results | |
while ($ResponseHeaders.'X-Next-Page' -le $ResponseHeaders.'X-Total-Pages') { | |
$pageuri = "$uri&page=$($ResponseHeaders.'X-Next-Page')" | |
$response += Invoke-RestMethod -Uri $pageuri -Method Get -ResponseHeadersVariable "ResponseHeaders" | |
} | |
Write-Host "Found $($response.count) projects (repos)" | |
# Loop across the projects to get the repos | |
foreach ($project in $response) { | |
# Access the project details | |
$projectId = $project.id | |
$projectName = $project.name | |
$projectUrl = $project.http_url_to_repo | |
# get the last portion of the URL for the repo name | |
$repoName = ($projectUrl.Split("/")[-1]).Replace(".git", "") | |
Write-Host "Project: $projectName ($projectId)" | |
# clean out our local workin folder | |
if (Test-Path $repoName) { | |
Write-Host "Local copy of repo '$repoName' already exists, deleting..." -ForegroundColor Yellow | |
Remove-Item -Recurse -Force $repoName | |
} | |
# check if the repo exist on the target Azure DevOps | |
# if it does this script will skip the import, there are other options | |
Write-Host "Checking if repo '$repoName' exists in Azure DevOps ..." -ForegroundColor Green | |
$repoExists = az repos show --repository $repoName --org https://dev.azure.com/$AzDoOrg --project $azdoproject --query "id" -o tsv | |
if ($repoExists) { | |
Write-Host "Repo '$repoName' already exists in Azure DevOps, skipping import." -ForegroundColor Yellow | |
} | |
else { | |
Write-Host "Create the new empty repo '$repoName' in Azure DevOps..." -ForegroundColor Green | |
$AzDoOutput = az repos create --name $repoName --org https://dev.azure.com/$AzDoOrg --project $azdoproject | ConvertFrom-Json | |
Write-Host "Cloning the GitLab repo URL: $projectUrl to local storage" -ForegroundColor Green | |
git clone --mirror $projectUrl.Replace("https://", "https://oauth2:$gitlabtoken@") $repoName | |
cd $repoName | |
Write-Host "Fetching tags for repo '$repoName'..." -ForegroundColor Green | |
git fetch --tags | |
Write-Host "Updating the ORIGIN remote to Azure DevOps $($AzDoOutput.remoteUrl)" -ForegroundColor Green | |
git remote rm origin | |
git remote add origin $AzDoOutput.remoteUrl | |
Write-Host "Pushing to Azure DevOps" -ForegroundColor Green | |
git push origin --all | |
git push --tags | |
cd .. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment