Skip to content

Instantly share code, notes, and snippets.

@paulmallon
Last active February 20, 2023 00:03
Show Gist options
  • Save paulmallon/57c046d2ed54974bc4a9c67b315ff0ce to your computer and use it in GitHub Desktop.
Save paulmallon/57c046d2ed54974bc4a9c67b315ff0ce to your computer and use it in GitHub Desktop.
Powershell script for Gitlab REST API - A quick solution to clone selected (by id or name) or all repositories from the projects returned by API and setup git to track all remote branches. References: Gitlab Projects API: https://docs.gitlab.com/ee/api/projects.html Git doc: https://docs.gitlab.com/ee/api/projects.html
#
# Gitlab clone script
#
# Author: PM
# Date: 2019-10-18#
#
[CmdletBinding(DefaultParameterSetName = 'all')]
param (
[Alias('ID')]
[Parameter(ParameterSetName="id")]
[int]$ProjectID = -1,
[Alias('name')]
[Parameter(ParameterSetName="search")]
[string]$projectName = $null,
[Parameter(ParameterSetName="all")]
[switch]$all,
[Switch]$force,
[string]$basePath = "c:\gitlab",
[string]$token= "secret-token",
[string]$apiUrl = "https://git.server.url/api/v4/projects"
)
# Begin script
$ErrorActionPreference = "Stop"
# Accept older TLS versions
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
# Get the ID and security principal of the current user account
# Check to see if we are currently running "as Administrator"
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (-not $myWindowsPrincipal.IsInRole($adminRole)){
Write-host "This script needs to be run As Admin";
exit;
}
# Set API url from input arguments
if($all.IsPresent) {
$url = $apiUrl + "?per_page=500"
} elseif($ProjectID -ne -1) {
$url = $apiUrl+"/"+$ProjectID
}elseif( $projectName -ne $null) {
$url = $apiUrl + "?search=" +$projectName
}
# Call API
try {
write-host "Calling url '$url'"
$projects = (Invoke-WebRequest $url -Headers @{"Private-Token"=$token} ).content | ConvertFrom-Json
}
catch [System.Net.WebException] {
if($_.Exception.Response.StatusCode.value__ -eq 404) {
write-host "Project with id '$ProjectID' not found!"
} else {
write-host $_.Exception.Message
}
exit
}
# Verify result
if($projects -is [array] -and $projects.count -le 0) {
write-host "Search for '$projectName' returned no projects!"
exit;
}
# Process each project
$projects | ForEach-Object {
if($_.empty_repo -or $_.archived) {
Write-host "Skipping empty/archived repository '$name'"
return;
}
$name = $_.name
$namespace= $_.path_with_namespace.Replace('`\','/')
$url = $_.ssh_url_to_repo
$destination = join-path $basePath $namespace
if( (Test-Path $destination) ) {
if(-not $force.IsPresent) {
$yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', "Delete directory"
$no = New-Object System.Management.Automation.Host.ChoiceDescription '&No', "Keep directory and skipp cloning"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice("Destination directory '$destination' already exists.", 'Would you like delete and continue with clone?', $options, 0)
if ($result -eq 0) {
Remove-Item $destination -Recurse -Force | out-null
} else {
write-host "Cloning of repository '$name' skipped.`n"
return;
}
} else {
Remove-Item $destination -Recurse -Force | out-null
}
}
write-host "Cloning '$name' into '$destination'...." -NoNewline
git clone $url $destination -q;
write-host "Done!"
$currentBranch = git -C $destination rev-parse --abbrev-ref HEAD
git -C $destination branch -r | ForEach-Object {
if( $_ -match "^\s*([a-zA-Z\/]*)$") {
$branch = $_.replace("origin/","").Trim();
if($branch -ne $currentBranch) {
git -C $destination branch --track $branch origin/$branch
} else {
write-host "Branch '$currentBranch' set up to track remote branch '$branch' from 'origin'."
}
}
}
git -C $destination fetch --all -q
write-host "Current branch is $currentBranch`n"
}
#EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment